Skip to content

Instantly share code, notes, and snippets.

@vidvisionify
Created February 3, 2022 06:59
Show Gist options
  • Save vidvisionify/d0daf4549223909795fa09de1b1b432e to your computer and use it in GitHub Desktop.
Save vidvisionify/d0daf4549223909795fa09de1b1b432e to your computer and use it in GitHub Desktop.
# ======================================================================================= #
#
# V A L E T U D O & H O M E A S S I S T A N T
#
# Phil Cooper, @ 2022 Jan 26
# Latest Major Revision: Let's begin.
#
# vidvisionify@gmail.com
# @vidvisionify
#
# ======================================================================================= #
# I was going through the Valetudo docs again after install, and I was confused by the Home Assistant integration.
# Sure, most of the functionality is there via MQTT and services, but the reccomendations in the tutorial
# suggest you edit several files.
# https://valetudo.cloud/pages/integrations/home-assistant-integration.html
#
## Why not use a package instead??
## I took several bits from the above tutorial for this, and threw in some other things I use.
## I'm no programmer, I just bodge things together in YAML. This is my personal package, YMMV
## For this package, my robot is a Dreame D9 called 'Dreame' with the entity id of 'vacuum.valetudo_d9'
## No autoempty dock here, since my robot doesn't have that.
# ======================================================================================= #
## Automation Ideas
## - Error Notifications via Phone
## - Vacuum when everyone is Away
## - Vacuum Daily
## - Return to base when people return home
## - When filters/brush low
## - Notification on phone
## - Add todoist task
## I've had issues in the past when customize-related stuff isn't at the top of a package, so we'll get that out of the way now.
## Valetudo's script wants us to add room-ids attributes to our selections, so doing that here. Check your 'map segments' sensor.
homeassistant:
customize_glob:
"sensor.dreame*":
icon: mdi:robot-vacuum
input_boolean.vacuum_livingroom:
room_id: "5"
input_boolean.vacuum_kitchen:
room_id: "6"
input_boolean.vacuum_hallway:
room_id: "4"
input_boolean.vacuum_lobby:
room_id: "1"
input_boolean.vacuum_bathroom:
room_id: "2"
input_boolean.vacuum_alex:
room_id: "3"
# Sure, Valetudo creates a sensor for the current job, but let's create sensors to track today's cleaning time, and the time for the week.
# Using these, you could make an automation to make a to-do task after X hours of cleaning.
# I honestly forgot where I got these templates from, I've used them since I had an ECOVACS Deebot.
sensor:
- platform: history_stats
name: Dreame Today
entity_id: vacuum.valetudo_d9
state: 'cleaning'
type: time
# icon: identified above in customize_glob
start: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
end: '{{ now() }}'
- platform: history_stats
name: Dreame This Week
entity_id: vacuum.valetudo_d9
state: 'cleaning'
type: time
# icon: identified above in customize_glob
start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0) ) - now().weekday() * 86400 }}'
end: '{{ now() }}'
# I also like to breakout the battery into it's own sensor.
# Probably could just use templates for that, but I use attributes-extractor instead.
# https://github.com/pilotak/homeassistant-attributes
- platform: attributes
attribute: battery_level
friendly_name: "Dreame Battery"
entities:
- vacuum.valetudo_d9
## You know, having the consumable sensors as minutes isn't great.
## Let's make new sensors with hours instead. I don't think I can set entity_ids AND names via config,
## we'll focus on IDs and customize the names later.
template:
- sensor:
- name: "valetudo_d9_main_brush_hours"
unique_id: "valetudo_d9_main_brush_hours"
unit_of_measurement: "hours"
state_class: total
icon: mdi:progress-wrench
state: >
{% set time = states.sensor.valetudo_d9_main_brush.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{{hours}}
attributes:
minutes: >
{{states.sensor.valetudo_d9_main_brush.state}}
hours: >
{% set time = states.sensor.valetudo_d9_main_brush.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{{hours}}
days: >
{% set time = states.sensor.valetudo_d9_main_brush.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{% set days = ((hours | int / 24) | string).split('.')[0] %}
{{days}}
- name: "valetudo_d9_main_filter_hours"
unique_id: "valetudo_d9_main_filter_hours"
unit_of_measurement: "hours"
state_class: total
icon: mdi:progress-wrench
state: >
{% set time = states.sensor.valetudo_d9_main_filter.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{{hours}}
attributes:
minutes: >
{{states.sensor.valetudo_d9_main_filter.state}}
hours: >
{% set time = states.sensor.valetudo_d9_main_filter.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{{hours}}
days: >
{% set time = states.sensor.valetudo_d9_main_filter.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{% set days = ((hours | int / 24) | string).split('.')[0] %}
{{days}}
- name: "valetudo_d9_right_brush_hours"
unique_id: "valetudo_d9_right_brush_hours"
unit_of_measurement: "hours"
state_class: total
icon: mdi:progress-wrench
state: >
{% set time = states.sensor.valetudo_d9_right_brush.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{{hours}}
attributes:
minutes: >
{{states.sensor.valetudo_d9_right_brush.state}}
hours: >
{% set time = states.sensor.valetudo_d9_right_brush.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{{hours}}
days: >
{% set time = states.sensor.valetudo_d9_right_brush.state %}
{% set hours = ((time | int / 60) | string).split('.')[0] %}
{% set days = ((hours | int / 24) | string).split('.')[0] %}
{{days}}
# A sensor to convert the 'Current Run' time from seconds to minutes.
# This could built upon to show hours too, but I'm bad at templates.
- name: "valetudo_d9_current_statistics_time_minutes"
unique_id: "valetudo_d9_current_statistics_time_minutes"
unit_of_measurement: "minutes"
state_class: total
icon: mdi:timer-outline
state: >
{% set uptime = (states.sensor.valetudo_d9_current_statistics_time.state | int) | int %}
{% set minutes = ((uptime / 60) % 60)| int %}
{{minutes}}
# Converting 'Current Area' to square meters
- name: "valetudo_d9_current_statistics_area_meters"
unique_id: "valetudo_d9_current_statistics_area_meters"
unit_of_measurement: "m²"
state_class: total
icon: mdi:texture-box
state: >
{% set area = (states.sensor.valetudo_d9_current_statistics_area.state | int) | int %}
{% set meters = ((area)/ 100)/100| int %}
{{meters}}
# Time to create the segment selections.
# I added 'Clean' to the friendly names, to make them easier to find later.
input_boolean:
vacuum_livingroom:
name: Clean Living Room
icon: mdi:sofa
vacuum_kitchen:
name: Clean Kitchen
icon: mdi:silverware-fork-knife
vacuum_hallway:
name: Clean Hallway
icon: mdi:foot-print
vacuum_lobby:
name: Clean Lobby
icon: mdi:popcorn
vacuum_bathroom:
name: Clean Bathroom
icon: mdi:toilet
vacuum_alex:
name: Clean Alex's Bedroom
icon: mdi:bed-empty
# One pass of my first floor only takes 30min, let's add the ability for it to run multiple times.
input_number:
vacuum_iterations:
name: Vacuum Iterations
icon: mdi:repeat
initial: 1
min: 1
max: 4
step: 1
# Grouping the segments together makes the script do things.
group:
vacuum_rooms:
name: Vacuum Rooms
entities:
- input_boolean.vacuum_livingroom
- input_boolean.vacuum_kitchen
- input_boolean.vacuum_hallway
- input_boolean.vacuum_lobby
- input_boolean.vacuum_bathroom
- input_boolean.vacuum_alex
# Time for the script that actually makes things go.
# I'm not sure why the tutorial splits this into two scripts? We can just use one template.
script:
vacuum_clean_segments:
alias: Start Cleaning
icon: mdi:robot-vacuum
mode: single
sequence:
- service: mqtt.publish
data:
# The line below you may need to edit for your robot. My identifier is D9.
topic: valetudo/D9/MapSegmentationCapability/clean/set
payload_template: >-
{"segment_ids": {{expand("group.vacuum_rooms") |
selectattr("state","eq","on")| map(attribute="attributes.room_id") | list |
to_json}}, "iterations": {{states.input_number.vacuum_iterations.state|int
}} }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment