I looked for a good way to allow for easy room cleaning. I did not like the hardcoded rooms most solutions called for. Unfortunately, the action to get the room numbers is not easily suited to find a segment based on the room name.
So I created a sensor that calls the action to get the map and reverses the loopup so you can find segment numbers. I also created a select entity that allows you to pick a room on the current floor. Then I created a script to use these.
Note that the room select entity does not survive a restart. It does have a default list: if it can find the default for a floor it will set that. I did that because normally my robot only does my bedroom. When you adjust the defaults, always make sure you have an “All” selection at the end of the defaults list.
The sensors (goes in template.yaml):
- trigger:
- trigger: homeassistant
event: start
- trigger: state
entity_id: select.dusty_selected_map
from:
- unavailable
- unknown
not_to:
- unavailable
- unknown
action:
- action: roborock.get_maps
target:
entity_id: vacuum.dusty
data: {}
response_variable: maps
sensor:
- name: "dusty roomnumbers"
unique_id: sensor.dusty_roomnumbers
icon: mdi:floor-plan
state: "{{ 'OK' if maps else 'unavailable' }}"
attributes:
rooms: |
{%- set ns = namespace(floors='{')-%}
{%- for floor in maps['vacuum.dusty'].maps -%}
{% set ns.rooms = '{ "flag":' + floor.flag | string %}
{%- for room in floor.rooms %}
{%- set ns.rooms = ns.rooms + ', ' + '"' + floor.rooms[room] + '": ' + room | string -%}
{%-endfor-%}
{%- set ns.floors = ns.floors + ('' if ns.floors=='{' else ',') +
'"' + floor.name + '": ' + ns.rooms + '}' -%}
{%-endfor%}
{{ (ns.floors + '}') | from_json }}
- trigger:
- trigger: state
id: state
entity_id:
- sensor.dusty_roomnumbers
- select.dusty_selected_map
- trigger: event
id: pick
event_type: dusty_room_picked
- trigger: event
id: "reload"
event_type: event_template_reloaded
action:
variables:
defaults: ['Bedroom', 'All']
select:
- name: "dusty room"
icon: mdi:location-enter
unique_id: sensor.dusty_room
options: |
{%- if has_value('select.dusty_selected_map') and has_value('sensor.dusty_roomnumbers') -%}
{%- set rooms = state_attr('sensor.dusty_roomnumbers','rooms') | default([]) -%}
{%- set selected = states('select.dusty_selected_map') | default('') -%}
{{ [defaults | last] + rooms.get(selected,[]) | reject('eq','flag') | list }}
{%- else -%}
{{ [defaults | last] }}
{%- endif -%}
state: |
{%- if trigger is defined and trigger and trigger.id == 'pick' -%}
{%- set cur = trigger.event.data.option -%}
{%- elif trigger is defined and trigger and trigger.id == 'state' and
trigger.entity_id == 'select.dusty_selected_map' -%}
{%- set cur = None -%}
{%- else -%}
{%- set cur = states('select.dusty_room') -%}
{%- endif -%}
{%- if has_value('select.dusty_selected_map') and has_value('sensor.dusty_roomnumbers') -%}
{%- set rooms = state_attr('sensor.dusty_roomnumbers','rooms') | default([]) -%}
{%- set selected = states('select.dusty_selected_map') | default('') -%}
{%- if selected in rooms -%}
{%- set options = [defaults | last] + rooms.get(selected,[]) | reject('eq','flag') | list -%}
{%- else -%}
{%- set options = [defaults | last] -%}
{%- endif -%}
{%- set cur = cur if cur in options else defaults | select("in", options) | first() -%}
{{ cur if cur in options else defaults | last }}
{%- else -%}
{{ defaults | last if cur in ['unavailable','unknown'] else cur }}
{%- endif -%}
select_option:
- event: dusty_room_picked
event_data:
option: "{{ option }}"
optimistic: true
The script (goes in scripts.yaml):
alias: Start dusty
variables:
rooms: "{{ state_attr('sensor.dusty_roomnumbers','rooms') }}"
floor: "{{states('select.dusty_selected_map') }}"
room: "{{ states('select.dusty_room') }}"
segments: "{{ [rooms[floor][room]] | reject('eq', Undefined) | list }}"
sequence:
- if:
- condition: template
value_template: "{{ segments | length == 0 }}"
then:
- action: vacuum.start
metadata: {}
data: {}
target:
entity_id: vacuum.dusty
else:
- action: vacuum.send_command
data:
command: app_segment_clean
params:
- segments: "{{ segments }}"
repeat: 1
target:
entity_id: vacuum.dusty
mode: single
icon: mdi:robot-vacuum-variant