jchh
((not John))
August 7, 2024, 1:12pm
1
Hi,
I’ve written this automation to try and generate a list off entity_id
’s in the trigger. Needless to say it doesn’t work.
automation:
- alias: 'Lights: Movement in hallway'
id: "lights_hallway_movement"
mode: queued
trigger:
- platform: state
entity_id: binary_sensor.hallway_motion_occupancy
to: "on"
id: "motion"
- platform: state
entity_id: >
{% set trigger = 'hallway_motion_occupancy' %}
- {{ states.binary_sensor
| selectattr('entity_id','match','.*_motion_occupancy')
| rejectattr('entity_id','match','binary_sensor.'~trigger)
| rejectattr('entity_id','search','patio')
| rejectattr('entity_id','search','front')
| map(attribute='entity_id')
| list
| join('\n- ')
}}
to: "on"
id: "cancel"
action:
[...]
It certainly looks like a list of entity_id
s when I do this in settings ➜ template:
I realise result type: string
isn’t helping, but removing both join()
& the preceding -
to create a list doesn’t work either.
My logs doesn’t really tell me why it is failing only that it:
failed to setup triggers and has been disabled: Entity {% set trigger = ‘study_motion_occupancy’ %} {{ states.binary_sensor | selectattr(‘entity_id’ is neither a valid entity ID nor a valid UUID for dictionary value @ data[‘entity_id’]. Got None
Is this possible and, if so, what am I doing wrong?
123
(Taras)
August 7, 2024, 1:20pm
2
The State Trigger doesn’t support templates. Consider using a Template Trigger.
1 Like
jchh
((not John))
August 7, 2024, 1:50pm
3
thanks - good to know that I wasn’t going completely mad!
1 Like
123
(Taras)
August 7, 2024, 1:52pm
4
No worries, it’s a common assumption. It would be handy if a State Trigger’s entity_id
option supported templates but it currently doesn’t.
NOTE
Even if it did support templates, what you created still wouldn’t work.
Your template produces a list in YAML format . Don’t use templates to generate YAML code in triggers, Template Sensors, etc.
This would be the acceptable way to generate a list:
{% set trigger = 'hallway_motion_occupancy' %}
{{ states.binary_sensor
| selectattr('entity_id','match','.*_motion_occupancy')
| rejectattr('entity_id','match','binary_sensor.'~trigger)
| rejectattr('entity_id','search','patio')
| rejectattr('entity_id','search','front')
| map(attribute='entity_id')
| list }}
1 Like
This reminded me a related question:
Consider these different triggers:
- platform: state
entity_id:
- binary_sensor.xxx_1
- binary_sensor.xxx_2
- binary_sensor.xxx_3
to: on
- platform: template
value_template: >-
{{ states.binary_sensor |
selectattr('entity_id','search','binary_sensor.xxx_') |
selectattr('state','==','on') |
list | count > 0 }}
Which trigger consumes more CPU time?
jchh
((not John))
August 7, 2024, 2:05pm
6
thanks!
I was trying the following as you posted
{% set trigger = 'study_motion_occupancy' %}
{{ states.binary_sensor
| selectattr('entity_id','match','.*_motion_occupancy')
| rejectattr('entity_id','match','binary_sensor.'~trigger)
| rejectattr('entity_id','search','patio')
| rejectattr('entity_id','search','front')
| rejectattr('state','eq','off')
| list
| count
}}
jchh
((not John))
August 7, 2024, 2:07pm
7
It’s a good question - I imagine the template one consumes more, but I don’t know for sure.
My rational for using the template is that it’s more ‘future proof’ (for when if I add more motion sensors and forget to update this particular automation). Also, I have several like this and was thinking of turning it into a blueprint.
123
(Taras)
August 7, 2024, 2:35pm
8
Here’s how a Template Trigger is triggered:
So your template will trigger when the count changes from 0 to a positive integer (like 1). Any additional changes involving positive numbers will not serve to trigger it again. The count must first return to 0 and then change to a positive integer in order to trigger it. Any positive number is considered to be true
and it must first change back to false
(0) before it can be triggered again.
Example:
Assume all motion sensors are off.
Now one motion sensor turns on. It will trigger the automation because the count changes from 0 to 1.
While the motion sensor is still reporting on
, a second motion sensor turns on.
The count changes from 1 to 2 but it won’t serve to trigger the Template Trigger again.
FWIW, petro has submitted a PR that would provide the Template Trigger with an option to trigger whenever its template’s result changes.
home-assistant:dev
← Petro31:value-template-trigger
opened 04:53PM - 07 Jul 24 UTC
<!--
You are amazing! Thanks for contributing to our project!
Please, DO N… OT DELETE ANY TEXT from this template! (unless instructed).
-->
## Proposed change
<!--
Describe the big picture of your changes here to communicate to the
maintainers why we should accept this pull request. If it fixes a bug
or resolves a feature request, be sure to link to that issue in the
additional information section.
-->
Currently, template triggers only trigger when the template previously renders `false` and then renders `true`. This limits template triggers and forces users to create template entities.
Adding the ability to optionally trigger off any template change opens up functionality for automations and template entities.
e.g. A user would now be able to create a trigger based template sensor where there's shared templates across states and attributes.
```
template:
- trigger:
- platform: template
value_template: "{{ label_entities('living_room') | select('is_state', 'on') | list }}"
render: True
sensor:
- name: Living Room On Entities
state: "{{ trigger.value | count }}"
attributes:
entity_id: "{{ trigger.value }}"
```
## Type of change
<!--
What type of change does your PR introduce to Home Assistant?
NOTE: Please, check only 1! box!
If your PR requires multiple boxes to be checked, you'll most likely need to
split it into multiple PRs. This makes things easier and faster to code review.
-->
- [ ] Dependency upgrade
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New integration (thank you!)
- [x] New feature (which adds functionality to an existing integration)
- [ ] Deprecation (breaking change to happen in the future)
- [ ] Breaking change (fix/feature causing existing functionality to break)
- [ ] Code quality improvements to existing code or addition of tests
## Additional information
<!--
Details are important, and help maintainers processing your PR.
Please be sure to fill out additional details, if applicable.
-->
- This PR fixes or closes issue: fixes #
- This PR is related to issue:
- Link to documentation pull request: https://github.com/home-assistant/home-assistant.io/pull/33614
## Checklist
<!--
Put an `x` in the boxes that apply. You can also fill these out after
creating the PR. If you're unsure about any of them, don't hesitate to ask.
We're here to help! This is simply a reminder of what we are going to look
for before merging your code.
-->
- [x] The code change is tested and works locally.
- [x] Local tests pass. **Your PR cannot be merged unless tests pass**
- [x] There is no commented out code in this PR.
- [x] I have followed the [development checklist][dev-checklist]
- [x] I have followed the [perfect PR recommendations][perfect-pr]
- [x] The code has been formatted using Ruff (`ruff format homeassistant tests`)
- [x] Tests have been added to verify that the new code works.
If user exposed functionality or configuration variables are added/changed:
- [x] Documentation added/updated for [www.home-assistant.io][docs-repository]
If the code communicates with devices, web services, or third-party tools:
- [ ] The [manifest file][manifest-docs] has all fields filled out correctly.
Updated and included derived files by running: `python3 -m script.hassfest`.
- [ ] New or updated dependencies have been added to `requirements_all.txt`.
Updated by running `python3 -m script.gen_requirements_all`.
- [ ] For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.
<!--
This project is very active and we have a high turnover of pull requests.
Unfortunately, the number of incoming pull requests is higher than what our
reviewers can review and merge so there is a long backlog of pull requests
waiting for review. You can help here!
By reviewing another pull request, you will help raise the code quality of
that pull request and the final review will be faster. This way the general
pace of pull request reviews will go up and your wait time will go down.
When picking a pull request to review, try to choose one that hasn't yet
been reviewed.
Thanks for helping out!
-->
To help with the load of incoming pull requests:
- [ ] I have reviewed two other [open pull requests][prs] in this repository.
[prs]: https://github.com/home-assistant/core/pulls?q=is%3Aopen+is%3Apr+-author%3A%40me+-draft%3Atrue+-label%3Awaiting-for-upstream+sort%3Acreated-desc+review%3Anone+-status%3Afailure
<!--
Thank you for contributing <3
Below, some useful links you could explore:
-->
[dev-checklist]: https://developers.home-assistant.io/docs/development_checklist/
[manifest-docs]: https://developers.home-assistant.io/docs/creating_integration_manifest/
[quality-scale]: https://developers.home-assistant.io/docs/integration_quality_scale_index/
[docs-repository]: https://github.com/home-assistant/home-assistant.io
[perfect-pr]: https://developers.home-assistant.io/docs/review-process/#creating-the-perfect-pr
All this to say that the Template Trigger you have created doesn’t replicate the behavior of a State Trigger that will trigger whenever any of its monitored entities changes state (and there’s no way to do it currently).
2 Likes
Means - this template will work ONCE when some entity changes OFF-> ON
- platform: template
value_template: >-
{{ states.binary_sensor |
selectattr('entity_id','search','binary_sensor.xxx_') |
selectattr('state','==','on') |
list | count > 0 }}
and will not be triggered again when ANOTHER entity changes OFF-> ON.
I.e. - not same functionality as
- platform: state
entity_id:
- binary_sensor.xxx_1
- binary_sensor.xxx_2
- binary_sensor.xxx_3
to: on
1 Like
jchh
((not John))
August 7, 2024, 2:52pm
11
Yes, that was what I wanted (in this instance).
Basically, this is “switch on light if you are in that room and switch it off if you are anywhere else”.
123
(Taras)
August 7, 2024, 2:57pm
12
The Template Trigger will be adequate provided this scenario is acceptable for your needs:
Person walks into bedroom, the bedroom motion sensor is turned on, automation is triggered.
While bedroom motion sensor is still reporting on
, a second person walks into kitchen, the kitchen motion sensor is turned on, automation is not triggered.
1 Like
jchh
((not John))
August 7, 2024, 4:07pm
13
Yes, that is correct. You haven’t seen the whole automation - there is a condition that input_bookean.single_occupancy is on. If off, the automation will not respond to that trigger but, instead use timers and the continued motion detection in that room. I’ll post the full automation in a minute for info.
1 Like
jchh
((not John))
August 7, 2024, 4:10pm
14
Here is the full package (but it uses some entities not defined here (eg: input_select.house_mode
).
Package
input_boolean: #----------------------------------------------------------------
hallway_light_awake:
name: Allow Hallway motion (awake)
hallway_light_asleep:
name: Allow Hallway motion (asleep)
hallway_light_triggered_by_motion:
name: Hallway light triggered by motion
input_number: #-----------------------------------------------------------------
hallway_light_awake_level:
name: Brightness (awake)
unit_of_measurement: "%"
min: 50
max: 100
step: 10
icon: mdi:brightness-percent
hallway_light_awake_time:
name: Timer (awake)
unit_of_measurement: "min"
min: 0.5
max: 5
step: 0.5
icon: mdi:timer
hallway_light_awake_warning_level:
name: Warning brightness (awake)
unit_of_measurement: "%"
min: 5
max: 30
step: 5
icon: mdi:brightness-percent
hallway_light_awake_warning_time:
name: Warning timer (awake)
unit_of_measurement: "min"
min: 0.5
max: 3
step: 0.5
icon: mdi:timer
hallway_light_asleep_time:
name: Timer (asleep)
unit_of_measurement: "min"
min: 0.5
max: 5
step: 0.5
icon: mdi:timer
input_select: #-----------------------------------------------------------------
hallway_light_level:
name: "Allow Hallway motion when light is"
icon: mdi:sunglasses
options:
- "Any"
- "Grey or less"
- "Dark or less"
- "Night"
timer: #------------------------------------------------------------------------
hallway_light:
name: Timer
icon: mdi:timer
duration: "00:02:30"
restore: true
hallway_light_warning:
name: Warning timer
icon: mdi:timer
duration: "00:02:30"
restore: true
automation: #-------------------------------------------------------------------
- alias: 'Lights: Movement in hallway'
id: "lights_hallway_movement"
mode: queued
trigger:
# activation sensor(s)
- platform: state
entity_id: binary_sensor.hallway_motion_occupancy
to: "on"
id: "motion_detected"
# cancelation sensor(s) - single_occupancy_mode
- platform: template
value_template: >
{% set trigger = 'hallway_motion_occupancy' %}
{{ states.binary_sensor
| selectattr('entity_id','match','.*_motion_occupancy')
| selectattr('state','eq','on')
| rejectattr('entity_id','match','binary_sensor.'~trigger)
| rejectattr('entity_id','search','patio')
| rejectattr('entity_id','search','front')
| list
| count > 0
}}
id: "single_occupancy_cancel"
# timers
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.hallway_light
id: "timer_finished"
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.hallway_light_warning
id: "warning_finished"
# house_mode
- platform: state
entity_id: input_select.house_mode
to: "Asleep"
id: "asleep_cancel"
condition: "{{ states('input_boolean.lux_scenes_locked') == 'off' }}"
action:
- choose:
# start ------------------------------
- conditions:
- "{{ trigger.id == 'motion_detected'}}"
- "{{ states('light.hallway') == 'off' }}"
- or: # house_mode
- and:
- "{{ states('input_select.house_mode') == 'Awake' }}"
- "{{ states('input_boolean.hallway_light_awake') == 'on' }}"
- and:
- "{{ states('input_select.house_mode') == 'Asleep' }}"
- "{{ states('input_boolean.hallway_light_asleep') == 'on' }}"
- or: # light_level
- "{{ states('input_select.hallway_light_level') == 'Any' }}"
- and:
- "{{ states('input_select.hallway_light_level') == 'Grey or less' }}"
- "{{ states('sensor.light_level') in ['Grey','Dark','Night'] }}"
- and:
- "{{ states('input_select.hallway_light_level') == 'Dark or less' }}"
- "{{ states('sensor.light_level') in ['Dark','Night'] }}"
- "{{ states('sensor.light_level') == 'Night' }}"
sequence:
- service: light.turn_on
target:
entity_id: light.hallway
data:
transition: 1
brightness_pct: "{{ iif(is_state('input_select.house_mode','Awake'),states('input_number.hallway_light_awake_level'),1) }}"
- service: input_boolean.turn_on
target:
entity_id: input_boolean.hallway_light_triggered_by_motion
# start timer if not using cancelation sensors (single-user mode)
- if: "{{ states('input_boolean.single_occupancy_mode') == 'off' }}"
then:
- service: timer.start
target:
entity_id: timer.hallway_light
data:
duration: "{{ iif(is_state('input_select.house_mode','Awake'),states('input_number.hallway_light_awake_time')|float*60,states('input_number.hallway_light_asleep_time')|float*60) }}"
# cancel warning timer (just in case - prob not needed)
- service: timer.cancel
target:
entity_id: timer.hallway_light_warning
# extend -----------------------------
- conditions:
- "{{ trigger.id == 'motion_detected'}}"
- or:
- "{{ states('timer.hallway_light') == 'active' }}"
- "{{ states('timer.hallway_light_warning') == 'active' }}"
sequence:
# light (back) to non-warning level
- service: light.turn_on
target:
entity_id: light.hallway
data:
transition: 1
brightness_pct: "{{ iif(is_state('input_select.house_mode','Awake'),states('input_number.hallway_light_awake_level'),1) }}"
# restart timer
- service: timer.start
target:
entity_id: timer.hallway_light
data:
duration: "{{ iif(is_state('input_select.house_mode','Awake'),states('input_number.hallway_light_awake_time')|float*60,states('input_number.hallway_light_asleep_time')|float*60) }}"
# cancel warning timer
- service: timer.cancel
target:
entity_id: timer.hallway_light_warning
# warning if no motion detected ----------------------------
- conditions: "{{ trigger.id == 'timer_finished'}}"
sequence:
- if: "{{ states('binary_sensor.hallway_motion_occupancy') == 'on' }}" # motion detected
then:
# restart timer
- service: timer.start
target:
entity_id: timer.hallway_light
data:
#duration: "{{ iif(is_state('input_select.house_mode','Awake'),150,30) }}"
duration: "{{ iif(is_state('input_select.house_mode','Awake'),states('input_number.hallway_light_awake_time')|float*60,states('input_number.hallway_light_asleep_time')|float*60) }}"
else:
# dim light
- service: light.turn_on
target:
entity_id: light.hallway
data:
transition: 1
brightness_pct: "{{ iif(is_state('input_select.house_mode','Awake'),states('input_number.hallway_light_awake_warning_level'),1) }}"
# start warning timer
- service: timer.start
target:
entity_id: timer.hallway_light_warning
data:
duration: "{{ iif(is_state('input_select.house_mode','Awake'),states('input_number.hallway_light_awake_warning_time')|float*60,1) }}"
# cancel / finish -----------------------------
- conditions:
- or:
- "{{ trigger.id == 'warning_finished'}}"
- "{{ trigger.id == 'asleep_cancel'}}"
- and:
- "{{ trigger.id == 'single_occupancy_cancel'}}"
- "{{ states('input_boolean.single_occupancy_mode') == 'on' }}"
- "{{ states('input_boolean.hallway_light_triggered_by_motion') == 'on' }}"
sequence:
- service: timer.cancel
target:
entity_id:
- timer.hallway_light
- timer.hallway_light_warning
- service: light.turn_off
target:
entity_id: light.hallway
data:
transition: 1
- service: input_boolean.turn_off
target:
entity_id: input_boolean.hallway_light_triggered_by_motion