Often a simple HA restart helps and the map shows up thereafter. See post #494.
I think you are right!
After several cleanups rooms appeared:
And the most important thing - I do not observe misalignment so far!
Here are some rules to provide same mutual alignment between a floorplan & a vacuum’s map:
- Do not shift a charging dock.
- Enable “Save map” feature (post).
- Do not start cleaning by a vacuum’s “hardware” button.
- Do not start cleaning by using a
vacuum.start
service. - Always start cleaning by using a “zone cleaning” (use this card) or a “segment cleaning” feature by calling this service:
service: vacuum.send_command
service_data:
entity_id: '[[SENSOR_VACUUM]]'
command: app_segment_clean
params: [2, 3, 16, 5, 17]
Room numbers may be retrieved from a vacuum’s map attributes.
Piotr, thank you again for the job!
@ 3_14
Piotr, may be you know:
is it possible to use a template for the params
option?
service: vacuum.send_command
service_data:
entity_id: '[[SENSOR_VACUUM]]'
command: app_segment_clean
params: [2, 3, 16, 5, 17]
I would like to generate the params
option dynamically dependingly on which rooms are selected for cleaning & how many passes are selected for each room.
I know that there is fantastic Vacuum Interactive Map Card - but so far I cannot integrate it to my floorplan and wanted to select rooms from UI.
Where do you want to achieve it? It should be possible to do in a script
To achieve it:
- Create 3 set of entities:
-
input_boolean
for each room - whether to add the room to the “cleaning list” or not; -
input_number
for each room - for keeping / changing room numbers (taken fromcamera
); -
input_number
for each room - for keeping counts of passes (1…3, for example).
-
Create a
group
containing theseinput_boolean
entities. -
Create template sensor:
sensor:
- platform: template
sensors:
vacuum_clean_command:
value_template: >-
{% set ns = namespace(COMMAND = "") -%}
{%- set ROOM_FLAGS = expand('group.vacuum_clean_rooms') -%}
{%- for flag in ROOM_FLAGS -%}
{%- if flag.entity_id | regex_match("input_boolean.vacuum_clean_room_", ignorecase=False) and
is_state(flag.entity_id,'on') -%}
{%- set ROOM = flag.entity_id.split("vacuum_clean_room_")[1] -%}
{%- set ROOM_NUMBER = states('input_number.vacuum_clean_room_number_' + ROOM)|int -%}
{%- set CLEAN_COUNT = states('input_number.vacuum_clean_room_count_' + ROOM)|int -%}
{%- set ROOM_NUMBER_STRING = (ROOM_NUMBER|string + ",") * CLEAN_COUNT -%}
{%- set ns.COMMAND = ns.COMMAND + ROOM_NUMBER_STRING -%}
{%- endif -%}
{%- endfor -%}
{%- set ns.COMMAND = (ns.COMMAND)[:-1] -%}
[{{ ns.COMMAND }}]
where:
-
input_boolean.vacuum_clean_room_*
- names forinput_boolean
entities; -
input_number.vacuum_clean_room_number_*
- names for room numbers; -
input_number.vacuum_clean_room_count_*
- names for counts; -
group.vacuum_clean_rooms
- name of the group.
- Create smth like this:
You make hide this card insidefold-entity-row
and expand it when needed.
So, the question is - is it possible to use smth like this:
service: vacuum.send_command
service_data:
entity_id: '[[SENSOR_VACUUM]]'
command: app_segment_clean
params: "{{ states('sensor.vacuum_clean_command') }}"
Yeah, it should be possible to do in a script:
vacuum_rooms:
sequence:
- service: vacuum.send_command
data:
entity_id: vacuum.xiaomi
command: app_segment_clean
params: "{{ states('sensor.vacuum_clean_command') }}"
or without template sensor:
vacuum_rooms:
sequence:
- service: vacuum.send_command
data:
entity_id: vacuum.xiaomi
command: app_segment_clean
params: >-
{% set ns = namespace(COMMAND = "") -%}
{%- set ROOM_FLAGS = expand('group.vacuum_clean_rooms') -%}
{%- for flag in ROOM_FLAGS -%}
{%- if flag.entity_id | regex_match("input_boolean.vacuum_clean_room_", ignorecase=False) and
is_state(flag.entity_id,'on') -%}
{%- set ROOM = flag.entity_id.split("vacuum_clean_room_")[1] -%}
{%- set ROOM_NUMBER = states('input_number.vacuum_clean_room_number_' + ROOM)|int -%}
{%- set CLEAN_COUNT = states('input_number.vacuum_clean_room_count_' + ROOM)|int -%}
{%- set ROOM_NUMBER_STRING = (ROOM_NUMBER|string + ",") * CLEAN_COUNT -%}
{%- set ns.COMMAND = ns.COMMAND + ROOM_NUMBER_STRING -%}
{%- endif -%}
{%- endfor -%}
{%- set ns.COMMAND = (ns.COMMAND)[:-1] -%}
[{{ ns.COMMAND }}]
Great, will try it next day! Thank you!
@3_14
Piotr, is it possible to support templates for yaml config file?
I think that it would be great to switch on/off displaying rooms etc…
maybe someday
Piotr, I got some questions about your script, could you clarify?
I made a small chart of the script:
1) python_script.vacuum_send_command
send first 5 segments
if command == 'app_zoned_clean':
if `there more than 5 segments to clean`
2) Wait until `vacuum = CLEANING`
3) Wait until `vacuum != CLEANING` (waiting for completion of cleaning the first 5 segments)
4) Pause the vacuum
5) script.vacuum_send_command_multiple_zones (recursive call of the same script)
send rest of the segments
endif
endif
Questions:
- What is a format of the
params
variable? Should it be like
[1, 2, 3, 45, 67, 8]
I see that you provided some checks & parsing & cleanup to ensure that the input data format is valid.
-
Regarding the
python_script.vacuum_send_command
:
According to the script, you are passing first 5 segments to the vacuum - does it mean that the vacuum can process max 5 segments per service call? -
According to the py script definition, that
params
value (i.e. first 5 segments) will be converted to
['1', '2', '3', '45', '67']
before sending to the vacuum. Does it mean that a vacuum accepts this format only?
-
I think this line is not required for the first call:
{%- set rest = cleaned | replace(firstBatch, "") | replace("[,[", "[[") -%}
-
I think that the
firstBatch
andrest
may be defined as variables. Just a speculation, I am still learning and never used variables in scripts so far…
Well, the script has been created over a year ago and some stuff has changed in HA . Right now it should be possible to make this script simpler - I think usage of python script can be avoided.
Answers:
- Yes
- Yes, as far as I know. You can try to check it in Xiaomi Home (my vacuum doesn’t have rooms)
- Actually it should be
[1, 2, 3, 45, 67]
- Yes, it isn’t. I have left it there for consistency reasons
- Yes, the script has been created before variables in script appeared in HA
Thank you very much for your answers!
Now - about my problem.
I described my approach to generate a command for cleaning segments.
The template sensor with this code
{% set ns = namespace(COMMAND = "") -%}
{%- set ROOM_FLAGS = expand('group.vacuum_clean_rooms') -%}
{%- for flag in ROOM_FLAGS -%}
{%- if flag.entity_id | regex_match("input_boolean.vacuum_clean_room_", ignorecase=False) and
is_state(flag.entity_id,'on') -%}
{%- set ROOM = flag.entity_id.split("vacuum_clean_room_")[1] -%}
{%- set ROOM_NUMBER = states('input_number.vacuum_clean_room_number_' + ROOM)|int -%}
{%- set CLEAN_COUNT = states('input_number.vacuum_clean_room_count_' + ROOM)|int -%}
{%- set ROOM_NUMBER_STRING = (ROOM_NUMBER|string + ",") * CLEAN_COUNT -%}
{%- set ns.COMMAND = ns.COMMAND + ROOM_NUMBER_STRING -%}
{%- endif -%}
{%- endfor -%}
{%- set ns.COMMAND = (ns.COMMAND)[:-1] -%}
{{ ns.COMMAND }}
generates this output:
Note the “Result type: list” text.
But using this script
script:
vacuum_clean_rooms:
alias: 'vacuum: Clean rooms'
sequence:
- service: vacuum.send_command
data:
entity_id: vacuum.xiaomi_roborock_s50
command: app_segment_clean
params: "{{states('sensor.vacuum_clean_command')}}"
gives an error:
Unable to send command to the vacuum: {'code': -10000, 'message': 'data for segment is not a number'}
Tried to discuss this issue, no solution so far.
Using the code directly in script (w/o that template sensor like you proposed before) does not help…
I started learning your script to find answers, not succeeded so far.
Can you try using service xiaomi_miio.vacuum_clean_segment
?
service: xiaomi_miio.vacuum_clean_segment
data:
entity_id: vacuum.xiaomi_roborock_s50
segments: "{{states('sensor.vacuum_clean_command')}}"
Error message:
Failed to call service xiaomi_miio.vacuum_clean_segment. expected int for dictionary value @ data['segments']. Got None
it seems like a bug in HA template engine… So probably the only way is to launch it via python script
I haven’t played with that for a long time, but last time I checked, the segments were not “templatable”.
There is a service input_select.set_option
which accepts a list
.
A correct syntax with a template is:
service: input_select.set_options
target:
entity_id: input_select.test_input_select_templatable
data:
options: "{{['one','two','three','four']}}"
Calling a service for vacuum with the same format
entity_id: vacuum.xiaomi_roborock_s50
command: app_segment_clean
params: "{{['2','3','3']}}"
causes same error
Unable to send command to the vacuum: {'code': -10000, 'message': 'data for segment is not a number'}
I think that the problem is in the service itself - it accepts a number
, not a string
.
I tried this call:
entity_id: vacuum.xiaomi_roborock_s50
command: app_segment_clean
params: "{{[2|int,3|int,3|int]}}"
it works!!!
Soooo, maybe this will work as well?
...
{%- set ns.COMMAND = (ns.COMMAND)[:-1] -%}
{{ ns.COMMAND | from_json }}
Made this, gonna test it after completion of the started cleaning:
params: >-
{% set ns = namespace(COMMAND = "") -%}
{%- set ROOM_FLAGS = expand('group.vacuum_clean_rooms') -%}
{%- for flag in ROOM_FLAGS -%}
{%- if flag.entity_id | regex_match("input_boolean.vacuum_clean_room_", ignorecase=False) and
is_state(flag.entity_id,'on') -%}
{%- set ROOM = flag.entity_id.split("vacuum_clean_room_")[1] -%}
{%- set ROOM_NUMBER = states('input_number.vacuum_clean_room_number_' + ROOM)|int -%}
{%- set CLEAN_COUNT = states('input_number.vacuum_clean_room_count_' + ROOM)|int -%}
{%- set ROOM_NUMBER_STRING = (ROOM_NUMBER|string +"|int" + ",") * CLEAN_COUNT -%}
{%- set ns.COMMAND = ns.COMMAND + ROOM_NUMBER_STRING -%}
{%- endif -%}
{%- endfor -%}
{%- set ns.COMMAND = (ns.COMMAND)[:-1] -%}
[{{ ns.COMMAND }}]
Actually, I have never used from_json
things, need some time for testing…
Update:
Because of unknown reasons the script above did not work - same error as before…
So I went back to the previous version with this expression:
[{{ ns.COMMAND }}]
and without this expression:
+"|int"
Code:
vacuum_clean_rooms:
alias: 'vacuum: Clean rooms'
sequence:
- service: vacuum.send_command
data:
entity_id: vacuum.xiaomi_roborock_s50
command: app_segment_clean
params: >-
{% set ns = namespace(COMMAND = "") -%}
{%- set ROOM_FLAGS = expand('group.vacuum_clean_rooms') -%}
{%- for flag in ROOM_FLAGS -%}
{%- if flag.entity_id | regex_match("input_boolean.vacuum_clean_room_", ignorecase=False) and
is_state(flag.entity_id,'on') -%}
{%- set ROOM = flag.entity_id.split("vacuum_clean_room_")[1] -%}
{%- set ROOM_NUMBER = states('input_number.vacuum_clean_room_number_' + ROOM)|int -%}
{%- set CLEAN_COUNT = states('input_number.vacuum_clean_room_count_' + ROOM)|int -%}
{%- set ROOM_NUMBER_STRING = (ROOM_NUMBER|string +",") * CLEAN_COUNT -%}
{%- set ns.COMMAND = ns.COMMAND + ROOM_NUMBER_STRING -%}
{%- endif -%}
{%- endfor -%}
{%- set ns.COMMAND = (ns.COMMAND)[:-1] -%}
[{{ ns.COMMAND }}]
Probably earlier I started the script before it was actually updated in HA after correction.
So to be sure I restarted HA - and the script works!
Now everything looks OK:
expanded control panel:
expanded settings with restricted access: