Hi,
I’m currently working on an automation to push schedule changes to my TRV’s.
I use a state_changed trigger combined with template conditions to monitor changes on an scheduler objects (third party integration “scheduler component”).
Problem
The states object contains a list of target entities, and could contain multiple entities, and my TRV’s follow a simple name scheme (trv_<floor>_<room>). Therefore, my first template condition looks like this (*):
{{ 'climate.trv_' | select('in',entities) }}
But: This doesn’t work. I started Testing in the dev tools template editor to check what wen’t wrong:
{{ ['abc','a','b'] | select('in','a') | list }}
{{ 'a' | select('in',['abc','a','b']) | list }}
{{ {"a":"a","b":"b","abc":"abc"} | select('in','a') | list }}
{{ 'a' | select('in',{"a":"a","b":"b","abc":"abc"}) | list }}
All of them return ['a']
, which I would expect using the eq
(aka ==
) test. Even more confusing to me, all the following will return ['a','b']
:
{{ ['abc','a','b'] | select('in','abe') | list }}
{{ 'abe' | select('in',['abc','a','b']) | list }}
{{ {"a":"a","b":"b","abc":"abc"} | select('in','abe') | list }}
{{ 'abe' | select('in',{"a":"a","b":"b","abc":"abc"}) | list }}
And I totally don’t understand what they compute there to get this result (if changing ‘abe’ to ‘babe’ ['b','a','b']
gets the result giving me atleast some hint what is done computationally but doesn’t make any sense to me).
Btw, using actuall data:
{{ 'climate.trv_' | select('in',['climate.trv_3_br']) | list }}
{{ ['climate.trv_3_br'] | select('in','climate.trv_') | list }}
result in an empty list.
Expectation
I would expect ['a','abc']
for the first example and []
for the second, as this is whats done in python
Python 3.10.8 (main, Nov 1 2022, 14:18:21) [GCC 12.2.0] on linux
...
>>> list(map(lambda i: "a" in i,["a","b","c","abc"]))
[True, False, False, True]
>>> list(filter(lambda i: "a" in i,["a","b","c","abc"]))
['a', 'abc']
>>> list(filter(lambda i: "ab" in i,["a","b","c","abc"]))
['abc']
>>> list(filter(lambda i: "abe" in i,["a","b","c","abc"]))
[]
Actually I’m expecting select as an jinja equivalent of python filter using (predefined) jinja tests as filter functions.
Question
Am I misusing/misunderstanding the filter or is this a bug in jinja?
Workaround
As a Workaround the list can be joined and the in
test can be used:
{{ 'a' in ['abc','a','b'] | join(' ') }}
As @123 pointed out the (HA custom) match
test can be used as a replacement.
Othen then in his snipped the list needs to be first and the regex in the select statement.
{{ ['abc','a','b'] | select('match','.*a.*') | list | length > 0 }}
My actual automation
As someone might ask/would like to see:
alias: TRV schedule update
description: Programm schedule to be executed on the TRV it self
trigger:
- platform: event
event_type: state_changed
context:
user_id:
- 036d3eeafc754998bc5a0b28848c1489
condition:
- condition: template
value_template: "{{ 'climate.trv_' in trigger.event.data.new_state.attributes.entities | join(' ') }}"
- condition: template
value_template: "{{ trigger.event.data.new_state.state == 'on' }}"
- condition: template
value_template: "{{ trigger.event.data.old_state.state == 'off' }}"
action:
- service: switch.turn_off
data:
entity_id: "{{ trigger.event.data.entity_id }}"
- alias: Populate variables
variables:
attrib: "{{ trigger.event.data.new_state.attributes }}"
weekdaytranslate: {'mon':'monday','tue':'tuesday','wed':'wednesday','thu':'thursday','fri':'friday','sat':'saturday','sun':'sunday'}
- variables:
attrib_times: "{{ attrib.timeslots|map('truncate',5,end='')|list }}"
attrib_temp: "{{ attrib.actions | map(attribute='data.temperature') | list }}"
- alias: Publish message for-each entity
repeat:
for_each: "{{ attrib.entities }}"
sequence:
- alias: Preserve iter
variables:
outer: "{{ repeat }}"
- alias: Publish message for-each day
repeat:
for_each: "{{ attrib.weekdays }}"
sequence:
- service: mqtt.publish
data:
topic: testzigbee2mqtt/{{ outer.item[8:] | upper }}/set
payload: >-
{ "{{ weekdaytranslate[repeat.item] }}": { {% for i in range(9) -%}
"{{ weekdaytranslate[repeat.item] }}_temp_{{i+1}}": "{{ attrib_temp[i] | default(min(attrib_temp)) }}","{{ weekdaytranslate[repeat.item] }}_hour_{{i+1}}": "{{ today_at(attrib_times[i] | default("00:00")).hour }}","{{ weekdaytranslate[repeat.item] }}_minute_{{i+1}}": "{{ today_at(attrib_times[i] | default("00:00")).minute }}"{{ ',' if not loop.last else '' }}
{%- endfor %}}}
mode: queued
max: 10
Please keep in mind, this is pretty much work in progress.
Best regards,
Markus
(*) Example is shortend for better readability