mirror of
https://github.com/CCOSTAN/Home-AssistantConfig.git
synced 2025-12-12 01:52:16 +00:00
Refactor Dreame vacuum orchestration to implement continuous phased cleaning cycles. Update logic for room queue management and notifications, enhancing automation for idle periods and phase transitions.
355 lines
13 KiB
YAML
Executable File
355 lines
13 KiB
YAML
Executable File
######################################################################
|
|
# @CCOSTAN - Follow Me on X
|
|
# For more info visit https://www.vcloudinfo.com/click-here
|
|
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
|
|
# -------------------------------------------------------------------
|
|
# Dreame Vacuum Orchestration - Continuous phased sweep/mop with away/on-demand
|
|
# Phases: sweep main, sweep baths, mop main, mop baths; notifications + idle auto-start
|
|
# -------------------------------------------------------------------
|
|
######################################################################
|
|
|
|
## 1. Helpers
|
|
######################################################################
|
|
|
|
input_boolean:
|
|
l10s_vacuum_on_demand:
|
|
name: Dreame Clean (On-Demand)
|
|
icon: mdi:robot-vacuum
|
|
|
|
input_select:
|
|
l10s_vacuum_phase:
|
|
name: L10s Vacuum Phase
|
|
options:
|
|
- sweep_main
|
|
- sweep_bath
|
|
- mop_main
|
|
- mop_bath
|
|
initial: sweep_main
|
|
icon: mdi:playlist-check
|
|
|
|
input_text:
|
|
l10s_vacuum_room_queue:
|
|
name: L10s Vacuum Room Queue
|
|
# Room order (id:name): 14 Kitchen, 12 Dining, 10 Living, 7 Master Bedroom, 15 Foyer, 9 Stacey Office,
|
|
# 17 Formal Dining, 13 Hallway, 8 Justin Bedroom, 6 Paige Bedroom, 4 Master Bathroom, 2 Office, 1 Pool Bath, 3 Kids Bathroom.
|
|
icon: mdi:format-list-bulleted
|
|
max: 255
|
|
l10s_vacuum_room_catalog:
|
|
name: L10s Vacuum Room Catalog
|
|
initial: "6,7,8,9,10,12,13,14,15,17,2,4,1,3"
|
|
icon: mdi:map
|
|
max: 255
|
|
l10s_vacuum_rooms_cleaned_today:
|
|
name: L10s Vacuum Rooms Cleaned Today
|
|
icon: mdi:clipboard-check-outline
|
|
max: 255
|
|
|
|
## 2. Script: Start Next Room
|
|
######################################################################
|
|
|
|
script:
|
|
|
|
l10s_vacuum_start_next_room:
|
|
alias: 'Away Vacuum: Start Next Room'
|
|
mode: single
|
|
sequence:
|
|
- variables:
|
|
catalog_raw: "{{ states('input_text.l10s_vacuum_room_catalog') | default('', true) | string | replace(' ', '') }}"
|
|
catalog_ints: "{{ catalog_raw | regex_findall('[0-9]+') | map('int') | select('gt', 0) | list }}"
|
|
bath_ids: [1, 3, 4]
|
|
main_ids: "{{ catalog_ints | reject('in', bath_ids) | list }}"
|
|
phase_order: ['sweep_main', 'sweep_bath', 'mop_main', 'mop_bath']
|
|
phase_state: "{{ states('input_select.l10s_vacuum_phase') }}"
|
|
phase: "{{ phase_state if phase_state in phase_order else 'sweep_main' }}"
|
|
cleaning_mode: "{{ 'mopping' if 'mop_' in phase else 'sweeping' }}"
|
|
queue_raw: "{{ states('input_text.l10s_vacuum_room_queue') | default('', true) | string | replace(' ', '') }}"
|
|
queue_ints: "{{ queue_raw | regex_findall('[0-9]+') | map('int') | select('gt', 0) | list }}"
|
|
phase_segments: >
|
|
{% if phase == 'sweep_main' %}
|
|
{{ main_ids }}
|
|
{% elif phase == 'sweep_bath' %}
|
|
{{ bath_ids }}
|
|
{% elif phase == 'mop_main' %}
|
|
{{ main_ids }}
|
|
{% else %}
|
|
{{ bath_ids }}
|
|
{% endif %}
|
|
segments_to_clean: "{{ queue_ints if queue_ints | length > 0 else phase_segments }}"
|
|
|
|
# 1. Seed the queue if necessary
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ queue_ints | length == 0 and phase_segments | length > 0 }}"
|
|
sequence:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.l10s_vacuum_room_queue
|
|
data:
|
|
value: "{{ phase_segments | join(',') }}"
|
|
default: []
|
|
|
|
# 2. Check if there is anything to clean and stop if not
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ segments_to_clean | length == 0 }}"
|
|
sequence:
|
|
- stop: 'No rooms left to clean today.'
|
|
default: []
|
|
|
|
# 3. Start cleaning
|
|
- service: select.select_option
|
|
target:
|
|
entity_id: select.l10s_vacuum_cleaning_mode
|
|
data:
|
|
option: "{{ cleaning_mode }}"
|
|
- service: vacuum.set_fan_speed
|
|
target:
|
|
entity_id: vacuum.l10s_vacuum
|
|
data:
|
|
fan_speed: Standard
|
|
- service: dreame_vacuum.vacuum_clean_segment
|
|
target:
|
|
entity_id: vacuum.l10s_vacuum
|
|
data:
|
|
# Clean the non-bathrooms if any, otherwise clean the bathrooms
|
|
segments: "{{ segments_to_clean }}"
|
|
|
|
|
|
## 3. Automations
|
|
######################################################################
|
|
|
|
automation:
|
|
|
|
- alias: 'Vacuum: Reset Cleaned List at 5am'
|
|
id: 18f7b6d3-c02c-4ec1-88b3-0c3b8b4c6f7b
|
|
trigger:
|
|
- platform: time
|
|
at: '05:00:00'
|
|
action:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.l10s_vacuum_rooms_cleaned_today
|
|
data:
|
|
value: ""
|
|
|
|
- alias: 'Vacuum: Auto-Start if Idle 3 Days'
|
|
id: c6b3f1e8-9a3f-4098-9b9e-1c7f2d6f1d11
|
|
trigger:
|
|
- platform: time
|
|
at: '16:00:00'
|
|
condition:
|
|
- condition: template
|
|
value_template: >
|
|
{% set last = state_attr('script.l10s_vacuum_start_next_room','last_triggered') %}
|
|
{{ last is none or (now() - last).days >= 3 }}
|
|
action:
|
|
- service: input_boolean.turn_on
|
|
target:
|
|
entity_id: input_boolean.l10s_vacuum_on_demand
|
|
|
|
- alias: 'Away Vacuum: Start or Resume When we leave or On-Demand'
|
|
id: 7f7e0a3c-6452-4f6b-8464-c6c25770a148
|
|
trigger:
|
|
- platform: state
|
|
entity_id: group.family
|
|
to: 'not_home'
|
|
- platform: state
|
|
entity_id: input_boolean.l10s_vacuum_on_demand
|
|
to: 'on'
|
|
condition:
|
|
- condition: state
|
|
entity_id: input_boolean.guest_mode
|
|
state: 'off'
|
|
- condition: template
|
|
value_template: >
|
|
{{ is_state('input_boolean.l10s_vacuum_on_demand', 'on') or is_state('group.family', 'not_home') }}
|
|
- condition: template
|
|
value_template: "{{ not is_state('vacuum.l10s_vacuum', 'cleaning') }}"
|
|
action:
|
|
- service: script.l10s_vacuum_start_next_room
|
|
|
|
- alias: 'Away Vacuum: Dock When Family Returns'
|
|
id: 1ef172f2-4b30-4e5b-953d-d4d1ca8701ad
|
|
trigger:
|
|
- platform: state
|
|
entity_id: group.family
|
|
to: 'home'
|
|
- platform: state
|
|
entity_id: input_boolean.l10s_vacuum_on_demand
|
|
to: 'off'
|
|
condition:
|
|
- condition: template
|
|
value_template: >
|
|
{{ is_state('vacuum.l10s_vacuum', 'cleaning') or is_state('vacuum.l10s_vacuum', 'returning') or is_state('vacuum.l10s_vacuum', 'paused') }}
|
|
action:
|
|
- service: vacuum.pause
|
|
target:
|
|
entity_id: vacuum.l10s_vacuum
|
|
- delay: 00:00:10
|
|
- service: vacuum.return_to_base
|
|
target:
|
|
entity_id: vacuum.l10s_vacuum
|
|
|
|
- alias: 'Away Vacuum: Confirm Room Cleaned'
|
|
id: c581c570-55b0-4acd-8b5d-53cfb486cc2a
|
|
trigger:
|
|
- platform: state
|
|
entity_id: sensor.l10s_vacuum_current_room
|
|
for: '00:03:00'
|
|
variables:
|
|
room_map: {14:'kitchen',12:'dining-room',10:'living room',7:'master-bedroom',15:'foyer',9:'stacey-office',17:'formal-dining',13:'hallway',8:'justin-bedroom',6:'paige-bedroom',4:'master-bathroom',2:'office',1:'pool-bath',3:'kids-bathroom'}
|
|
queue_raw: "{{ states('input_text.l10s_vacuum_room_queue') | default('', true) | string | replace(' ', '') }}"
|
|
queue_ints: "{{ queue_raw | regex_findall('[0-9]+') | map('int') | list | default([], true) }}"
|
|
current_room_id: "{{ trigger.to_state.attributes.room_id | default(state_attr('sensor.l10s_vacuum_current_room', 'room_id'), true) | int(0) }}"
|
|
matched_room_id: "{{ current_room_id if current_room_id > 0 and current_room_id in (queue_ints | default([], true)) else 0 }}"
|
|
remaining_list: >
|
|
{% set rem = [] %}
|
|
{% set removed = namespace(done=false) %}
|
|
{% for r in queue_ints %}
|
|
{% if not removed.done and r == matched_room_id %}
|
|
{% set removed.done = true %}
|
|
{% else %}
|
|
{% set rem = rem + [r] %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
{{ rem }}
|
|
remaining_rooms: "{{ remaining_list | join(',') }}"
|
|
remaining_count: "{{ remaining_list | length }}"
|
|
phase_order: ['sweep_main', 'sweep_bath', 'mop_main', 'mop_bath']
|
|
phase_state: "{{ states('input_select.l10s_vacuum_phase') }}"
|
|
phase: "{{ phase_state if phase_state in phase_order else 'sweep_main' }}"
|
|
phase_index: "{{ phase_order.index(phase) if phase in phase_order else 0 }}"
|
|
has_next_phase: "{{ phase_index < (phase_order | length) - 1 }}"
|
|
next_phase: "{{ phase_order[phase_index + 1] if has_next_phase else '' }}"
|
|
|
|
condition:
|
|
- condition: template
|
|
value_template: "{{ queue_ints | length > 0 }}"
|
|
- condition: template
|
|
value_template: "{{ matched_room_id != 0 }}"
|
|
- condition: state
|
|
entity_id: vacuum.l10s_vacuum
|
|
state: 'cleaning'
|
|
|
|
action:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.l10s_vacuum_room_queue
|
|
data:
|
|
value: "{{ remaining_rooms }}"
|
|
- variables:
|
|
cleaned_raw: "{{ states('input_text.l10s_vacuum_rooms_cleaned_today') | default('', true) | string }}"
|
|
cleaned_parts: "{{ cleaned_raw | regex_findall('[^,]+') | map('trim') | reject('equalto','') | list }}"
|
|
room_name: "{{ room_map.get(matched_room_id, states('sensor.l10s_vacuum_current_room')) }}"
|
|
updated_cleaned: >
|
|
{% set parts = cleaned_parts %}
|
|
{% if room_name not in parts %}
|
|
{{ (parts + [room_name]) | join(', ') }}
|
|
{% else %}
|
|
{{ parts | join(', ') }}
|
|
{% endif %}
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.l10s_vacuum_rooms_cleaned_today
|
|
data:
|
|
value: "{{ updated_cleaned }}"
|
|
- service: script.notify_engine
|
|
data:
|
|
title: 'Vacuum Room Cleaned'
|
|
value1: "{{ room_name }} is clean."
|
|
value2: "Remaining: {{ remaining_count }}."
|
|
ios_category: 'camera'
|
|
camera_entity: 'camera.l10s_vacuum_map'
|
|
content_type: 'jpeg'
|
|
who: 'carlo'
|
|
group: 'information'
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ remaining_count > 0 }}"
|
|
sequence:
|
|
- service: script.l10s_vacuum_start_next_room
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ remaining_count == 0 and has_next_phase }}"
|
|
sequence:
|
|
- service: input_select.select_option
|
|
target:
|
|
entity_id: input_select.l10s_vacuum_phase
|
|
data:
|
|
option: "{{ next_phase }}"
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.l10s_vacuum_room_queue
|
|
data:
|
|
value: ""
|
|
- service: script.l10s_vacuum_start_next_room
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ remaining_count == 0 and not has_next_phase }}"
|
|
sequence:
|
|
- service: input_select.select_option
|
|
target:
|
|
entity_id: input_select.l10s_vacuum_phase
|
|
data:
|
|
option: "sweep_main"
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: input_text.l10s_vacuum_room_queue
|
|
data:
|
|
value: ""
|
|
- service: script.l10s_vacuum_start_next_room
|
|
|
|
- alias: 'Vacuum Sensor Cleaning Silencer'
|
|
id: 6548de52-a4a4-4df2-9d66-9c2c15577a7f
|
|
trigger:
|
|
- platform: numeric_state
|
|
entity_id: sensor.l10s_vacuum_sensor_dirty_left
|
|
below: 10
|
|
condition:
|
|
- condition: state
|
|
entity_id: sensor.l10s_vacuum_task_status
|
|
state: 'completed'
|
|
action:
|
|
- service: button.press
|
|
target:
|
|
entity_id: button.l10s_vacuum_reset_sensor
|
|
|
|
- alias: 'Help Vacuum'
|
|
id: 6548de52-a4a4-4df2-9d66-9c2c15577a7e
|
|
trigger:
|
|
- platform: state
|
|
entity_id: sensor.l10s_vacuum_error
|
|
- platform: event
|
|
event_type: event_did_someone_help_vacuum_loop
|
|
condition:
|
|
- condition: template
|
|
value_template: "{{ states('sensor.l10s_vacuum_error') not in ['no_error', 'unavailable'] }}"
|
|
action:
|
|
- service: script.notify_engine
|
|
data:
|
|
title: 'Help vacuum'
|
|
value1: "{{ states('sensor.l10s_vacuum_error') }} - {{states('sensor.l10s_vacuum_current_room')}}"
|
|
who: 'family'
|
|
ios_category: 'camera'
|
|
camera_entity: 'camera.l10s_vacuum_map'
|
|
content_type: 'jpeg'
|
|
group: 'information'
|
|
- wait_template: "{{ is_state('group.bed', 'off') }}"
|
|
- wait_template: "{{ is_state('group.family', 'home') }}"
|
|
- delay: 00:03:00
|
|
- service: vacuum.locate
|
|
entity_id: vacuum.l10s_vacuum
|
|
- service: script.speech_engine
|
|
data:
|
|
value1: >
|
|
{{ "Vacuum error: " ~ states('sensor.l10s_vacuum_error') ~ " [ask Residents to help]" }}
|
|
Currently in {{states('sensor.l10s_vacuum_current_room')}}
|
|
- delay: 00:01:00
|
|
- service: vacuum.locate
|
|
entity_id: vacuum.l10s_vacuum
|
|
- delay: 00:20:00
|
|
- event: event_did_someone_help_vacuum_loop
|