This card provides a user-friendly way to fully control map-based vacuums in Home Assistant. Supported brands include Xiaomi (Roborock/Viomi/Dreame/Roidmi/Valetudo/Valetudo RE), Neato, Wyze, Roomba, Ecovacs (and probably more).
TypeScript
1,948
637 commits
updated Jun 24, 2026
This card provides a user-friendly way to fully control map-based vacuums in Home Assistant. Supported brands include Xiaomi (Roborock/Viomi/Dreame/Roidmi/Valetudo/Valetudo RE), Neato, Wyze, Roomba, Ecovacs (and probably more).
https://user-images.githubusercontent.com/6118709/140251738-7fb06e81-34b0-4bf8-b7b1-2221d0062331.mp4
Features include:
url: /hacsfiles/lovelace-xiaomi-vacuum-map-card/xiaomi-vacuum-map-card.js
type: module
xiaomi-vacuum-map-card.js file from
the latest release<ha config>/www/ directory,
e.g. /config/www/custom_lovelace/xiaomi-vacuum-map-card.jsurl: /local/custom_lovelace/xiaomi-vacuum-map-card.js
type: module
www directoryThis card contains UI configuration editor, but it is limited to only basic set of features. Its full potential can be achieved by manual yaml adjustments.
⚠️⚠️⚠️
You can use this configuration as an example: demo config (configuration used in full_demo.mp4).
⚠️⚠️⚠️
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
title | string | no | empty | Card's title |
language | string | no | autodetected | Overrides autodetected language (supported languages) |
action_handler_id | string | no | - | Enables action handling |
additional_presets | list | no | empty | A list of additional presets (e.g. with different map/vacuum) |
| All values from preset options section | ||||
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
preset_name | string | yes1 | - | Name of the preset |
entity | string | yes | - | Vacuum entity |
map_source | string | yes | - | Preset's map source |
calibration_source | object | yes2 | - | Preset's calibration source |
vacuum_platform | string | no | default | Preset's vacuum platform |
map_locked | boolean | no | false | Default state of pan/zoom |
two_finger_pan | string | no | false | Enables two finger map panning |
icons | list | no | autogenerated | Preset's icons |
append_icons | boolean | no | false | Enables appending configured icons to autogenerated ones instead of replacing them |
tiles | list | no | autogenerated | Preset's tiles |
append_tiles | boolean | no | false | Enables appending configured tiles to autogenerated ones instead of replacing them |
map_modes | list | no | autogenerated | Preset's map modes |
activate | object | no | - | Service call that should be executed after clicking preset name |
activate_on_switch | boolean | no | false | Enables executing activate service call after switching map preset |
conditions | list | no | - | List of conditions that need to be (all of them) met for preset to be shown |
clean_selection_on_start | boolean | no | true | Allows to disable cleaning selection on cleanup start |
internal_variables | object | no | - | Allows to specify default values for internal variables |
1 If multiple presets are configured
2 Not mandatory when used with a platform that support a default calibration
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
camera | string | no1 | - | Entity id of map camera |
image | string | no1 | - | URL of map image |
crop | object | no | no cropping | Images cropping options |
1 Exactly one of camera or image must be provided
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
top | number | no | 0 | Image cropping value from the top (in pixels) |
bottom | number | no | 0 | Image cropping value from the bottom (in pixels) |
left | number | no | 0 | Image cropping value from the left (in pixels) |
right | number | no | 0 | Image cropping value from the right (in pixels) |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
camera | boolean | no1 | - | Enables retrieving calibration from camera defined in map_source (Xiaomi Cloud Map Extractor) |
entity | string | no1 | - | Entity with calibration returned as a state |
attribute | string | no | - | Enables usage of a configured attribute instead of state of given entity |
calibration_points | list | no1 | - | List of 3 or 4 calibration points |
identity | boolean | no1 | - | Enables using image coordinates on map (e.g. when map is used just for rooms) |
platform | string | no1 | - | Enables using a default calibration from a chosen platform (provided that it supports it) |
1 Exactly one of camera, entity, calibration_points, identity or platform must be provided
Each of calibration points must have a following structure:
vacuum: # coordinates of a point in a vacuum coordinate system
x: 25500
y: 25500
map: # coordinates of a point in a map coordinate system (can be read using e.g. Paint or Gimp)
x: 466
y: 1889
Following vacuum platforms are supported out of the box at this moment:
Xiaomi MiioRoborockhumbertogontijo/homeassistant-roborockTasshack/dreame-vacuumrand256/ValetudoREHypfer/Valetudomarotoweb/viomi SEtykarol/ViomiVacuumV8KrzysztofHajdamowicz/miio2send_commandal-one/Xiaomi MIoT (additional manual configuration required)NeatoRoombaDeebotUniverse/Deebot-4-Home-Assistantromedtino/simple-wyze-vacBenjaminPaap/home-assistant-myneatoCoderAS-ru/hass-neatsvorjohnnyh1975/ha_roomba_plusCreate a request for a new built-in platform
![]()
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
icon | string | yes | - | An icon to be displayed (mdi) |
icon_id | string | no | - | Icon ID that can be used to override the configuration |
tap_action | action | no | more-info | Action that will be triggered when an icon is tapped. Warning: use service_data instead of data |
hold_action | action | no | - | Action that will be triggered when an icon is held and released. Warning: use service_data instead of data |
double_tap_action | action | no | - | Action that will be triggered when an icon is double-tapped. Warning: use service_data instead of data |
conditions | list | no | - | List of conditions that need to be (all of them) met for an icon to be shown |
tooltip | string | no | - | Tooltip to be displayed on hoover |
order | number | no | - | Used to sort the icons |
replace_config | boolean | no | false | Marks that this icon should override the config of an already existing icon with the same icon_id |
menu_id | string | no | - | Adds this icon to the menu with given ID |
label | string | no | - | Label that should be displayed in the menu |
variables | object | no | - | Variables that should be passed to to service calls |
remove | boolean | no | false | Allows to remove specific pre-defined icon (when combined with icon_id and replace_config: true |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | yes | - | Has to be set to menu |
menu_id | string | yes | - | A menu ID |
entity | string | yes | - | Entity that should be used to generate the menu |
current_value_attribute | string | no | - | Changes the source of the selected value to given attribute |
available_values_attribute | string | yes | - | Configures an attribute that contains all available values for the menu |
icon_mapping | object | no | - | A mapping of possible entity value -> icon that should be used for the value |
value_translation_keys | object | no | - | A mapping of possible entity value -> label that should be used for the value |
tap_action | object | no | - | Action that should enable a specific value |
Examples:
select entity
type: "menu",
menu_id: "water_box_mode",
icon_id: "water_box_mode",
entity: "select.water_box_mode"
available_values_attribute: "options"
icon: "mdi:water",
icon_mapping:
off: "mdi:water-remove"
mild: "mdi:water-minus"
moderate: "mdi:water"
intense: "mdi:water-plus"
custom: "mdi:water-sync"
tap_action:
action: "call-service"
service: "select.select_option"
service_data:
option: "[[value]]"
entity_id: "[[entity_id]]"

| Key | Type | Required | Default | Description |
|---|---|---|---|---|
label | string | no | - | Label of a tile |
entity | string | no | - | Entity which should be shown on a tile |
internal_variable | string | no | - | Internal variable which should be shown on a tile |
icon | string | no | - | An icon to be displayed (mdi) |
icon_source | string | no | - | Source of an icon, e.g: vacuum.xiaomi.attributes.battery_icon |
attribute | string | no | - | Attribute that should be shown on a tile |
multiplier | number | no | - | Multiplier that should be used to calculate value shown on a tile |
precision | number | no | - | Precision that should be used to present value on a tile |
unit | string | no | - | Unit to be used |
tap_action | action | no | more-info | Action that will be triggered when a tile is tapped. Warning: use service_data instead of data |
hold_action | action | no | - | Action that will be triggered when a tile is held and released. Warning: use service_data instead of data |
double_tap_action | action | no | - | Action that will be triggered when a tile is double-tapped. Warning: use service_data instead of data |
conditions | list | no | - | List of conditions that need to be (all of them) met for a tile to be shown |
tooltip | string | no | - | Tooltip to be displayed on hoover |
translations | map | no | - | Translations that should be applied to tile's value |
tile_id | string | no | - | ID of an autogenerated tile that should be replaced with this one |
order | number | no | - | Used to sort the tiles |
replace_config | boolean | no | false | Marks that this tile should override the config of an already existing tile with the same tile_id |
variables | object | no | - | Variables that should be passed to to service calls |
remove | boolean | no | false | Allows to remove specific pre-defined tile (when combined with icon_id and replace_config: true |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
entity | string | no | - | Entity ID |
attribute | string | no | - | Attribute to use instead of entity state |
internal_variable | string | no | - | Name of internal variable to use instead of entity state |
value | string | no1 | - | Entity state/attribute has to be equal to this value |
value_not | string | no1 | - | Entity state/attribute has to be unequal to this value |
1 Exactly one of them has to be provided

| Key | Type | Required | Default | Description |
|---|---|---|---|---|
template | string | no1 | - | Map mode template to be used (supported templates) |
name | string | yes2 | - | Name of map mode |
icon | string | yes2 | - | Icon of map mode (mdi) |
selection_type | string | yes2 | - | Type of selection, one of supported ones |
service_call_schema | object | yes2 | - | Service call schema that should be used in this mode |
run_immediately | boolean | no | false | Enables calling service immediately after choosing a selection |
coordinates_rounding | boolean | no | true | Enables coordinates rounding |
max_selections | integer | no | 1 | Maximal number of selections |
repeats_type | string | no | NONE | Type of repeats inclusion, one of supported ones |
max_repeats | integer | no | 1 | Maximal value of repeats |
variables | object | no | - | Variables that should be passed to service_call_schema |
predefined_selections | list | no3 | - |
You can override any value from built-in template by providing it in your configuration
1 Not required if all parameters with (2) are provided
2 Required if template is not provided
3 Required if template is not provided and selection_type is one
of: PREDEFINED_RECTANGLE, PREDEFINED_POINT, ROOM
List of supported templates depends on selected vacuum_platform
Following selection types are supported at this moment:
MANUAL_RECTANGLE: Free-drawn rectangular zones on the map
PREDEFINED_RECTANGLE: Rectangular zones that can be selected on the map from predefined_selections
MANUAL_POINT: Point selected by clicking in an arbitrary place on the map
PREDEFINED_POINT: Point selected on the map from predefined_selections
ROOM: Identifier-based selection with free-drawn outline
MANUAL_PATH: Path selected by clicking on the map
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
service | string | yes | - | Service that should be called in a given mode |
service_data | object | no | - | Data that should be passed to service call |
target | object | no | - | Target that should be passed to service call |
evaluate_data_as_template | boolean | no | false | Enables support for jinja templates in service calls |
It is possible to use several built-in placeholders in service_data section. They will be replaced by:
[[entity_id]]: entity_id defined in preset's config[[selection]]: selection made on the map (zone, point or path)[[selection_size]]: number of selections made on the map[[selection_unwrapped]]: the same as [[selection]], but passed as string unwrapped from brackets[[repeats]]: selected number of repeats[[point_x]]: x coordinate of selected point (for MANUAL_POINT and PREDEFINED_POINT selection types)[[point_y]]: y coordinate of selected point (for MANUAL_POINT and PREDEFINED_POINT selection types)[[variables]]: a list of variables for all selectionsIt is possible to use any value from variables section (wrapped with double rectangular brackets):
variables:
test_variable: 123
service_call_schema:
service: fake.service
service_data:
var: "[[test_variable]]"
It is possible to use following modifiers in service_data section:
|[[jsonify]]: if value ends with this modifier it will be decoded as a JSON and attached to service call in
unwrapped form|[[jsonify_jinja]]: behaves in the same way as |[[jsonify]], but is executed after jinja templatingFollowing repeats types are supported at this moment:
NONE: No repeatsINTERNAL: Repeats number included in coordinates array ([25500, 25000, 26500, 26500, 2])EXTERNAL: Repeats number used as a separate attribute in service_call_schemaREPEAT: Repeats selection (repeats: 2, selection: [5,6] => [5,6,5,6])Format of data depends on selected selection_type:
PREDEFINED_RECTANGLE
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
zones | list | yes | - | List of lists containing zone's coordinates in [x,y,width,height] format (e.g. [[25500, 25000, 26500, 26500]]) |
icon | object | no | - | Icon definition |
label | object | no | - | Label definition |
variables | object | no | - | Variables that should be passed to service_call_schema |
default_state | selected/unselected | no | unselected | Default state of selection |
state_entity | entity id | no | - | Entity that should be used to store the state of selection |
See this page to check how to easily retrieve zone coordinates.
PREDEFINED_POINT
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
position | list | yes | - | Point's coordinates in [x,y] format (e.g. [25500, 25000]) |
icon | object | no | - | Icon definition |
label | object | no | - | Label definition |
variables | object | no | - | Variables that should be passed to service_call_schema |
default_state | selected/unselected | no | unselected | Default state of selection |
state_entity | entity id | no | - | Entity that should be used to store the state of selection |
See this page to check how to easily retrieve point coordinates.
ROOM
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
id | string or number | yes | - | Room's identifier |
outline | list | no | - | List of points forming an outline of a room (e.g. [[25500,25500],[26500,25500],[25500,26500]] |
icon | object | no | - | Icon definition |
label | object | no | - | Label definition |
variables | object | no | - | Variables that should be passed to service_call_schema |
default_state | selected/unselected | no | unselected | Default state of selection |
state_entity | entity id | no | - | Entity that should be used to store the state of selection (e.g. switch.bathroom) |
See this page to check how to easily create outline.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | - | An icon to be displayed (mdi) |
x | number | yes | - | X coordinate of an icon (in vacuum's coordinate system) |
y | number | yes | - | Y coordinate of an icon (in vacuum's coordinate system) |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
text | string | yes | - | Text to be displayed |
x | number | yes | - | X coordinate of a label (in vacuum's coordinate system) |
y | number | yes | - | Y coordinate of a label (in vacuum's coordinate system) |
offset_x | number | no | - | Offset that should be applied to label in X direction (in pixels) |
offset_y | number | no | - | Offset that should be applied to label in Y direction (in pixels) |
To enable handling actions you have to configure action_handler_id in Main options.
This card handles following actions:
Starts cleaning
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: cleaning.start
Set a value of internal variable
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: internal_variable.set
data:
variable: variable_1
value: "some value"
Selects next map mode
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: map_mode.next
Selects previous map mode
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: map_mode.previous
Selects a specific map mode
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: map_mode.set
data:
index: 2
Decrements a number of repeats
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: repeats.decrement
Increments a number of repeats
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: repeats.increment
Set a number of repeats
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: repeats.set
data:
value: 2
Clears current selection
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: selection.clear
Make sure to check out FAQ section in Discussions, it contains a lot of useful information
Does this card require rooted device?
No, it only utilizes features of Home Assistant.
How to create a map?
The easiest way is to use Xiaomi Cloud Map Extractor, but you can use any image (e.g., a screenshot from Mi Home/FloleVac).
Can I use image that has a perspective distortion?
Yes, you just have to provide 4 calibration points.
map_imageOld config (v1.x.x) | New config (v2.x.x) |
|---|---|
type: custom:xiaomi-vacuum-map-card
entity: vacuum.xiaomi_vacuum
map_image: '/local/custom_lovelace/xiaomi_vacuum_map_card/map.png'
calibration_points:
- vacuum:
x: 25500
y: 25500
map:
x: 466
y: 1889
- vacuum:
x: 26500
y: 26500
map:
x: 730
y: 1625
- vacuum:
x: 25500
y: 26500
map:
x: 466
y: 1625
zones:
- [[25500, 25500, 26500, 26500]]
- [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]]
|
type: custom:xiaomi-vacuum-map-card
entity: vacuum.xiaomi_vacuum
map_source:
image: '/local/custom_lovelace/xiaomi_vacuum_map_card/map.png'
calibration_source:
calibration_points:
- vacuum:
x: 25500
y: 25500
map:
x: 466
y: 1889
- vacuum:
x: 26500
y: 26500
map:
x: 730
y: 1625
- vacuum:
x: 25500
y: 26500
map:
x: 466
y: 1625
map_modes:
- template: vacuum_clean_zone
- template: vacuum_goto
- template: vacuum_clean_zone_predefined
predefined_selections:
- zones: [[25500, 25500, 26500, 26500]]
- zones: [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]]
|
map_cameraOld config (v1.x.x) | New config (v2.x.x) |
|---|---|
type: custom:xiaomi-vacuum-map-card entity: vacuum.xiaomi_vacuum map_camera: camera.xiaomi_cloud_map_extractor camera_calibration: true zones: - [[25500, 25500, 26500, 26500]] - [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]] |
type: custom:xiaomi-vacuum-map-card
entity: vacuum.xiaomi_vacuum
map_source:
camera: camera.xiaomi_cloud_map_extractor
calibration_source:
camera: true
map_modes:
- template: vacuum_clean_zone
- template: vacuum_goto
- template: vacuum_clean_zone_predefined
predefined_selections:
- zones: [[25500, 25500, 26500, 26500]]
- zones: [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]]
|
Currently, this card contains translations for following languages:
bg - Bulgarian (Български)ca - Catalan (Català)cs - Czech (Čeština)da - Danish (Dansk)de - German (Deutsch)el - Greek (Ελληνικά)en - Englishes - Spanish (Español)fi - Finnish (Suomi)fr - French (Français)he - Hebrew (עברית)hu - Hungarian (Magyar)is - Icelandic (Íslenska)it - Italian (Italiano)lv - Latvian (Latviešu)nb-NO - Norwegian Bokmål (Norsk bokmål)nl - Dutch (Nederlands)pl - Polish (Polski)pt - Portuguese (Português)pt-BR - Brazilian Portuguese (Português Brasileiro)ro - Romanian (Română)ru - Russian (Русский)sk - Slovak (Slovenčina)sv - Swedish (Svenska)tr - Turkish (Türkçe)uk - Ukrainian (Українська)zh - Chinese (中文)zh-Hant - Traditional Chinese (正體中文)I'd like to give special thanks to people who helped me with card's design and development:
If you want to support my work with a donation you can use one of the following platforms:
| Platform | Payment methods | Link | Comment |
|---|---|---|---|
| Ko-fi |
|
|
|
| buycoffee.to |
|
| |
| PayPal |
|
|
|
| Revolut |
|
|
|
552 followers · starred Feb 2026
2,980 followers · starred Aug 2019
59 followers · starred Aug 2023
7 followers · starred Apr 2023
This card provides a user-friendly way to fully control map-based vacuums in Home Assistant. Supported brands include Xiaomi (Roborock/Viomi/Dreame/Roidmi/Valetudo/Valetudo RE), Neato, Wyze, Roomba, Ecovacs (and probably more).
TypeScript
1,948
637 commits
updated Jun 24, 2026
This card provides a user-friendly way to fully control map-based vacuums in Home Assistant. Supported brands include Xiaomi (Roborock/Viomi/Dreame/Roidmi/Valetudo/Valetudo RE), Neato, Wyze, Roomba, Ecovacs (and probably more).
https://user-images.githubusercontent.com/6118709/140251738-7fb06e81-34b0-4bf8-b7b1-2221d0062331.mp4
Features include:
url: /hacsfiles/lovelace-xiaomi-vacuum-map-card/xiaomi-vacuum-map-card.js
type: module
xiaomi-vacuum-map-card.js file from
the latest release<ha config>/www/ directory,
e.g. /config/www/custom_lovelace/xiaomi-vacuum-map-card.jsurl: /local/custom_lovelace/xiaomi-vacuum-map-card.js
type: module
www directoryThis card contains UI configuration editor, but it is limited to only basic set of features. Its full potential can be achieved by manual yaml adjustments.
⚠️⚠️⚠️
You can use this configuration as an example: demo config (configuration used in full_demo.mp4).
⚠️⚠️⚠️
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
title | string | no | empty | Card's title |
language | string | no | autodetected | Overrides autodetected language (supported languages) |
action_handler_id | string | no | - | Enables action handling |
additional_presets | list | no | empty | A list of additional presets (e.g. with different map/vacuum) |
| All values from preset options section | ||||
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
preset_name | string | yes1 | - | Name of the preset |
entity | string | yes | - | Vacuum entity |
map_source | string | yes | - | Preset's map source |
calibration_source | object | yes2 | - | Preset's calibration source |
vacuum_platform | string | no | default | Preset's vacuum platform |
map_locked | boolean | no | false | Default state of pan/zoom |
two_finger_pan | string | no | false | Enables two finger map panning |
icons | list | no | autogenerated | Preset's icons |
append_icons | boolean | no | false | Enables appending configured icons to autogenerated ones instead of replacing them |
tiles | list | no | autogenerated | Preset's tiles |
append_tiles | boolean | no | false | Enables appending configured tiles to autogenerated ones instead of replacing them |
map_modes | list | no | autogenerated | Preset's map modes |
activate | object | no | - | Service call that should be executed after clicking preset name |
activate_on_switch | boolean | no | false | Enables executing activate service call after switching map preset |
conditions | list | no | - | List of conditions that need to be (all of them) met for preset to be shown |
clean_selection_on_start | boolean | no | true | Allows to disable cleaning selection on cleanup start |
internal_variables | object | no | - | Allows to specify default values for internal variables |
1 If multiple presets are configured
2 Not mandatory when used with a platform that support a default calibration
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
camera | string | no1 | - | Entity id of map camera |
image | string | no1 | - | URL of map image |
crop | object | no | no cropping | Images cropping options |
1 Exactly one of camera or image must be provided
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
top | number | no | 0 | Image cropping value from the top (in pixels) |
bottom | number | no | 0 | Image cropping value from the bottom (in pixels) |
left | number | no | 0 | Image cropping value from the left (in pixels) |
right | number | no | 0 | Image cropping value from the right (in pixels) |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
camera | boolean | no1 | - | Enables retrieving calibration from camera defined in map_source (Xiaomi Cloud Map Extractor) |
entity | string | no1 | - | Entity with calibration returned as a state |
attribute | string | no | - | Enables usage of a configured attribute instead of state of given entity |
calibration_points | list | no1 | - | List of 3 or 4 calibration points |
identity | boolean | no1 | - | Enables using image coordinates on map (e.g. when map is used just for rooms) |
platform | string | no1 | - | Enables using a default calibration from a chosen platform (provided that it supports it) |
1 Exactly one of camera, entity, calibration_points, identity or platform must be provided
Each of calibration points must have a following structure:
vacuum: # coordinates of a point in a vacuum coordinate system
x: 25500
y: 25500
map: # coordinates of a point in a map coordinate system (can be read using e.g. Paint or Gimp)
x: 466
y: 1889
Following vacuum platforms are supported out of the box at this moment:
Xiaomi MiioRoborockhumbertogontijo/homeassistant-roborockTasshack/dreame-vacuumrand256/ValetudoREHypfer/Valetudomarotoweb/viomi SEtykarol/ViomiVacuumV8KrzysztofHajdamowicz/miio2send_commandal-one/Xiaomi MIoT (additional manual configuration required)NeatoRoombaDeebotUniverse/Deebot-4-Home-Assistantromedtino/simple-wyze-vacBenjaminPaap/home-assistant-myneatoCoderAS-ru/hass-neatsvorjohnnyh1975/ha_roomba_plusCreate a request for a new built-in platform
![]()
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
icon | string | yes | - | An icon to be displayed (mdi) |
icon_id | string | no | - | Icon ID that can be used to override the configuration |
tap_action | action | no | more-info | Action that will be triggered when an icon is tapped. Warning: use service_data instead of data |
hold_action | action | no | - | Action that will be triggered when an icon is held and released. Warning: use service_data instead of data |
double_tap_action | action | no | - | Action that will be triggered when an icon is double-tapped. Warning: use service_data instead of data |
conditions | list | no | - | List of conditions that need to be (all of them) met for an icon to be shown |
tooltip | string | no | - | Tooltip to be displayed on hoover |
order | number | no | - | Used to sort the icons |
replace_config | boolean | no | false | Marks that this icon should override the config of an already existing icon with the same icon_id |
menu_id | string | no | - | Adds this icon to the menu with given ID |
label | string | no | - | Label that should be displayed in the menu |
variables | object | no | - | Variables that should be passed to to service calls |
remove | boolean | no | false | Allows to remove specific pre-defined icon (when combined with icon_id and replace_config: true |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | yes | - | Has to be set to menu |
menu_id | string | yes | - | A menu ID |
entity | string | yes | - | Entity that should be used to generate the menu |
current_value_attribute | string | no | - | Changes the source of the selected value to given attribute |
available_values_attribute | string | yes | - | Configures an attribute that contains all available values for the menu |
icon_mapping | object | no | - | A mapping of possible entity value -> icon that should be used for the value |
value_translation_keys | object | no | - | A mapping of possible entity value -> label that should be used for the value |
tap_action | object | no | - | Action that should enable a specific value |
Examples:
select entity
type: "menu",
menu_id: "water_box_mode",
icon_id: "water_box_mode",
entity: "select.water_box_mode"
available_values_attribute: "options"
icon: "mdi:water",
icon_mapping:
off: "mdi:water-remove"
mild: "mdi:water-minus"
moderate: "mdi:water"
intense: "mdi:water-plus"
custom: "mdi:water-sync"
tap_action:
action: "call-service"
service: "select.select_option"
service_data:
option: "[[value]]"
entity_id: "[[entity_id]]"

| Key | Type | Required | Default | Description |
|---|---|---|---|---|
label | string | no | - | Label of a tile |
entity | string | no | - | Entity which should be shown on a tile |
internal_variable | string | no | - | Internal variable which should be shown on a tile |
icon | string | no | - | An icon to be displayed (mdi) |
icon_source | string | no | - | Source of an icon, e.g: vacuum.xiaomi.attributes.battery_icon |
attribute | string | no | - | Attribute that should be shown on a tile |
multiplier | number | no | - | Multiplier that should be used to calculate value shown on a tile |
precision | number | no | - | Precision that should be used to present value on a tile |
unit | string | no | - | Unit to be used |
tap_action | action | no | more-info | Action that will be triggered when a tile is tapped. Warning: use service_data instead of data |
hold_action | action | no | - | Action that will be triggered when a tile is held and released. Warning: use service_data instead of data |
double_tap_action | action | no | - | Action that will be triggered when a tile is double-tapped. Warning: use service_data instead of data |
conditions | list | no | - | List of conditions that need to be (all of them) met for a tile to be shown |
tooltip | string | no | - | Tooltip to be displayed on hoover |
translations | map | no | - | Translations that should be applied to tile's value |
tile_id | string | no | - | ID of an autogenerated tile that should be replaced with this one |
order | number | no | - | Used to sort the tiles |
replace_config | boolean | no | false | Marks that this tile should override the config of an already existing tile with the same tile_id |
variables | object | no | - | Variables that should be passed to to service calls |
remove | boolean | no | false | Allows to remove specific pre-defined tile (when combined with icon_id and replace_config: true |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
entity | string | no | - | Entity ID |
attribute | string | no | - | Attribute to use instead of entity state |
internal_variable | string | no | - | Name of internal variable to use instead of entity state |
value | string | no1 | - | Entity state/attribute has to be equal to this value |
value_not | string | no1 | - | Entity state/attribute has to be unequal to this value |
1 Exactly one of them has to be provided

| Key | Type | Required | Default | Description |
|---|---|---|---|---|
template | string | no1 | - | Map mode template to be used (supported templates) |
name | string | yes2 | - | Name of map mode |
icon | string | yes2 | - | Icon of map mode (mdi) |
selection_type | string | yes2 | - | Type of selection, one of supported ones |
service_call_schema | object | yes2 | - | Service call schema that should be used in this mode |
run_immediately | boolean | no | false | Enables calling service immediately after choosing a selection |
coordinates_rounding | boolean | no | true | Enables coordinates rounding |
max_selections | integer | no | 1 | Maximal number of selections |
repeats_type | string | no | NONE | Type of repeats inclusion, one of supported ones |
max_repeats | integer | no | 1 | Maximal value of repeats |
variables | object | no | - | Variables that should be passed to service_call_schema |
predefined_selections | list | no3 | - |
You can override any value from built-in template by providing it in your configuration
1 Not required if all parameters with (2) are provided
2 Required if template is not provided
3 Required if template is not provided and selection_type is one
of: PREDEFINED_RECTANGLE, PREDEFINED_POINT, ROOM
List of supported templates depends on selected vacuum_platform
Following selection types are supported at this moment:
MANUAL_RECTANGLE: Free-drawn rectangular zones on the map
PREDEFINED_RECTANGLE: Rectangular zones that can be selected on the map from predefined_selections
MANUAL_POINT: Point selected by clicking in an arbitrary place on the map
PREDEFINED_POINT: Point selected on the map from predefined_selections
ROOM: Identifier-based selection with free-drawn outline
MANUAL_PATH: Path selected by clicking on the map
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
service | string | yes | - | Service that should be called in a given mode |
service_data | object | no | - | Data that should be passed to service call |
target | object | no | - | Target that should be passed to service call |
evaluate_data_as_template | boolean | no | false | Enables support for jinja templates in service calls |
It is possible to use several built-in placeholders in service_data section. They will be replaced by:
[[entity_id]]: entity_id defined in preset's config[[selection]]: selection made on the map (zone, point or path)[[selection_size]]: number of selections made on the map[[selection_unwrapped]]: the same as [[selection]], but passed as string unwrapped from brackets[[repeats]]: selected number of repeats[[point_x]]: x coordinate of selected point (for MANUAL_POINT and PREDEFINED_POINT selection types)[[point_y]]: y coordinate of selected point (for MANUAL_POINT and PREDEFINED_POINT selection types)[[variables]]: a list of variables for all selectionsIt is possible to use any value from variables section (wrapped with double rectangular brackets):
variables:
test_variable: 123
service_call_schema:
service: fake.service
service_data:
var: "[[test_variable]]"
It is possible to use following modifiers in service_data section:
|[[jsonify]]: if value ends with this modifier it will be decoded as a JSON and attached to service call in
unwrapped form|[[jsonify_jinja]]: behaves in the same way as |[[jsonify]], but is executed after jinja templatingFollowing repeats types are supported at this moment:
NONE: No repeatsINTERNAL: Repeats number included in coordinates array ([25500, 25000, 26500, 26500, 2])EXTERNAL: Repeats number used as a separate attribute in service_call_schemaREPEAT: Repeats selection (repeats: 2, selection: [5,6] => [5,6,5,6])Format of data depends on selected selection_type:
PREDEFINED_RECTANGLE
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
zones | list | yes | - | List of lists containing zone's coordinates in [x,y,width,height] format (e.g. [[25500, 25000, 26500, 26500]]) |
icon | object | no | - | Icon definition |
label | object | no | - | Label definition |
variables | object | no | - | Variables that should be passed to service_call_schema |
default_state | selected/unselected | no | unselected | Default state of selection |
state_entity | entity id | no | - | Entity that should be used to store the state of selection |
See this page to check how to easily retrieve zone coordinates.
PREDEFINED_POINT
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
position | list | yes | - | Point's coordinates in [x,y] format (e.g. [25500, 25000]) |
icon | object | no | - | Icon definition |
label | object | no | - | Label definition |
variables | object | no | - | Variables that should be passed to service_call_schema |
default_state | selected/unselected | no | unselected | Default state of selection |
state_entity | entity id | no | - | Entity that should be used to store the state of selection |
See this page to check how to easily retrieve point coordinates.
ROOM
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
id | string or number | yes | - | Room's identifier |
outline | list | no | - | List of points forming an outline of a room (e.g. [[25500,25500],[26500,25500],[25500,26500]] |
icon | object | no | - | Icon definition |
label | object | no | - | Label definition |
variables | object | no | - | Variables that should be passed to service_call_schema |
default_state | selected/unselected | no | unselected | Default state of selection |
state_entity | entity id | no | - | Entity that should be used to store the state of selection (e.g. switch.bathroom) |
See this page to check how to easily create outline.
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | - | An icon to be displayed (mdi) |
x | number | yes | - | X coordinate of an icon (in vacuum's coordinate system) |
y | number | yes | - | Y coordinate of an icon (in vacuum's coordinate system) |
| Key | Type | Required | Default | Description |
|---|---|---|---|---|
text | string | yes | - | Text to be displayed |
x | number | yes | - | X coordinate of a label (in vacuum's coordinate system) |
y | number | yes | - | Y coordinate of a label (in vacuum's coordinate system) |
offset_x | number | no | - | Offset that should be applied to label in X direction (in pixels) |
offset_y | number | no | - | Offset that should be applied to label in Y direction (in pixels) |
To enable handling actions you have to configure action_handler_id in Main options.
This card handles following actions:
Starts cleaning
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: cleaning.start
Set a value of internal variable
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: internal_variable.set
data:
variable: variable_1
value: "some value"
Selects next map mode
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: map_mode.next
Selects previous map mode
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: map_mode.previous
Selects a specific map mode
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: map_mode.set
data:
index: 2
Decrements a number of repeats
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: repeats.decrement
Increments a number of repeats
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: repeats.increment
Set a number of repeats
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: repeats.set
data:
value: 2
Clears current selection
tap_action:
action: fire-dom-event
xiaomi_vacuum_map_card:
action_handler_id: xiaomi_vacuum_map_card_id_1
action: selection.clear
Make sure to check out FAQ section in Discussions, it contains a lot of useful information
Does this card require rooted device?
No, it only utilizes features of Home Assistant.
How to create a map?
The easiest way is to use Xiaomi Cloud Map Extractor, but you can use any image (e.g., a screenshot from Mi Home/FloleVac).
Can I use image that has a perspective distortion?
Yes, you just have to provide 4 calibration points.
map_imageOld config (v1.x.x) | New config (v2.x.x) |
|---|---|
type: custom:xiaomi-vacuum-map-card
entity: vacuum.xiaomi_vacuum
map_image: '/local/custom_lovelace/xiaomi_vacuum_map_card/map.png'
calibration_points:
- vacuum:
x: 25500
y: 25500
map:
x: 466
y: 1889
- vacuum:
x: 26500
y: 26500
map:
x: 730
y: 1625
- vacuum:
x: 25500
y: 26500
map:
x: 466
y: 1625
zones:
- [[25500, 25500, 26500, 26500]]
- [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]]
|
type: custom:xiaomi-vacuum-map-card
entity: vacuum.xiaomi_vacuum
map_source:
image: '/local/custom_lovelace/xiaomi_vacuum_map_card/map.png'
calibration_source:
calibration_points:
- vacuum:
x: 25500
y: 25500
map:
x: 466
y: 1889
- vacuum:
x: 26500
y: 26500
map:
x: 730
y: 1625
- vacuum:
x: 25500
y: 26500
map:
x: 466
y: 1625
map_modes:
- template: vacuum_clean_zone
- template: vacuum_goto
- template: vacuum_clean_zone_predefined
predefined_selections:
- zones: [[25500, 25500, 26500, 26500]]
- zones: [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]]
|
map_cameraOld config (v1.x.x) | New config (v2.x.x) |
|---|---|
type: custom:xiaomi-vacuum-map-card entity: vacuum.xiaomi_vacuum map_camera: camera.xiaomi_cloud_map_extractor camera_calibration: true zones: - [[25500, 25500, 26500, 26500]] - [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]] |
type: custom:xiaomi-vacuum-map-card
entity: vacuum.xiaomi_vacuum
map_source:
camera: camera.xiaomi_cloud_map_extractor
calibration_source:
camera: true
map_modes:
- template: vacuum_clean_zone
- template: vacuum_goto
- template: vacuum_clean_zone_predefined
predefined_selections:
- zones: [[25500, 25500, 26500, 26500]]
- zones: [[24245, 25190, 27495, 27940], [27492, 26789, 28942, 27889]]
|
Currently, this card contains translations for following languages:
bg - Bulgarian (Български)ca - Catalan (Català)cs - Czech (Čeština)da - Danish (Dansk)de - German (Deutsch)el - Greek (Ελληνικά)en - Englishes - Spanish (Español)fi - Finnish (Suomi)fr - French (Français)he - Hebrew (עברית)hu - Hungarian (Magyar)is - Icelandic (Íslenska)it - Italian (Italiano)lv - Latvian (Latviešu)nb-NO - Norwegian Bokmål (Norsk bokmål)nl - Dutch (Nederlands)pl - Polish (Polski)pt - Portuguese (Português)pt-BR - Brazilian Portuguese (Português Brasileiro)ro - Romanian (Română)ru - Russian (Русский)sk - Slovak (Slovenčina)sv - Swedish (Svenska)tr - Turkish (Türkçe)uk - Ukrainian (Українська)zh - Chinese (中文)zh-Hant - Traditional Chinese (正體中文)I'd like to give special thanks to people who helped me with card's design and development:
If you want to support my work with a donation you can use one of the following platforms:
| Platform | Payment methods | Link | Comment |
|---|---|---|---|
| Ko-fi |
|
|
|
| buycoffee.to |
|
| |
| PayPal |
|
|
|
| Revolut |
|
|
|
552 followers · starred Feb 2026
2,980 followers · starred Aug 2019
59 followers · starred Aug 2023
7 followers · starred Apr 2023