It doesnât have to be a template that you pass to a script, I know you can pass objects (entity types) to a script. It would be great if you could overload them like in C++ and have several versions of scripts with the same names that accept different types of objects and the right script would be run depending upon the type of the object passed, but I am sure overloading isnât possible here. Maybe you can use more than one script, or one script which would take a large number of parameters (every object type that you would need) and when called, call it only with one object and leave all the others as null when you pass them and then in the script your code would check to see which is null?
I had a scenario where I was doing the same kind of thing in a gazillion different automations and so after a lot of struggle figured out how to pass three different objects to a script. After the huge struggle to figure it out the many hours of testing and retesting to get it right was much more time than it took to even write those automations, but of course once I had it working I had to go back to all my automations and have them call the script instead. I have maybe 50 automations calling that one script. Not sure if it was worth the effort, and there is no way I can change the script now without breaking all of those automations (!!!) but I do it because I love programming.
Anyway hereâs my scenario. I have many automations that are launched by motion detectors to turn on lights in different rooms. The paradigm I use is if motion is detected, just (re)start a dedicated timer (in the example below the timer is named âdining_room_chandelier_timerâ). Another automation turns on the light when the timer (re)starts, and a third automation turns the light off when the timer finishes. Therefore I had as helpers an input_number that was the duration of the timer (so I can adjust those with sliders in the dashboard - in the example below it is called âdining_room_adjust_chandelier_timerâ), the related timer for the scenario just described for that specific light (âdining_room_chandelier_timerâ), and whether or not the specific automation is âEnabledâ (I have input_select helpers with two values, âEnabledâ and âDisabledâ which I use as drop downs in my dashboard to 'enable or disable automations (named âdining_room_chandelier_automation_isâ in the below example). The automations are not actually disabled, I just rely upon the value of the input_select in all of my code to do or not do things so that is essentially the same result (!)))
So for many of these automations they do the same thing, but each have a separate timer, and separate input_number and separate input_select helpers. So in trying to remove redundant code all over the place I created one script which would accept a timer object and the two helper objects, and that one single script is called from many different automations all over the place. Now that I know how to do this I need to look through my automations and see what else that might be redundant can call another generic script.
I also ran into a scenario where if someone turned a light off manually and then walked out of the room, the motion detector would sense the motion and the lights would immediately go back on again before the person was able to even get out of the room. So I added a bunch more code to only turn the lights back on if they had not been turned off MANUALLY within the last 5 minutes (and code of course to set the exact current time whenever the switch is manually turned off)). For any type of switch or light the way to detect within a condition of an automation triggered by itâs state changing to off is to use this code as the condition to save the value of when the light was manually turned off in this automation for example (note the condition which is key here):
alias: >-
Dining Room Chandelier Turned Off -> If Done Manually -> Set Last Manual Off
Timestamp
description: >-
If the dining room chandelier is turned off (manually), then make sure the
"last_manual_off-dining_room" timestamp is updated
trigger:
- platform: state
entity_id:
- light.dining_room_chandelier
to: "off"
condition:
- "{{ trigger.to_state.context.id != none }}"
- "{{ trigger.to_state.context.parent_id == none }}"
- "{{ trigger.to_state.context.user_id == none }}"
action:
- service: input_text.set_value
data:
value: "{{ as_timestamp(now()) }}"
target:
entity_id: input_text.last_manual_off_dining_room
mode: parallel
max: 1000
Works like a charm. (Hence the âlast_manual_off_dining_roomâ input helper (which is a text instead of a datetime because of a bug at the time in the datetime helper, but all of this is a story for another time, letâs stick to your question about passing objects to scripts.)
So this automation for example calls the script with the three objects mentioned previously. Look at the end of the automation to see how it calls the script - (in the âactionâ section):
alias: >-
Dining Room Motion Detected (Chandelier Automation - if not switched off
manually within last 5 minutes)
description: ""
trigger:
- type: motion
platform: device
device_id: bb102cf7fbd20ffd14ac00fe56682ca4
entity_id: binary_sensor.dining_room_motion_sensor_motion
domain: binary_sensor
condition:
- condition: template
value_template: >-
{{ (float(as_timestamp(now())) -
float(states('input_text.last_manual_off_dining_room'),0)) > 300 }}
action:
- service: script.motion_detected
data:
enablement_input_selector_entity: input_select.dining_room_chandelier_automation_is
timer_duration_entity: input_number.dining_room_adjust_chandelier_timer
timer_entity: timer.dining_room_chandelier_timer
mode: parallel
And those objects shown as âdataâ in the above action section (enablement_input_selector_entity, timer_duration_entity, timer_entity) at the end of the automation code, get passed as above, to this script:
alias: Motion Detected
sequence:
- condition: template
value_template: "{{ is_state(enablement_input_selector_entity,'Enabled') }}"
- service: timer.start
data:
duration: "{{ (states(timer_duration_entity)|int*60) }}"
target:
entity_id: "{{ timer_entity }}"
mode: parallel
max: 1000
icon: mdi:run-fast
Hope that helps! Let me know if you can figure out how to overload scripts so one can take a variety of objects (entity types?)!
The key here might be if there is a way to create your own entity type and pass that all over the place. Now THAT would be very useful!
Thoughts?