Has anyone started to work on a card for Xiaomi Vacuum cleaner, I´m unfortunately a total noob. But would be nice to have a nice looking card for the Xiaomi Vacuum cleaner.
Nice thanks
Nice work, thx!
I modify a little bit of it. And I integrated my scheduling. That’s how it turned out.
Oh looks cool!
Could you please share config?
I am trying to create something similar except with realtime map from vacuum instead of static image in background.
ui-lovelace.yaml
- icon: mdi:robot-vacuum
id: vacuum
title: Robika
cards:
- type: vertical-stack
cards:
- type: picture-elements
image: /local/house/vacuum_card.jpg
elements:
- type: icon
icon: mdi:bell-ring
tap_action: call-service
entity: vacuum.xiaomi_vacuum_cleaner
service: vacuum.locate
style:
top: 90%
left: 65%
"--paper-item-icon-color": rgb(115, 122, 130)
- type: icon
tap_action: call-service
icon: mdi:home
entity: vacuum.xiaomi_vacuum_cleaner
service: vacuum.return_to_base
style:
top: 90%
left: 55%
"--paper-item-icon-color": rgb(115, 122, 130)
- type: icon
icon: mdi:play
tap_action: call-service
entity: vacuum.xiaomi_vacuum_cleaner
service: vacuum.start
style:
top: 90%
left: 45%
"--paper-item-icon-color": rgb(115, 122, 130)
- type: icon
icon: mdi:stop
tap_action: call-service
entity: vacuum.xiaomi_vacuum_cleaner
service: vacuum.stop
style:
top: 90%
left: 35%
"--paper-item-icon-color": rgb(115, 122, 130)
- type: state-label
entity: sensor.vacuum_operation
style:
top: 10%
left: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-color: rgb(34, 154, 210)
background-color: rgb(54, 65, 78)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_accessories
style:
top: 10%
right: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-color: rgb(34, 154, 210)
background-color: rgb(54, 65, 78)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_main_brush
style:
top: 30%
right: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-right-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_side_brush
style:
top: 45%
right: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-right-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_filter
style:
top: 60%
right: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-right-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_sensor
style:
top: 75%
right: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-right-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_status
style:
top: 30%
left: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-left-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_battery
style:
top: 45%
left: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-left-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_weekdays
style:
top: 75%
left: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-left-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: state-label
entity: sensor.vacuum_weekend
style:
top: 60%
left: 1%
color: rgb(255, 255, 255)
transform: translate(0%,-50%)
pointer-events: none
text-shadow: 1px 1px black
font-family: Trebuchet MS
font-size: 90%
font-weight: bold
border-left-style: solid
border-color: rgb(34, 154, 210)
opacity: 0.8
- type: image
entity: automation.takaritas_utemezese_hetkoznap
tap_action: toggle
image: /local/house/timer-off.png
state_image:
'on': /local/house/timer.png
state_filter:
'on': brightness(200%) saturate(1.8)
'off': brightness(80%) saturate(0.8)
style:
top: 75%
left: 25%
- type: image
entity: automation.takaritas_utemezese_hetvegen
tap_action: toggle
image: /local/house/timer-off.png
state_image:
'on': /local/house/timer.png
state_filter:
'on': brightness(200%) saturate(1.8)
'off': brightness(80%) saturate(0.8)
style:
top: 60%
left: 22%
- type: conditional
conditions:
- entity: automation.takaritas_utemezese_hetkoznap
state: "on"
card:
type: entities
entities:
- sensor.vacuum_start_time_weekdays
- input_number.vacuum_start_hour_weekdays
- input_number.vacuum_start_minutes_weekdays
- type: conditional
conditions:
- entity: automation.takaritas_utemezese_hetvegen
state: "on"
card:
type: entities
entities:
- sensor.vacuum_start_time_weekend
- input_number.vacuum_start_hour_weekend
- input_number.vacuum_start_minutes_weekend
sensor.yaml
- platform: template
sensors:
vacuum_start_time_weekdays:
friendly_name: 'Takarítás indítási idő (Hétköznap)'
value_template: '{{ "%0.02d:%0.02d" | format(states("input_number.vacuum_start_hour_weekdays") | int, states("input_number.vacuum_start_minutes_weekdays") | int) }}'
vacuum_start_time_weekend:
friendly_name: 'Takarítás indítási idő (Hétvége)'
value_template: '{{ "%0.02d:%0.02d" | format(states("input_number.vacuum_start_hour_weekend") | int, states("input_number.vacuum_start_minutes_weekend") | int) }}'
vacuum_status:
friendly_name: "Vacuum - Status"
value_template: "Állapot: {{ states.vacuum.xiaomi_vacuum_cleaner.attributes.status }}"
vacuum_weekdays:
friendly_name: "Vacuum - Weekdays"
value_template: "Hétköznap:"
vacuum_weekend:
friendly_name: "Vacuum - Weekend"
value_template: "Hétvége:"
vacuum_battery:
friendly_name: "Vacuum - Battery"
value_template: "Akku: {{ states.vacuum.xiaomi_vacuum_cleaner.attributes.battery_level }}"
device_class: battery
unit_of_measurement: '%'
vacuum_accessories:
friendly_name: "Vacuum - Kellékek"
value_template: "KELLÉKEK ÁLLAPOTA"
vacuum_operation:
friendly_name: "Vacuum - Üzemelés"
value_template: "ÜZEMELÉS"
vacuum_main_brush:
friendly_name: "Vacuum - Fő kefe"
value_template: "Fő kefe: {{ states.vacuum.xiaomi_vacuum_cleaner.attributes.main_brush_left }} h"
vacuum_side_brush:
friendly_name: "Vacuum - Első kefe"
value_template: "Első kefe: {{ states.vacuum.xiaomi_vacuum_cleaner.attributes.side_brush_left }} h"
vacuum_filter:
friendly_name: "Vacuum - Filter"
value_template: "Filter: {{ states.vacuum.xiaomi_vacuum_cleaner.attributes.filter_left }} h"
vacuum_sensor:
friendly_name: "Vacuum - Szenzorok"
value_template: "Szenzorok: {{ states.vacuum.xiaomi_vacuum_cleaner.attributes.sensor_dirty_left }} h"
input_slider.yaml
vacuum_start_minutes_weekend:
name: Indítási perc
initial: 0
min: 0
max: 59
step: 1
mode: slider
vacuum_start_hour_weekend:
name: Indítási óra
initial: 13
min: 0
max: 23
step: 1
mode: slider
vacuum_start_minutes_weekdays:
name: Indítási perc
initial: 0
min: 0
max: 59
step: 1
mode: slider
vacuum_start_hour_weekdays:
name: Indítási óra
initial: 15
min: 0
max: 23
step: 1
mode: slider
automations.yaml
- id: cleaning_timer_weekdays
alias: Takarítás ütemezése hétköznap
trigger:
- platform: template
value_template: '{{ states.sensor.vacuum_start_time_weekdays.state == states.sensor.time.state
}}'
condition:
- condition: time
weekday:
- mon
- tue
- wed
- thu
- fri
action:
- data:
entity_id: vacuum.xiaomi_vacuum_cleaner
service: vacuum.start
- id: cleaning_timer_weekend
alias: Takarítás ütemezése hétvégén
trigger:
- platform: template
value_template: '{{ states.sensor.vacuum_start_time_weekend.state == states.sensor.time.state
}}'
condition:
- condition: time
weekday:
- sat
- sun
action:
- data:
entity_id: vacuum.xiaomi_vacuum_cleaner
service: vacuum.start
How do you put the real-time image into the background?
Thanks for sharing.
Getting real time map requires rooting of Xiaomi Vaccum. I did that following this tutorial.
And then to get map images I found Valetudo to be the easiest solution.
When that was done on vaccum itself I added HA configuration
Sensor:
- platform: rest
resource: http://192.168.0.101/api/remote/map
name: Vacuum Map URL
value_template: 'http://192.168.0.101{{ value_json.mapsrc }}'
Camera:
- platform: generic
name: Vacuum Map
still_image_url: '{{ states.sensor.vacuum_map_url.state }}'
verify_ssl: false
content_type: image/png
framerate: 1
And you can use that always updating camera in lovelace picture-elements
card or any other card that supports camera_image
a la
elements:
- type: image
entity: vacuum.servantess
camera_image: camera.vacuum_map
Hopefully I did not forget something
Dear Kejszijo, i have try your script work perfectly for basique commande but not for all
i have roborock s50 like you maybe ?
look your script in my home assistant, could you help me please to solve problem ? thank you
Hi,
Yes, I have s50 too. You need a sensor.yaml too, to see left and right informations. You must replace “vacuum.xiaomi_vacuum_cleaner” value to yours in this file, and the Vacuum informations appear.
i have copy your sensor.yaml so, i dont view where is the probleme because is the same file and you and you all information appear
here all information for my vacuum :
No i dont view nothing.
but when i click directly in Vaccum card i view all information (configuration.yaml)
My sensor.yaml create many sensor like my picture. So if you can’t see there sensors, the problem is your sensor.yaml. Do you see any errors in the log? If sensors appear, the vacuum informations appear too.
in the log i have this error :
Could not render template Vacuum Status, the state is unknown.
09:10 components/sensor/template.py (WARNING)
and it’s my template.py
> """
> Allows the creation of a sensor that breaks out state_attributes.
>
> For more details about this platform, please refer to the documentation at
> https://home-assistant.io/components/sensor.template/
> """
> import asyncio
> import logging
>
> import voluptuous as vol
>
> from homeassistant.core import callback
> from homeassistant.components.sensor import ENTITY_ID_FORMAT, PLATFORM_SCHEMA
> from homeassistant.const import (
> ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE,
> ATTR_ENTITY_ID, CONF_SENSORS)
> from homeassistant.exceptions import TemplateError
> from homeassistant.helpers.entity import Entity, async_generate_entity_id
> from homeassistant.helpers.event import async_track_state_change
> import homeassistant.helpers.config_validation as cv
>
> _LOGGER = logging.getLogger(__name__)
>
> SENSOR_SCHEMA = vol.Schema({
> vol.Required(CONF_VALUE_TEMPLATE): cv.template,
> vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
> vol.Optional(ATTR_UNIT_OF_MEASUREMENT): cv.string,
> vol.Optional(ATTR_ENTITY_ID): cv.entity_ids
> })
>
> PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
> vol.Required(CONF_SENSORS): vol.Schema({cv.slug: SENSOR_SCHEMA}),
> })
>
>
> @asyncio.coroutine
> # pylint: disable=unused-argument
> def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
> """Setup the template sensors."""
> sensors = []
>
> for device, device_config in config[CONF_SENSORS].items():
> state_template = device_config[CONF_VALUE_TEMPLATE]
> entity_ids = (device_config.get(ATTR_ENTITY_ID) or
> state_template.extract_entities())
> friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
> unit_of_measurement = device_config.get(ATTR_UNIT_OF_MEASUREMENT)
>
> state_template.hass = hass
>
> sensors.append(
> SensorTemplate(
> hass,
> device,
> friendly_name,
> unit_of_measurement,
> state_template,
> entity_ids)
> )
> if not sensors:
> _LOGGER.error("No sensors added")
> return False
>
> yield from async_add_devices(sensors, True)
> return True
>
>
> class SensorTemplate(Entity):
> """Representation of a Template Sensor."""
>
> def __init__(self, hass, device_id, friendly_name, unit_of_measurement,
> state_template, entity_ids):
> """Initialize the sensor."""
> self.hass = hass
> self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device_id,
> hass=hass)
> self._name = friendly_name
> self._unit_of_measurement = unit_of_measurement
> self._template = state_template
> self._state = None
>
> @callback
> def template_sensor_state_listener(entity, old_state, new_state):
> """Called when the target device changes state."""
> hass.async_add_job(self.async_update_ha_state, True)
>
> async_track_state_change(
> hass, entity_ids, template_sensor_state_listener)
>
> @property
> def name(self):
> """Return the name of the sensor."""
> return self._name
>
> @property
> def state(self):
> """Return the state of the sensor."""
> return self._state
>
> @property
> def unit_of_measurement(self):
> """Return the unit_of_measurement of the device."""
> return self._unit_of_measurement
>
> @property
> def should_poll(self):
> """No polling needed."""
> return False
>
> @asyncio.coroutine
> def async_update(self):
> """Update the state from the template."""
> try:
> self._state = self._template.async_render()
> except TemplateError as ex:
> if ex.args and ex.args[0].startswith(
> "UndefinedError: 'None' has no attribute"):
> # Common during HA startup - so just a warning
> _LOGGER.warning(ex)
> return
> self._state = None
> _LOGGER.error(ex)
Which HA version do you use?
@inutilis first thank you for the url sensor, it made all of the so much easier. Not sure if you have solved the live map as background, but I found a solution.
You only need two things
shell_command:
download_new_vacuum_map: "wget -O [full/path/to/hass/config]/www/vacuum_map.jpg {{ states('sensor.vacuum_map_url') }}"
automation:
- alias: save_new_vacuum_map
trigger:
platform: state
entity_id: sensor.vacuum_map_url
action:
- service: shell_command.download_new_vacuum_map
then in ui-lovelace.yaml you just set the picture-elements as:
- type: picture-elements
image: /local/vacuum_map.jpg
elements: