Analyze Washing Machine.yaml file designed to work as automation blueprint for Home Assisant OS. Refactor it improving overall code quality, fix obvious or critical bugs/mistakes and add comments that will make the code more easy to read and understand.
This commit is contained in:
@@ -1,38 +1,86 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Washing Machine / Dryer Notifications Blueprint for Home Assistant
|
||||||
|
# =============================================================================
|
||||||
|
# This blueprint monitors washing machine or dryer appliances and sends
|
||||||
|
# notifications for various events throughout the wash/dry cycle.
|
||||||
|
#
|
||||||
|
# Features:
|
||||||
|
# - Start notification with cycle duration and mode details
|
||||||
|
# - Completion notification (reminder to unload clothes)
|
||||||
|
# - "Almost done" notification (configurable minutes before end)
|
||||||
|
# - Error message notifications
|
||||||
|
# - Preparation mode notification (e.g., for dryer prep)
|
||||||
|
# - Tub/drum cleaning reminder based on wash counter
|
||||||
|
#
|
||||||
|
# State Machine:
|
||||||
|
# The automation tracks the appliance through these states:
|
||||||
|
# 1. IDLE: Waiting for cycle to start
|
||||||
|
# 2. RUNNING: Cycle in progress (start notification sent)
|
||||||
|
# 3. FINISHING: Near completion (time-to-end notification sent)
|
||||||
|
# 4. COMPLETED: Cycle done (completion notification sent, state reset)
|
||||||
|
#
|
||||||
|
# Persistent State Keys:
|
||||||
|
# - nass: Notification About Start Sent
|
||||||
|
# - nart: Notification About Remaining Time Sent
|
||||||
|
# - naps: Notification About Preparation Sent
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# - Sensors for: remaining time, run state, error messages
|
||||||
|
# - input_text entity for persistent state storage
|
||||||
|
# - Notification service entity
|
||||||
|
#
|
||||||
|
# Note: Default values are in Russian for LG ThinQ integration.
|
||||||
|
# Adjust run_state_completion_id and other defaults for your language.
|
||||||
|
#
|
||||||
|
# Author: Alexei Dolgolyov (dolgolyov.alexei@gmail.com)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
blueprint:
|
blueprint:
|
||||||
name: "Custom: Washing Machine Notifications"
|
name: "Custom: Washing Machine Notifications"
|
||||||
description: >
|
description: >
|
||||||
Sends notifications when washing starts (with mode details),
|
Sends notifications when washing starts (with mode details),
|
||||||
when errors occur, and when run completes.
|
when errors occur, and when run completes.
|
||||||
domain: automation
|
domain: automation
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# INPUT CONFIGURATION
|
||||||
|
# ===========================================================================
|
||||||
input:
|
input:
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Time & State Sensors
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Core sensors for tracking the appliance cycle state
|
||||||
time_group:
|
time_group:
|
||||||
name: "Time"
|
name: "Time"
|
||||||
collapsed: false
|
collapsed: false
|
||||||
input:
|
input:
|
||||||
remaining_time_sensor:
|
remaining_time_sensor:
|
||||||
name: Remaining Time Sensor
|
name: Remaining Time Sensor
|
||||||
description: "Sensor that contains remaining time in format `hh:mm::ss`. Note: `-`, 'unknown' values means remaining time is not available."
|
description: >
|
||||||
|
Sensor that contains remaining time in format `hh:mm:ss`.
|
||||||
|
Note: `-`, 'unknown' values mean remaining time is not available.
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
domain: sensor
|
domain: sensor
|
||||||
|
|
||||||
run_state_sensor:
|
run_state_sensor:
|
||||||
name: Run State Sensor
|
name: Run State Sensor
|
||||||
description: "Sensor that run state of the device"
|
description: "Sensor that reports the run state of the device"
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
domain: sensor
|
domain: sensor
|
||||||
|
|
||||||
run_state_completion_id:
|
run_state_completion_id:
|
||||||
name: Run State Completion Id
|
name: Run State Completion ID
|
||||||
description: "Identifier of run state that indicates that run is completed"
|
description: "Identifier of run state that indicates that the cycle is completed"
|
||||||
default: 'Цикл завершен.'
|
default: 'Цикл завершен.'
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
|
|
||||||
notify_time_to_end:
|
notify_time_to_end:
|
||||||
name: Notify Time-to-End (minutes)
|
name: Notify Time-to-End (minutes)
|
||||||
description: "Send notification if run is about to be finished"
|
description: "Send notification when cycle is about to finish (minutes remaining)"
|
||||||
default: 10
|
default: 10
|
||||||
selector:
|
selector:
|
||||||
number:
|
number:
|
||||||
@@ -40,170 +88,238 @@ blueprint:
|
|||||||
max: 60
|
max: 60
|
||||||
unit_of_measurement: minutes
|
unit_of_measurement: minutes
|
||||||
mode: slider
|
mode: slider
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Persistent State Configuration
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Stores automation state between triggers to track notification history
|
||||||
persistent_state:
|
persistent_state:
|
||||||
name: "Persistent State"
|
name: "Persistent State"
|
||||||
collapsed: false
|
collapsed: false
|
||||||
input:
|
input:
|
||||||
automation_state_entity:
|
automation_state_entity:
|
||||||
name: Automation state entity
|
name: Automation state entity
|
||||||
description: "`input_text` that stores the automation state in JSON format. Required for all features proper functioning. `Doesn't require specific initial state, values of the entity can be empty`"
|
description: >
|
||||||
|
`input_text` entity that stores the automation state in JSON format.
|
||||||
|
Required for all features to function properly.
|
||||||
|
Doesn't require specific initial state - values can be empty.
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
domain: input_text
|
domain: input_text
|
||||||
|
|
||||||
automation_state_placeholder_key:
|
automation_state_placeholder_key:
|
||||||
name: Automation state placeholder key
|
name: Automation state placeholder key
|
||||||
description: Overrides key for persistent storage if not empty. By default uses identifier of target light, otherwise uses constant. `Don't override it if you don't understand the meaning`
|
description: >
|
||||||
|
Overrides key for persistent storage if not empty.
|
||||||
|
By default uses the remaining time sensor entity ID.
|
||||||
|
Don't override if you don't understand the meaning.
|
||||||
default: ''
|
default: ''
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Notification Settings
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
notification_group:
|
notification_group:
|
||||||
name: "Notification"
|
name: "Notification"
|
||||||
collapsed: false
|
collapsed: false
|
||||||
input:
|
input:
|
||||||
input_device_name:
|
input_device_name:
|
||||||
name: "Device Name"
|
name: "Device Name"
|
||||||
description: Device name (used for notifications)
|
description: "Device name used in notification messages"
|
||||||
default: "Стиральная машина"
|
default: "Стиральная машина"
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
|
|
||||||
notify_target:
|
notify_target:
|
||||||
name: Notification Target
|
name: Notification Target
|
||||||
description: Device or service to send notifications
|
description: "Notification service entity to send messages to"
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
domain: notify
|
domain: notify
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Device Information Sensors
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
info_group:
|
info_group:
|
||||||
name: "Info"
|
name: "Info"
|
||||||
collapsed: false
|
collapsed: false
|
||||||
input:
|
input:
|
||||||
non_running_state_ids:
|
non_running_state_ids:
|
||||||
name: Non Running State ID(s)
|
name: Non Running State ID(s)
|
||||||
description: "List of run state ID(s) that indicates that device is not actually doing its direct job"
|
description: >
|
||||||
|
List of run state ID(s) that indicate the device is not actively
|
||||||
|
running a cycle (e.g., 'Pause', 'Standby', 'Ready')
|
||||||
default: []
|
default: []
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
multiple: true
|
multiple: true
|
||||||
|
|
||||||
preparation_state_id:
|
preparation_state_id:
|
||||||
name: Preparation Mode State ID (optional)
|
name: Preparation Mode State ID (optional)
|
||||||
description: "Optional run state ID that indicates that device is preparing to run"
|
description: >
|
||||||
|
Optional run state ID that indicates the device is preparing
|
||||||
|
(e.g., dryer heating up before starting)
|
||||||
default: 'Подготовка к сушке'
|
default: 'Подготовка к сушке'
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
|
|
||||||
error_message_sensor:
|
error_message_sensor:
|
||||||
name: Error Message Sensor
|
name: Error Message Sensor
|
||||||
description: "Sensor that reports possible error message"
|
description: "Sensor that reports error messages from the device"
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
domain: sensor
|
domain: sensor
|
||||||
|
|
||||||
tub_clean_counter_sensor:
|
tub_clean_counter_sensor:
|
||||||
name: Tub Clean Counter Sensor (Optional)
|
name: Tub Clean Counter Sensor (optional)
|
||||||
description: "Sensor that reports tub clean counter value"
|
description: "Sensor that reports the number of cycles since last tub cleaning"
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
domain:
|
domain:
|
||||||
- sensor
|
- sensor
|
||||||
- input_number
|
- input_number
|
||||||
|
|
||||||
tub_clean_counter_threshold:
|
tub_clean_counter_threshold:
|
||||||
name: Tub Clean Counter Threshold
|
name: Tub Clean Counter Threshold
|
||||||
description: "Threshold for tub clean counter value when notification should be sent. Zero means no reports."
|
description: >
|
||||||
|
Number of cycles after which a tub cleaning reminder is sent.
|
||||||
|
Set to 0 to disable tub cleaning notifications.
|
||||||
default: 30
|
default: 30
|
||||||
selector:
|
selector:
|
||||||
number:
|
number:
|
||||||
min: 0
|
min: 0
|
||||||
max: 100
|
max: 100
|
||||||
mode: slider
|
mode: slider
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Startup Details (optional additional info in start notification)
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
details_group:
|
details_group:
|
||||||
name: "Details"
|
name: "Details"
|
||||||
collapsed: false
|
collapsed: false
|
||||||
input:
|
input:
|
||||||
startup_info_sensors:
|
startup_info_sensors:
|
||||||
name: Startup Info Sensors (Optional)
|
name: Startup Info Sensors (optional)
|
||||||
description: "A list of sensor with some details that will be reported on machine startup notification"
|
description: >
|
||||||
|
List of sensors with additional details to include in the
|
||||||
|
startup notification (e.g., temperature, spin speed, program)
|
||||||
default: []
|
default: []
|
||||||
selector:
|
selector:
|
||||||
entity:
|
entity:
|
||||||
domain:
|
domain:
|
||||||
- sensor
|
- sensor
|
||||||
- binary_sensor
|
- binary_sensor
|
||||||
multiple: true
|
multiple: true
|
||||||
|
|
||||||
startup_info_texts:
|
startup_info_texts:
|
||||||
name: Startup Info Texts
|
name: Startup Info Texts
|
||||||
description: "List of texts associated with `Startup Info Sensors` (one per sensor)"
|
description: >
|
||||||
|
Labels for each sensor in `Startup Info Sensors` list.
|
||||||
|
Must have the same number of entries as sensors.
|
||||||
default: []
|
default: []
|
||||||
selector:
|
selector:
|
||||||
text:
|
text:
|
||||||
multiple: true
|
multiple: true
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# AUTOMATION MODE
|
||||||
|
# =============================================================================
|
||||||
|
# Restart mode ensures new triggers interrupt any running automation
|
||||||
|
# (useful for rapid state changes)
|
||||||
mode: restart
|
mode: restart
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# TRIGGERS
|
||||||
|
# =============================================================================
|
||||||
|
# Monitor all relevant sensors for state changes
|
||||||
trigger:
|
trigger:
|
||||||
# Remaining time changes
|
# Remaining time changes (tracks cycle progress)
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input remaining_time_sensor
|
entity_id: !input remaining_time_sensor
|
||||||
|
|
||||||
# Error message appears
|
# Error message appears
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input error_message_sensor
|
entity_id: !input error_message_sensor
|
||||||
# Run state
|
|
||||||
|
# Run state changes (start, stop, pause, etc.)
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input run_state_sensor
|
entity_id: !input run_state_sensor
|
||||||
# Tub clean sensor changed
|
|
||||||
|
# Tub clean counter changed
|
||||||
- platform: state
|
- platform: state
|
||||||
entity_id: !input tub_clean_counter_sensor
|
entity_id: !input tub_clean_counter_sensor
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# CONDITIONS
|
||||||
|
# =============================================================================
|
||||||
|
# No global conditions - individual cases handle their own logic
|
||||||
condition: []
|
condition: []
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# VARIABLES
|
||||||
|
# =============================================================================
|
||||||
variables:
|
variables:
|
||||||
# JSON state constants
|
|
||||||
state_notification_about_renaming_time_sent: 'nart'
|
# ---------------------------------------------------------------------------
|
||||||
state_notification_about_start_sent: 'nass'
|
# Persistent State Keys
|
||||||
state_notification_about_preparation_sent: 'naps'
|
# ---------------------------------------------------------------------------
|
||||||
|
# Short keys to minimize JSON storage size in input_text entity
|
||||||
# Inputs
|
state_notification_about_remaining_time_sent: 'nart' # "Almost done" notification sent
|
||||||
|
state_notification_about_start_sent: 'nass' # Start notification sent
|
||||||
|
state_notification_about_preparation_sent: 'naps' # Preparation notification sent
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Input Variables
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
run_state_sensor: !input run_state_sensor
|
run_state_sensor: !input run_state_sensor
|
||||||
non_running_state_ids: !input non_running_state_ids
|
non_running_state_ids: !input non_running_state_ids
|
||||||
preparation_state_id: !input preparation_state_id
|
preparation_state_id: !input preparation_state_id
|
||||||
error_message_sensor: !input error_message_sensor
|
error_message_sensor: !input error_message_sensor
|
||||||
remaining_time_sensor: !input remaining_time_sensor
|
remaining_time_sensor: !input remaining_time_sensor
|
||||||
notify_target: !input notify_target
|
notify_target: !input notify_target
|
||||||
notify_time_to_end: !input notify_time_to_end
|
notify_time_to_end: !input notify_time_to_end
|
||||||
input_device_name: !input input_device_name
|
input_device_name: !input input_device_name
|
||||||
tub_clean_counter_sensor: !input tub_clean_counter_sensor
|
tub_clean_counter_sensor: !input tub_clean_counter_sensor
|
||||||
tub_clean_counter_threshold: !input tub_clean_counter_threshold
|
tub_clean_counter_threshold: !input tub_clean_counter_threshold
|
||||||
run_state_completion_id: !input run_state_completion_id
|
run_state_completion_id: !input run_state_completion_id
|
||||||
|
|
||||||
# States
|
# ---------------------------------------------------------------------------
|
||||||
|
# Computed State Values
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
remaining: "{{ states(remaining_time_sensor) }}"
|
remaining: "{{ states(remaining_time_sensor) }}"
|
||||||
device_name: "{{ input_device_name }}"
|
device_name: "{{ input_device_name }}"
|
||||||
run_state: "{{ states(run_state_sensor) }}"
|
run_state: "{{ states(run_state_sensor) }}"
|
||||||
|
|
||||||
|
# Determine if the appliance is actively running a cycle
|
||||||
|
# Excludes: unknown states, non-running states, preparation, and completion
|
||||||
is_running: >
|
is_running: >
|
||||||
{{ run_state not in ['unknown', 'unavailable', 'waiting', '-']
|
{{ run_state not in ['unknown', 'unavailable', 'waiting', '-']
|
||||||
and run_state not in non_running_state_ids
|
and run_state not in non_running_state_ids
|
||||||
and run_state != preparation_state_id
|
and run_state != preparation_state_id
|
||||||
and run_state != run_state_completion_id
|
and run_state != run_state_completion_id
|
||||||
and remaining not in ['unknown', 'unavailable'] }}
|
and remaining not in ['unknown', 'unavailable'] }}
|
||||||
|
|
||||||
|
# Parse remaining time string (hh:mm:ss) to total minutes
|
||||||
remaining_time_in_minutes: >
|
remaining_time_in_minutes: >
|
||||||
{% if remaining not in ['unknown', 'unavailable'] %}
|
{% if remaining not in ['unknown', 'unavailable', '-'] %}
|
||||||
{% set parts = remaining.split(':') %}
|
{% set parts = remaining.split(':') %}
|
||||||
{% set total = parts[0]|int * 60 + parts[1]|int %}
|
{% if parts | length >= 2 %}
|
||||||
{{ total }}
|
{% set total = parts[0]|int * 60 + parts[1]|int %}
|
||||||
|
{{ total }}
|
||||||
|
{% else %}
|
||||||
|
{{ 0 }}
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
0
|
{{ 0 }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# JSON global state.
|
# ---------------------------------------------------------------------------
|
||||||
|
# Persistent State Management
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
automation_state_entity: !input automation_state_entity
|
automation_state_entity: !input automation_state_entity
|
||||||
|
|
||||||
|
# Parse global state JSON from input_text entity
|
||||||
automation_state_global: >
|
automation_state_global: >
|
||||||
{% set text = states(automation_state_entity) | string %}
|
{% set text = states(automation_state_entity) | string %}
|
||||||
{% if text in ['unknown','unavailable','none',''] %}
|
{% if text in ['unknown','unavailable','none',''] %}
|
||||||
@@ -211,20 +327,33 @@ variables:
|
|||||||
{% else %}
|
{% else %}
|
||||||
{{ text | from_json }}
|
{{ text | from_json }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
automation_state_placeholder_key: !input automation_state_placeholder_key
|
automation_state_placeholder_key: !input automation_state_placeholder_key
|
||||||
|
|
||||||
|
# Determine the key for this automation's state
|
||||||
automation_state_key: >
|
automation_state_key: >
|
||||||
{% if automation_state_placeholder_key != '' %}
|
{% if automation_state_placeholder_key != '' %}
|
||||||
{{ automation_state_placeholder_key }}
|
{{ automation_state_placeholder_key }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ remaining_time_sensor }}
|
{{ remaining_time_sensor }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
# Get this automation's state from global state
|
||||||
automation_state: "{{ automation_state_global.get(automation_state_key, dict()) }}"
|
automation_state: "{{ automation_state_global.get(automation_state_key, dict()) }}"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Debug Flag
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
is_debug: false
|
is_debug: false
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ACTIONS
|
||||||
|
# =============================================================================
|
||||||
action:
|
action:
|
||||||
|
|
||||||
# Debug info (log if required)
|
# ---------------------------------------------------------------------------
|
||||||
|
# DEBUG: Log current state (enable by setting is_debug: true)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
- choose:
|
- choose:
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
@@ -232,87 +361,112 @@ action:
|
|||||||
sequence:
|
sequence:
|
||||||
- service: persistent_notification.create
|
- service: persistent_notification.create
|
||||||
data:
|
data:
|
||||||
title: "Debug Info"
|
title: "Debug Info - Washing Machine"
|
||||||
message: >
|
message: >
|
||||||
run_state = {{ run_state }},
|
run_state = {{ run_state }},
|
||||||
non_running_state_ids = {{ non_running_state_ids }},
|
non_running_state_ids = {{ non_running_state_ids }},
|
||||||
remaining_time = {{ states(remaining_time_sensor) }},
|
remaining_time = {{ states(remaining_time_sensor) }},
|
||||||
is_running = {{ is_running }},
|
is_running = {{ is_running }},
|
||||||
t = {{ automation_state.get(state_notification_about_start_sent, false) }}
|
start_notification_sent = {{ automation_state.get(state_notification_about_start_sent, false) }}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# MAIN STATE MACHINE - Handle different cycle events
|
||||||
|
# ===========================================================================
|
||||||
- choose:
|
- choose:
|
||||||
# 🟢 Case 1: Washing started
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# CASE 1: Cycle Started
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Triggered when: Device starts running and start notification not yet sent
|
||||||
|
# Action: Send start notification with duration and optional details
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: "{{ not automation_state.get(state_notification_about_start_sent, false) and is_running }}"
|
value_template: >
|
||||||
|
{{ not automation_state.get(state_notification_about_start_sent, false)
|
||||||
|
and is_running }}
|
||||||
sequence:
|
sequence:
|
||||||
- variables:
|
- variables:
|
||||||
startup_info_sensors: !input startup_info_sensors
|
startup_info_sensors: !input startup_info_sensors
|
||||||
startup_info_texts: !input startup_info_texts
|
startup_info_texts: !input startup_info_texts
|
||||||
|
# Build notification message with optional sensor details
|
||||||
message: >
|
message: >
|
||||||
{% set ns = namespace(text = '🧺 ' ~ device_name ~ ': старт. Длительность: `' ~ remaining ~ '`.') %}
|
{% set ns = namespace(text = '🧺 ' ~ device_name ~ ': старт. Длительность: `' ~ remaining ~ '`.') %}
|
||||||
{% for i in range(startup_info_sensors | count) %}
|
{% for i in range(startup_info_sensors | count) %}
|
||||||
{% set ns.text = ns.text ~ ' ' ~ startup_info_texts[i] ~ ': [' ~ states(startup_info_sensors[i]) ~ '].' %}
|
{% set ns.text = ns.text ~ ' ' ~ startup_info_texts[i] ~ ': [' ~ states(startup_info_sensors[i]) ~ '].' %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{{ ns.text }}
|
{{ ns.text }}
|
||||||
|
|
||||||
|
# Send start notification
|
||||||
- service: notify.send_message
|
- service: notify.send_message
|
||||||
target:
|
target:
|
||||||
entity_id: !input notify_target
|
entity_id: !input notify_target
|
||||||
data:
|
data:
|
||||||
message: "{{ message }}"
|
message: "{{ message }}"
|
||||||
|
|
||||||
|
# Mark start notification as sent
|
||||||
- service: input_text.set_value
|
- service: input_text.set_value
|
||||||
target:
|
target:
|
||||||
entity_id: "{{ automation_state_entity }}"
|
entity_id: "{{ automation_state_entity }}"
|
||||||
data:
|
data:
|
||||||
value: >
|
value: >
|
||||||
{% set new_automation_state = (automation_state | combine({ state_notification_about_start_sent: true })) %}
|
{% set new_automation_state = (automation_state | combine({ state_notification_about_start_sent: true })) %}
|
||||||
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
||||||
|
|
||||||
# ✅ Case 2: Run completed
|
# -----------------------------------------------------------------------
|
||||||
|
# CASE 2: Cycle Completed
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Triggered when: Device stops running after cycle was started
|
||||||
|
# Action: Send completion notification and reset all state flags
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ not is_running
|
{{ not is_running
|
||||||
and automation_state.get(state_notification_about_start_sent, false)
|
and automation_state.get(state_notification_about_start_sent, false)
|
||||||
and (states(run_state_sensor) in [run_state_completion_id, 'unknown', '-'] or states(remaining_time_sensor) in ['unknown', '-']) }}
|
and (states(run_state_sensor) in [run_state_completion_id, 'unknown', '-'] or states(remaining_time_sensor) in ['unknown', '-']) }}
|
||||||
sequence:
|
sequence:
|
||||||
|
# Send completion notification
|
||||||
- service: notify.send_message
|
- service: notify.send_message
|
||||||
target:
|
target:
|
||||||
entity_id: !input notify_target
|
entity_id: !input notify_target
|
||||||
data:
|
data:
|
||||||
message: >
|
message: >
|
||||||
🟢 {{ device_name }}: завершено. Не забудьте достать вещи!
|
🟢 {{ device_name }}: завершено. Не забудьте достать вещи!
|
||||||
|
|
||||||
# Reset the state.
|
# Reset all notification flags for next cycle
|
||||||
- service: input_text.set_value
|
- service: input_text.set_value
|
||||||
target:
|
target:
|
||||||
entity_id: "{{ automation_state_entity }}"
|
entity_id: "{{ automation_state_entity }}"
|
||||||
data:
|
data:
|
||||||
value: >
|
value: >
|
||||||
{% set new_automation_state = (automation_state | combine({ state_notification_about_renaming_time_sent: false, state_notification_about_start_sent: false, state_notification_about_preparation_sent: false })) %}
|
{% set new_automation_state = (automation_state | combine({
|
||||||
|
state_notification_about_remaining_time_sent: false,
|
||||||
|
state_notification_about_start_sent: false,
|
||||||
|
state_notification_about_preparation_sent: false
|
||||||
|
})) %}
|
||||||
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
||||||
|
|
||||||
# ✅ Case 3: Preparation
|
# -----------------------------------------------------------------------
|
||||||
|
# CASE 3: Preparation Mode Started
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Triggered when: Device enters preparation state (e.g., dryer heating)
|
||||||
|
# Action: Send preparation notification
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{{ preparation_state_id != ''
|
{{ preparation_state_id != ''
|
||||||
and states(run_state_sensor) == preparation_state_id
|
and states(run_state_sensor) == preparation_state_id
|
||||||
and not automation_state.get(state_notification_about_preparation_sent, false) }}
|
and not automation_state.get(state_notification_about_preparation_sent, false) }}
|
||||||
sequence:
|
sequence:
|
||||||
|
# Mark preparation notification as sent (before sending to prevent duplicates)
|
||||||
# Reset the state.
|
|
||||||
- service: input_text.set_value
|
- service: input_text.set_value
|
||||||
target:
|
target:
|
||||||
entity_id: "{{ automation_state_entity }}"
|
entity_id: "{{ automation_state_entity }}"
|
||||||
data:
|
data:
|
||||||
value: >
|
value: >
|
||||||
{% set new_automation_state = (automation_state | combine({ state_notification_about_preparation_sent: true })) %}
|
{% set new_automation_state = (automation_state | combine({ state_notification_about_preparation_sent: true })) %}
|
||||||
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
||||||
|
|
||||||
|
# Send preparation notification
|
||||||
- service: notify.send_message
|
- service: notify.send_message
|
||||||
target:
|
target:
|
||||||
entity_id: !input notify_target
|
entity_id: !input notify_target
|
||||||
@@ -320,13 +474,22 @@ action:
|
|||||||
message: >
|
message: >
|
||||||
⚙️ {{ device_name }}: подготовка активирована!
|
⚙️ {{ device_name }}: подготовка активирована!
|
||||||
|
|
||||||
# 🔴 Case 4: Error message
|
# -----------------------------------------------------------------------
|
||||||
|
# CASE 4: Error Occurred
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Triggered when: Error message sensor changes to non-empty value
|
||||||
|
# Action: Send error notification with details
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: "{{ trigger.entity_id == error_message_sensor and error|length > 0 }}"
|
value_template: >
|
||||||
|
{{ trigger.entity_id == error_message_sensor
|
||||||
|
and states(error_message_sensor) not in ['', 'unknown', 'unavailable', 'none', '-']
|
||||||
|
and states(error_message_sensor) | length > 0 }}
|
||||||
sequence:
|
sequence:
|
||||||
- variables:
|
- variables:
|
||||||
error: "{{ states(error_message_sensor) }}"
|
error: "{{ states(error_message_sensor) }}"
|
||||||
|
|
||||||
|
# Send error notification
|
||||||
- service: notify.send_message
|
- service: notify.send_message
|
||||||
target:
|
target:
|
||||||
entity_id: !input notify_target
|
entity_id: !input notify_target
|
||||||
@@ -334,36 +497,49 @@ action:
|
|||||||
message: >
|
message: >
|
||||||
⚠️ {{ device_name }}: ошибка. Детали: {{ error }}. Для более подробной информации обратитесь к приложению LG ThinQ.
|
⚠️ {{ device_name }}: ошибка. Детали: {{ error }}. Для более подробной информации обратитесь к приложению LG ThinQ.
|
||||||
|
|
||||||
# ⏰ Case 5: Notify before end
|
# -----------------------------------------------------------------------
|
||||||
|
# CASE 5: Almost Done (Time-to-End Notification)
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Triggered when: Remaining time drops below threshold
|
||||||
|
# Action: Send "almost done" notification
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: >
|
value_template: >
|
||||||
{% if not automation_state.get(state_notification_about_renaming_time_sent, false) and is_running %}
|
{{ not automation_state.get(state_notification_about_remaining_time_sent, false)
|
||||||
{{ remaining_time_in_minutes <= notify_time_to_end }}
|
and is_running
|
||||||
{% else %}
|
and remaining_time_in_minutes <= notify_time_to_end
|
||||||
{{ false }}
|
and remaining_time_in_minutes > 0 }}
|
||||||
{% endif %}
|
|
||||||
sequence:
|
sequence:
|
||||||
|
# Mark time-to-end notification as sent
|
||||||
- service: input_text.set_value
|
- service: input_text.set_value
|
||||||
target:
|
target:
|
||||||
entity_id: "{{ automation_state_entity }}"
|
entity_id: "{{ automation_state_entity }}"
|
||||||
data:
|
data:
|
||||||
value: >
|
value: >
|
||||||
{% set new_automation_state = (automation_state | combine({ state_notification_about_renaming_time_sent: true })) %}
|
{% set new_automation_state = (automation_state | combine({ state_notification_about_remaining_time_sent: true })) %}
|
||||||
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
||||||
|
|
||||||
|
# Send "almost done" notification
|
||||||
- service: notify.send_message
|
- service: notify.send_message
|
||||||
target:
|
target:
|
||||||
entity_id: !input notify_target
|
entity_id: !input notify_target
|
||||||
data:
|
data:
|
||||||
message: >
|
message: >
|
||||||
🟢 {{ device_name }}: завершение через {{ remaining.split(':')[1] }} минут.
|
🟢 {{ device_name }}: завершение через {{ remaining.split(':')[1] | int }} минут.
|
||||||
|
|
||||||
# 🔴 Case 6: Tub clean notification
|
# -----------------------------------------------------------------------
|
||||||
|
# CASE 6: Tub Cleaning Reminder
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# Triggered when: Tub clean counter exceeds threshold
|
||||||
|
# Action: Send tub cleaning reminder
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: "{{ trigger.entity_id == tub_clean_counter_sensor and tub_clean_counter_threshold != 0 and (states(tub_clean_counter_sensor) | int) > tub_clean_counter_threshold }}"
|
value_template: >
|
||||||
|
{{ trigger.entity_id == tub_clean_counter_sensor
|
||||||
|
and tub_clean_counter_threshold != 0
|
||||||
|
and (states(tub_clean_counter_sensor) | int(0)) > tub_clean_counter_threshold }}
|
||||||
sequence:
|
sequence:
|
||||||
|
# Send tub cleaning reminder
|
||||||
- service: notify.send_message
|
- service: notify.send_message
|
||||||
target:
|
target:
|
||||||
entity_id: !input notify_target
|
entity_id: !input notify_target
|
||||||
@@ -371,4 +547,4 @@ action:
|
|||||||
message: >
|
message: >
|
||||||
⚠️ {{ device_name }}: внимание. Необходима чистка барабана.
|
⚠️ {{ device_name }}: внимание. Необходима чистка барабана.
|
||||||
Число стирок: {{ states(tub_clean_counter_sensor) | int }}.
|
Число стирок: {{ states(tub_clean_counter_sensor) | int }}.
|
||||||
Допустимый предел: {{ tub_clean_counter_threshold }}.
|
Допустимый предел: {{ tub_clean_counter_threshold }}.
|
||||||
|
|||||||
Reference in New Issue
Block a user