From 2201d7cddab5555546a6204746afcef56c46829d Mon Sep 17 00:00:00 2001 From: Carlo Costanzo Date: Sat, 14 Feb 2026 01:25:38 -0500 Subject: [PATCH] Update logbook and logger configurations; enhance vacuum package logic. Added new entity globs for motion sensors and cameras in logbook.yaml, improved error logging for Alexa components in logger.yaml, and refined vacuum phase management in vacuum.yaml by simplifying phase advancement logic and removing obsolete flags. --- config/logbook.yaml | 4 + config/logger.yaml | 3 + config/packages/vacuum.yaml | 241 +++++++++++++++++++++--------------- 3 files changed, 149 insertions(+), 99 deletions(-) diff --git a/config/logbook.yaml b/config/logbook.yaml index 4eb0d64a..96fd31c7 100644 --- a/config/logbook.yaml +++ b/config/logbook.yaml @@ -14,6 +14,9 @@ exclude: - persistent_notification - update entity_globs: + - binary_sensor.*_motion + - binary_sensor.*gate_motion + - camera.* - sensor.*_location - sensor.*_place - sensor.*_geocoded_location @@ -32,6 +35,7 @@ exclude: - sensor.*_activity - sensor.*_bssid - sensor.*_wifi_signal_strength + - switch.*_container - "*alarm_panel_1*" - "*alarm_panel_2*" entities: diff --git a/config/logger.yaml b/config/logger.yaml index 96ea6ae8..634636ef 100755 --- a/config/logger.yaml +++ b/config/logger.yaml @@ -17,7 +17,10 @@ logs: AIOGitHubAPI: error aiohttp.access: critical aiohttp.server: critical + alexapy: error + alexapy.helpers: error aiounifi: error + custom_components.alexa_media: error custom_components.hacs: error hacs: error homeassistant.core: error diff --git a/config/packages/vacuum.yaml b/config/packages/vacuum.yaml index e1380dd4..f81062a0 100755 --- a/config/packages/vacuum.yaml +++ b/config/packages/vacuum.yaml @@ -10,15 +10,15 @@ # Notes: # - `sensor.l10s_vacuum_current_room` can change during transit; require a dwell (`for:`) before dequeuing. # - Treat 2+ minutes in a room as "being cleaned" and dequeue immediately (queue = remaining rooms). -# - Phase changes happen when the queue is reseeded after the queue hits zero (queue is the source of truth). +# - Phase changes happen only after verified completion at dock (`task_status: completed`). +# - Guarded fallback: if docked with empty queue for 10 minutes but no `completed`, advance with `fallback_advance` log. # - Avoid reissuing `dreame_vacuum.vacuum_clean_segment` while already cleaning; only send a new segment job when starting/resuming or switching phases. # - Jinja2 loop scoping: use a `namespace` when building lists (otherwise the queue can appear empty and get cleared). -# - Docked + task complete only logs queue state; no auto-clearing. +# - If docked+completed still has queue entries, treat queue as stale and clear it before phase advance. # - Mop phases use `sweeping_and_mopping` instead of mop-only. # - One-off room clean booleans ignore the queue; they only run when the vacuum is docked/idle. # - Formal Dining (room 17/dock) is excluded from phased queues; clean via one-off toggle. -# - Confirm Room Cleaned drops room 17 from the queue at cycle start so it never runs first. -# - Phase changes arm when the queue hits zero; reseed advances and clears the phase-ready flag. +# - Phase advancement no longer depends on a separate "ready" latch. ###################################################################### ## 1. Helpers @@ -28,9 +28,6 @@ input_boolean: l10s_vacuum_on_demand: name: Dreame Clean (On-Demand) icon: mdi:robot-vacuum - l10s_vacuum_phase_ready: - name: L10s Vacuum Phase Ready - icon: mdi:progress-check l10s_vacuum_clean_kitchen: name: Kitchen Clean icon: mdi:robot-vacuum @@ -95,7 +92,7 @@ input_text: max: 255 l10s_vacuum_room_catalog: name: L10s Vacuum Room Catalog - initial: "17,6,7,8,9,10,12,13,14,15,2,4,1,3" + initial: "6,7,8,9,10,12,13,14,15,2,4,1,3" icon: mdi:map max: 255 l10s_vacuum_rooms_cleaned_today: @@ -116,85 +113,37 @@ script: 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 }}" + main_ids: "{{ catalog_ints | reject('in', bath_ids) | reject('equalto', 17) | 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' }}" - 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 '' }}" 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 }}" vac_state: "{{ states('vacuum.l10s_vacuum') | default('', true) | string | lower }}" vac_is_cleaning: "{{ vac_state == 'cleaning' }}" - phase_ready: "{{ is_state('input_boolean.l10s_vacuum_phase_ready', 'on') }}" - advance_phase: "{{ queue_ints | length == 0 and phase_ready }}" - reset_cycle: "{{ advance_phase and not has_next_phase }}" - phase_for_seed: "{{ next_phase if advance_phase and has_next_phase else phase }}" - cleaning_mode: "{{ 'sweeping_and_mopping' if 'mop_' in phase_for_seed else 'sweeping' }}" + cleaning_mode: "{{ 'sweeping_and_mopping' if 'mop_' in phase else 'sweeping' }}" phase_segments: > - {% if phase_for_seed == 'sweep_main' %} + {% if phase == 'sweep_main' %} {{ main_ids }} - {% elif phase_for_seed == 'sweep_bath' %} + {% elif phase == 'sweep_bath' %} {{ bath_ids }} - {% elif phase_for_seed == 'mop_main' %} + {% elif phase == 'mop_main' %} {{ main_ids }} {% else %} {{ bath_ids }} {% endif %} segments_to_clean: "{{ queue_ints if queue_ints | length > 0 else phase_segments }}" - # 0. Advance phase when reseeding an empty queue + # 0. Reseed the current phase when queue is empty. - choose: - conditions: - condition: template - value_template: "{{ advance_phase and has_next_phase }}" + value_template: "{{ queue_ints | length == 0 }}" sequence: - - service: input_select.select_option - target: - entity_id: input_select.l10s_vacuum_phase - data: - option: "{{ phase_for_seed }}" - - service: input_boolean.turn_off - target: - entity_id: input_boolean.l10s_vacuum_phase_ready - service: script.send_to_logbook data: topic: "VACUUM" - message: "Queue reseeded; advancing phase to {{ phase_for_seed }}." - - conditions: - - condition: template - value_template: "{{ reset_cycle }}" - sequence: - - service: input_select.select_option - target: - entity_id: input_select.l10s_vacuum_phase - data: - option: "sweep_main" - - service: input_boolean.turn_off - target: - entity_id: input_boolean.l10s_vacuum_phase_ready - - service: input_boolean.turn_off - target: - entity_id: input_boolean.l10s_vacuum_on_demand - - service: script.send_to_logbook - data: - topic: "VACUUM" - message: "All phases complete; resetting phase to sweep_main and disabling On-Demand." - - stop: "All phases complete." - default: [] - - # If the queue is empty but the phase-ready flag is not armed yet, reseed the same phase. - # This is the common case when we haven't positively confirmed the last room as cleaned. - - choose: - - conditions: - - condition: template - value_template: "{{ (queue_ints | length == 0) and (not phase_ready) }}" - sequence: - - service: script.send_to_logbook - data: - topic: "VACUUM" - message: "Queue empty but phase_ready is off; reseeding phase {{ phase }} (no phase advance)." + message: "Queue empty; reseeding phase {{ phase }}." default: [] # 1. Seed the queue if necessary @@ -267,9 +216,6 @@ automation: entity_id: input_text.l10s_vacuum_rooms_cleaned_today data: value: "" - - service: input_boolean.turn_off - target: - entity_id: input_boolean.l10s_vacuum_phase_ready - alias: 'Vacuum: Auto-Start if Idle 4 Days' id: c6b3f1e8-9a3f-4098-9b9e-1c7f2d6f1d11 @@ -468,9 +414,7 @@ automation: 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_raw: "{{ queue_raw | regex_findall('[0-9]+') | map('int') | select('gt', 0) | list | default([], true) }}" - queue_has_17: "{{ 17 in queue_ints_raw }}" - queue_ints: "{{ queue_ints_raw | reject('equalto', 17) | list }}" - queue_without_17: "{{ queue_ints | join(',') }}" + queue_ints: "{{ queue_ints_raw | list }}" cleaned_room_state: "{{ trigger.to_state.state if trigger.to_state is not none else '' }}" cleaned_room_id: "{{ (trigger.to_state.attributes.room_id if trigger.to_state is not none else 0) | int(0) }}" matched_room_id: "{{ cleaned_room_id if cleaned_room_id > 0 and cleaned_room_id in (queue_ints | default([], true)) else 0 }}" @@ -502,7 +446,7 @@ automation: - condition: template value_template: "{{ queue_ints_raw | length > 0 }}" - condition: template - value_template: "{{ matched_room_id != 0 or queue_has_17 }}" + value_template: "{{ matched_room_id != 0 }}" - condition: state entity_id: vacuum.l10s_vacuum state: 'cleaning' @@ -519,22 +463,6 @@ automation: {% set is_formal_dining = matched_room_id == 17 %} {{ not (is_formal_dining and (vac_charging or vac_status in ['charging', 'docked'])) }} - - choose: - - conditions: - - condition: template - value_template: "{{ queue_has_17 }}" - sequence: - - service: input_text.set_value - target: - entity_id: input_text.l10s_vacuum_room_queue - data: - value: "{{ queue_without_17 }}" - - service: script.send_to_logbook - data: - topic: "VACUUM" - message: "Removing Formal Dining (17) from the queue at cycle start." - default: [] - - choose: - conditions: - condition: template @@ -569,27 +497,39 @@ automation: - condition: template value_template: "{{ remaining_count == 0 }}" sequence: - - service: input_boolean.turn_on - target: - entity_id: input_boolean.l10s_vacuum_phase_ready - service: script.send_to_logbook data: topic: "VACUUM" - message: "Queue empty for phase {{ phase }}; phase advance armed for next reseed." + message: "Queue empty for phase {{ phase }}; waiting for completed+docked to advance." default: [] default: [] - - alias: 'Away Vacuum: Clear Queue on Dock After Completion' + - alias: 'Away Vacuum: Advance Phase on Dock After Completion' id: 6a2d6d8c-3c67-4e3f-9c97-0a2560890d60 mode: single trigger: - platform: state entity_id: vacuum.l10s_vacuum to: 'docked' + - platform: state + entity_id: sensor.l10s_vacuum_task_status + to: 'completed' variables: queue_raw: "{{ states('input_text.l10s_vacuum_room_queue') | default('', true) | trim }}" - queue_empty: "{{ queue_raw == '' }}" + queue_ints: "{{ queue_raw | regex_findall('[0-9]+') | map('int') | select('gt', 0) | 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' }}" + 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: state + entity_id: input_boolean.l10s_vacuum_on_demand + state: 'on' + - condition: state + entity_id: vacuum.l10s_vacuum + state: 'docked' - condition: state entity_id: sensor.l10s_vacuum_task_status state: 'completed' @@ -597,23 +537,126 @@ automation: - choose: - conditions: - condition: template - value_template: "{{ queue_empty }}" + value_template: "{{ queue_ints | length > 0 }}" sequence: - - service: input_boolean.turn_on + - service: script.send_to_logbook + data: + topic: "VACUUM" + message: "Completed+docked but queue still had rooms ({{ queue_raw }}); clearing stale queue." + - service: input_text.set_value target: - entity_id: input_boolean.l10s_vacuum_phase_ready + entity_id: input_text.l10s_vacuum_room_queue + data: + value: "" + default: [] + + - choose: + - conditions: + - condition: template + value_template: "{{ has_next_phase }}" + sequence: + - service: input_select.select_option + target: + entity_id: input_select.l10s_vacuum_phase + data: + option: "{{ next_phase }}" - service: script.send_to_logbook data: topic: "VACUUM" - message: "Docked after completion; queue already empty. Phase advance armed." + message: "Completed phase {{ phase }}; advancing to {{ next_phase }}." + - service: script.l10s_vacuum_start_next_room - conditions: - condition: template - value_template: "{{ not queue_empty }}" + value_template: "{{ not has_next_phase }}" sequence: + - service: input_select.select_option + target: + entity_id: input_select.l10s_vacuum_phase + data: + option: "sweep_main" + - service: input_boolean.turn_off + target: + entity_id: input_boolean.l10s_vacuum_on_demand + - service: input_text.set_value + target: + entity_id: input_text.l10s_vacuum_room_queue + data: + value: "" + - service: script.send_to_logbook + data: + topic: "VACUUM" + message: "All phases complete; resetting to sweep_main and disabling On-Demand." + default: [] + + - alias: 'Away Vacuum: Fallback Advance After Dock Timeout' + id: 0b3db0d9-8a13-4e64-9b2b-8162b64b1e6f + mode: single + trigger: + - platform: template + value_template: > + {{ + is_state('input_boolean.l10s_vacuum_on_demand', 'on') + and is_state('vacuum.l10s_vacuum', 'docked') + and (states('input_text.l10s_vacuum_room_queue') | default('', true) | trim == '') + and not is_state('sensor.l10s_vacuum_task_status', 'completed') + }} + for: "00:10:00" + variables: + 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 '' }}" + task_status: "{{ states('sensor.l10s_vacuum_task_status') }}" + condition: + - condition: state + entity_id: input_boolean.l10s_vacuum_on_demand + state: 'on' + - condition: state + entity_id: vacuum.l10s_vacuum + state: 'docked' + - condition: template + value_template: "{{ states('input_text.l10s_vacuum_room_queue') | default('', true) | trim == '' }}" + - condition: template + value_template: "{{ task_status != 'completed' }}" + action: + - choose: + - conditions: + - condition: template + value_template: "{{ has_next_phase }}" + sequence: + - service: input_select.select_option + target: + entity_id: input_select.l10s_vacuum_phase + data: + option: "{{ next_phase }}" + - service: script.send_to_logbook + data: + topic: "VACUUM" + message: "fallback_advance: docked 10m with empty queue and task_status={{ task_status }}; advancing {{ phase }} -> {{ next_phase }}." + - service: script.l10s_vacuum_start_next_room + - conditions: + - condition: template + value_template: "{{ not has_next_phase }}" + sequence: + - service: input_select.select_option + target: + entity_id: input_select.l10s_vacuum_phase + data: + option: "sweep_main" + - service: input_boolean.turn_off + target: + entity_id: input_boolean.l10s_vacuum_on_demand + - service: input_text.set_value + target: + entity_id: input_text.l10s_vacuum_room_queue + data: + value: "" - service: script.send_to_logbook data: topic: "VACUUM" - message: "Docked after completion; queue still has rooms: {{ queue_raw }}." + message: "fallback_advance: final phase timed out docked 10m with empty queue; resetting to sweep_main and disabling On-Demand." default: [] - alias: 'Away Vacuum: Resume From Dock When Queue Exists'