I’d like to create something like ‘generic scripts’.
So let’s say I have some heatings controlled by HA and want to have a BOOST-Mode handled by a script.
Therefore I don’t want to create a BOOST-script for each heating entity. I’d like to create a generic script, that handles the BOOST mode for every entity.
The entity_id is passed as a parameter.
thermostat_generic_boost:
alias: 'Aktiviere Boost-Modus für generisches Thermostat'
sequence:
# Turn on central heating
- service: script.heizung_boost
# Set temperature for thermostat
- service: script.thermostat_generic_update
data_template:
entity_id: '{{entity_id}}'
temperature: 30
# cancel running timers, start new timer
- service: script.turn_off
entity_id: script.thermostat_generic_boost_timer
- service: script.thermostat_generic_boost_timer
data_template:
entity_id: '{{entity_id}}'
thermostat_generic_boost_timer:
alias: 'Beende Boost-Modus für generisches Thermostat'
sequence:
- delay: 00:30:00
- service: script.thermostat_generic_auto
data_template:
entity_id: '{{entity_id}}'
If I got it right, script.turn_off turns off a running script, which then means (if its possible to run the same script n parallel times) all scripts are stopped.
In the logs I’ve found the following entry: 17-02-04 21:22:30 WARNING (MainThread) [homeassistant.components.script] Script script.thermostat_generic_boost already running.
So finally my questions are:
Is it possible to run multiple instances of a script?
If so, can I turn off a specific one or what exactly does script.turn_off?
I have all of my automations set up to send me Pushover notifications through the script above. If 2 or more automations trigger around the same time, only 1 notification comes through and the other ones cause the warning above in my log file.
See a generic timer for example. It can be activated with HASS-events.
Simply fire an event with event_data “entity_id” and “event_type” and a “duration” in seconds and the timer-script is going to fire the event after the time-out has reached.
So I active the timer in HASS by firing an event - then I listen to the event that will be fired from the timer.
def initialize(self):
self.log("Starting Scripts...")
# Global vars
self.action_timers = dict()
# Scripts can be called by firing its event identifier
self.listen_event(self.generic_event_timer, "appdaemon_generic_event_timer")
def generic_event_timer(self, event_name, data, kwargs):
# data requirements:
# - entity_id
# - event_type (to fire)
# - duration (of timer in seconds)
# - Optional: kwargs for event
def generic_timer_final_action(self, kwargs):
# Stop running timers
if kwargs['entity_id'] in self.action_timers:
self.cancel_timer(self.action_timers[kwargs['entity_id']])
self.action_timers.pop(kwargs['entity_id'], None)
# Fire given event
self.fire_event(kwargs['event_type'], **kwargs)
# Log
self.log("Generic timer ended and fired event %s for %s" % (kwargs['event_type'], kwargs['entity_id']))
# If action is passed -> do this
if 'action' in data and data['action'] == 'stop':
kwargs.update(data)
generic_timer_final_action(self, **kwargs)
# else start
else:
# Stop running timers
if data['entity_id'] in self.action_timers:
self.cancel_timer(self.action_timers[data['entity_id']])
self.action_timers.pop(data['entity_id'], None)
# Create and save new timer
kwargs.update(data)
timer = self.run_in(generic_timer_final_action, (int(data['duration'])), kwargs)
self.action_timers[kwargs['entity_id']] = timer
# Log
self.log("Generic timer created for %s" % (kwargs['entity_id']))
The only stupid thing I noticed is:
Its not possible to use data_templates for event_data in hass… So everything handled in hass must be static… (Fire Event with data_template)
For what it’s worth, it seems I found a workaround in using a python_script instead of a script. The script I shared above now looks like this:
# Get time and settings
time = hass.states.get('sensor.time').state
sending = hass.states.get('input_boolean.notify_pushover').state
default_priority = hass.states.get('input_slider.pushover_priority').state
# Get script variables
target = data.get('target') or 'xxx'
title = (data.get('title') or 'HA automation') + ' @ ' + time
message = data.get('message')
priority = data.get('priority') or default_priority
# Call service
if sending == 'on' :
data = { "target" : target, "title" : title, "message" : message , "data" : { "priority" : int(float(priority)) } }
hass.services.call('notify', 'pushover', data)
It is not an exact rewrite of the script I was using before. For example: doing import time in the Python script is not supported, therefore I cannot use time.strftime('%H:%M:%S') to get a timestamp.
So it’s not a perfect solution, but it’s a workaround I can live with to not miss any notifications.