Hello there!
I am desperate in trying to get a button working.
It should get my Roborock S5 to clean the segments I define through input_booleans
.
The button looks like this at the moment:
type: button
tap_action:
action: call-service
service: xiaomi_miio.vacuum_clean_segment
data_template:
segments: >
[{% if is_state('input_boolean.clean_room1', 'on') %}16,{% endif
%}{% if is_state('input_boolean.clean_room2', 'on') %}17,{% endif %}{% if
is_state('input_boolean.clean_room3', 'on') %}18,{% endif %}{% if
is_state('input_boolean.clean_room4', 'on') %}19,{% endif %}{% if
is_state('input_boolean.clean_room5', 'on') %}20,{% endif %}{% if
is_state('input_boolean.clean_room6', 'on') %}21,{% endif %}0]
entity_id: vacuum.borris
name: Go Borris
I can not find a proper way to debug this. I tried reading the jinja2 documentation and yaml conventions. I tried starting the “segments:
” with “|-
” to enable multiline and select the segments with “- 16
”, line-returns ("\n
") and without the “[ ]
”. I basically ended up in t’n’r (try and error) but nothing worked. Please tell me, I just did not read properly and someone can figure it out in seconds.
My shown error is: “required key not provided @ data['segments']
”
Love to hear from you soon!
Try this:
Create a group consisting of all these input_booleans, e.g. group.cleaning_booleans
Then use this template:
segments: >
{{ expand('group.cleaning_booleans')|selectattr('state','eq','on')|map(attribute='entity_id')|list }}
1 Like
What would be the expected output of this? I do not see where this could get the room-numbers from, as my actual input_booleans do not have the number in their names. And a little documentation of the used functions would be nice to actually understand what you are doing there.
I will try this anyway! Thanks for your reply
Ou, I’m sorry, totally missed that you want the room number, not the entity_id, sorry.
Two workaround that would come to my mind would be to add a custom attribute to the input booleans with customization, which has the room number, or change the friendly name of the booleans to be the room number.
It will give a list of entity_ids of all input_booleans that are on.
expand
, expands the group to get all elements.
selectattr('state', 'eq', 'on')
filters out the only the entities of the group that are on
map(attribute='entity_id')
gives you the entity_id of the filtered entities, this could be changed to friendly_name or your custom attribute, if you use one of my suggested workarounds
list
converts the string to a list
Hey, your idea sounds very promising. My only problem is that I can not find any official documentation of the “map()” function and as soon as I try anything else other than the “entity_id” my output becomes a list of “undefined”. Any suggestions or links to the doc for map() ?
I don’t think there’s any docs regarding the map in the HA docs, only in the Jinja docs (which is the template engine used in HA),e.g. here.
What did you try in the map that didn’t work?
Thanks for the information you got there!
My template looks like this right now:
segments: >
{{
expand('group.vacuum_rooms')|selectattr('state','eq','on')|map(attribute='number')|list
}}
I also tried expand('group.vacuum_rooms')|selectattr('state','eq','on')|map(attribute='friendly_name')|list
but this did not work either.
I reloaded every possible configuration. I will shortly try to reboot HA and inform about possible changes.
Nothing changed. the attribute-field does only work for the entity_id and nothing else, e.g. the friendly_name or custom attributes. Would love to see this working. Its way more compact than my attempt
Yes, you’re right. Just checked on my machine now and it didn’t work. You can get the friendly name by using map(attribute=‘name’), but the other attributes are not available.
I’m not sure whether one can get this to work with some other tricks, however, I have a different solution for you, which works with every attribute.
Try this:
segments: >
{% set ns = namespace(rooms=[]) %}
{% for s in expand('group.vacuum_rooms') if s.state == 'on' %}
{% set ns.rooms = ns.rooms + [ s.attributes.number ] %}
{% endfor %}
{{ ns.rooms }}
This loops through all the entities in the groups, checks if the state is ‘on’, if yes, the attribute number of this entity is added to the list.
You are awesome! I actually get used to the functions for future use.
But sadly my problem stil exists.
I added stripping of quotation marks and blanks to make it as close to the documentation, as possible.
And the output looks good for me. But the service-xiaomi_miiovacuum_clean_segment service does not work.
Thats my code now:
{%- set ns = namespace(rooms=[]) -%}
{%- for s in expand('group.vacuum_rooms') if s.state == 'on' -%}
{%- set ns.rooms = ns.rooms + [ s.attributes.number ] -%}
{%- endfor -%} {{ ns.rooms|replace("'", "")|replace(" ", "") }}
And the output from the developer tools is the following:
[17,18]
My desperation grows as I am learning very helpful stuff.
Thanks a lot, I appreciate your ideas!
Maybe it works when you convert them to an int before they are added to the list:
segments: >
{% set ns = namespace(rooms=[]) %}
{% for s in expand('group.vacuum_rooms') if s.state == 'on' %}
{% set ns.rooms = ns.rooms + [ s.attributes.number | int ] %}
{% endfor %}
{{ ns.rooms }}
2 Likes
Sadly the internet does not forget
The problem was solved as I marked your last post.
So the conversion to int is necessary. But the other problem was the way I was trying to start all of this.
My solution is your code plus an older post in the forum.
So I now created a script containing your code and trigger it with my button from lovelance.
It works like a charm and I am an idiot for ignoring the warnings in the GUI.
Thanks for your help. Really love this community!
1 Like
Hey Burningstone,
I actually found the solution to the problem of the map(attribute='number')
fail.
To actually get the attribute to the entity, you have to address the “attributes” attribute
So the way it works is the following:
map(attribute="attributes.number")
Encountered this while exploring jinja2 logic.
1 Like