Files
haos-blueprints/Common/Dreame Vacuum/blueprint.yaml
T
alexei.dolgolyov a52cffa062 fix: remove notification title from Dreame Vacuum to avoid duplicated device name
The `notification_title` input defaulted to `{vacuum_name}`, which caused the
device name to appear twice (once in the title, once in the message body that
already starts with `{vacuum_name}`). Drop the title input and revert to
message-only notifications, matching the original behavior.
2026-05-07 22:11:21 +03:00

444 lines
17 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Dreame Vacuum Notifications
# Sends notifications for Dreame vacuum events (cleaning, errors, consumables).
# See README.md for detailed documentation.
#
# Author: Alexei Dolgolyov (dolgolyov.alexei@gmail.com)
blueprint:
name: "Custom: Dreame Vacuum Notifications"
description: >
Sends customizable notifications for Dreame vacuum events including
cleaning status, consumable alerts, warnings, and errors.
Requires the Dreame Vacuum integration (github.com/Tasshack/dreame-vacuum).
domain: automation
# ===========================================================================
# INPUT CONFIGURATION
# ===========================================================================
input:
# -------------------------------------------------------------------------
# Vacuum Configuration
# -------------------------------------------------------------------------
vacuum_group:
name: "Vacuum"
collapsed: false
input:
vacuum_entity:
name: Vacuum Entity
description: "The Dreame vacuum entity to monitor."
selector:
entity:
integration: dreame_vacuum
domain: vacuum
# -------------------------------------------------------------------------
# Notification Configuration
# -------------------------------------------------------------------------
notification_group:
name: "Notification"
collapsed: false
input:
notify_targets:
name: Notification Targets
description: "Notification service entities to send messages to (select one or more)."
selector:
entity:
domain: notify
multiple: true
# -------------------------------------------------------------------------
# Event Toggles
# -------------------------------------------------------------------------
toggles_group:
name: "Event Toggles"
collapsed: false
input:
enable_cleaning_started:
name: Cleaning Started
description: "Send notification when the vacuum starts cleaning."
default: true
selector:
boolean:
enable_cleaning_completed:
name: Cleaning Completed
description: "Send notification when the vacuum finishes cleaning."
default: true
selector:
boolean:
enable_consumable:
name: Consumable Depleted
description: "Send notification when a consumable reaches end-of-life."
default: true
selector:
boolean:
enable_warning:
name: Warning
description: "Send notification for device warnings."
default: true
selector:
boolean:
enable_error:
name: Error
description: "Send notification for device errors."
default: true
selector:
boolean:
enable_information:
name: Information
description: "Send notification for informational alerts (e.g., blocked by DND)."
default: true
selector:
boolean:
# -------------------------------------------------------------------------
# Filtering
# -------------------------------------------------------------------------
filters_group:
name: "Filtering"
collapsed: true
input:
warning_codes_ignore:
name: Warning Codes to Ignore
description: >
List of warning codes to silence (one entry per code, as text).
Useful for suppressing routine warnings while keeping critical ones.
default: []
selector:
text:
multiple: true
error_codes_ignore:
name: Error Codes to Ignore
description: >
List of error codes to silence (one entry per code, as text).
default: []
selector:
text:
multiple: true
information_codes_ignore:
name: Information Codes to Ignore
description: >
List of information codes to silence (one entry per code, as text).
default: []
selector:
text:
multiple: true
# -------------------------------------------------------------------------
# Message Templates
# -------------------------------------------------------------------------
messages_group:
name: "Message Templates"
collapsed: true
input:
message_cleaning_started:
name: "Cleaning Started Message"
description: >
Message sent when the vacuum starts cleaning.
Variables: `{vacuum_name}`, `{cleaning_mode}`, `{status}`
default: "🧹 {vacuum_name} started cleaning ({cleaning_mode})."
selector:
text:
multiline: true
message_cleaning_completed:
name: "Cleaning Completed Message"
description: >
Message sent when the vacuum finishes cleaning.
Variables: `{vacuum_name}`, `{cleaning_mode}`, `{status}`,
`{cleaned_area}`, `{cleaning_time}`
default: "✅ {vacuum_name} finished cleaning. Area: {cleaned_area} m², time: {cleaning_time} min."
selector:
text:
multiline: true
message_consumable:
name: "Consumable Depleted Message"
description: >
Message sent when a consumable reaches end-of-life.
Variables: `{vacuum_name}`, `{consumable}`
default: "🔧 {vacuum_name}: {consumable} needs replacement."
selector:
text:
multiline: true
message_warning:
name: "Warning Message"
description: >
Message sent for device warnings.
Variables: `{vacuum_name}`, `{warning}`, `{code}`
default: "⚠️ {vacuum_name} warning: {warning} (code: {code})."
selector:
text:
multiline: true
message_error:
name: "Error Message"
description: >
Message sent for device errors.
Variables: `{vacuum_name}`, `{error}`, `{code}`
default: "❌ {vacuum_name} error: {error} (code: {code})."
selector:
text:
multiline: true
message_information:
name: "Information Message"
description: >
Message sent for informational alerts.
Variables: `{vacuum_name}`, `{information}`, `{code}`
default: "️ {vacuum_name}: {information}."
selector:
text:
multiline: true
# -------------------------------------------------------------------------
# Debug
# -------------------------------------------------------------------------
debug:
name: "Debug"
collapsed: true
input:
enable_debug_notifications:
name: Enable Debug Notifications
description: >
Send persistent notifications for debugging automation behavior.
Shows raw event data, dispatched event kind, and the enable decision.
default: false
selector:
boolean:
# Queued mode to avoid dropping rapid events
mode: queued
max: 5
# =============================================================================
# TRIGGERS
# =============================================================================
trigger:
# Cleaning job started or completed
- platform: event
event_type: dreame_vacuum_task_status
id: "task_status"
# Consumable reached end-of-life
- platform: event
event_type: dreame_vacuum_consumable
id: "consumable"
# Informational alert (job blocked by user settings)
- platform: event
event_type: dreame_vacuum_information
id: "information"
# Dismissible device warning
- platform: event
event_type: dreame_vacuum_warning
id: "warning"
# Device fault
- platform: event
event_type: dreame_vacuum_error
id: "error"
# =============================================================================
# VARIABLES
# =============================================================================
variables:
# Bumped whenever event-handling logic changes; surfaced in debug output
# so users can confirm which revision is running.
blueprint_version: "1.1.1"
# ---------------------------------------------------------------------------
# Input References
# ---------------------------------------------------------------------------
vacuum_entity: !input vacuum_entity
notify_targets: !input notify_targets
enable_debug_notifications: !input enable_debug_notifications
# Event toggles
enable_cleaning_started: !input enable_cleaning_started
enable_cleaning_completed: !input enable_cleaning_completed
enable_consumable: !input enable_consumable
enable_warning: !input enable_warning
enable_error: !input enable_error
enable_information: !input enable_information
# Filter lists (lists of strings)
warning_codes_ignore: !input warning_codes_ignore
error_codes_ignore: !input error_codes_ignore
information_codes_ignore: !input information_codes_ignore
# Message templates
message_cleaning_started_template: !input message_cleaning_started
message_cleaning_completed_template: !input message_cleaning_completed
message_consumable_template: !input message_consumable
message_warning_template: !input message_warning
message_error_template: !input message_error
message_information_template: !input message_information
# ---------------------------------------------------------------------------
# Vacuum Info
# ---------------------------------------------------------------------------
vacuum_name: "{{ state_attr(vacuum_entity, 'friendly_name') | default(vacuum_entity) }}"
vacuum_device: "{{ device_id(vacuum_entity) | default('', true) }}"
# ---------------------------------------------------------------------------
# Event Data (flat structure — fields are directly on trigger.event.data)
# ---------------------------------------------------------------------------
event_entity_id: "{{ trigger.event.data.entity_id | default('') }}"
event_device_id: "{{ trigger.event.data.device_id | default('') }}"
# Task status fields
task_cleaning_mode: "{{ trigger.event.data.cleaning_mode | default('unknown') }}"
task_status_value: "{{ trigger.event.data.status | default('unknown') }}"
task_completed: "{{ trigger.event.data.completed | default(false) }}"
task_cleaned_area: "{{ trigger.event.data.cleaned_area | default(0) }}"
task_cleaning_time: "{{ trigger.event.data.cleaning_time | default(0) }}"
# Consumable fields
consumable_name: "{{ (trigger.event.data.consumable | default('unknown')) | replace('_', ' ') | title }}"
# Warning fields
warning_description: "{{ trigger.event.data.warning | default('unknown') }}"
warning_code: "{{ trigger.event.data.code | default('') }}"
# Error fields
error_description: "{{ trigger.event.data.error | default('unknown') }}"
error_code: "{{ trigger.event.data.code | default('') }}"
# Information fields
information_description: "{{ (trigger.event.data.information | default('unknown')) | replace('_', ' ') | title }}"
information_code: "{{ trigger.event.data.code | default('') }}"
# ---------------------------------------------------------------------------
# Event Dispatch
# ---------------------------------------------------------------------------
# Map the raw trigger to a single logical event kind. Keeping this in one
# place avoids the duplicated condition logic that the old multi-branch
# `choose` had.
event_kind: >
{%- if trigger.id == 'task_status' and not task_completed -%}cleaning_started
{%- elif trigger.id == 'task_status' and task_completed -%}cleaning_completed
{%- elif trigger.id == 'consumable' -%}consumable
{%- elif trigger.id == 'warning' -%}warning
{%- elif trigger.id == 'error' -%}error
{%- elif trigger.id == 'information' -%}information
{%- else -%}none
{%- endif -%}
# Whether this event should produce a notification, given user toggles
# and any per-code filter lists. Coerce with `| bool(false)` at the
# consumer because folded scalars can render as the string "True"/"False".
event_enabled: >
{%- if event_kind == 'cleaning_started' -%}{{ enable_cleaning_started }}
{%- elif event_kind == 'cleaning_completed' -%}{{ enable_cleaning_completed }}
{%- elif event_kind == 'consumable' -%}{{ enable_consumable }}
{%- elif event_kind == 'warning' -%}{{ enable_warning and (warning_code | string) not in warning_codes_ignore }}
{%- elif event_kind == 'error' -%}{{ enable_error and (error_code | string) not in error_codes_ignore }}
{%- elif event_kind == 'information' -%}{{ enable_information and (information_code | string) not in information_codes_ignore }}
{%- else -%}False
{%- endif -%}
# Pick the per-event message template.
message_template: >
{%- if event_kind == 'cleaning_started' -%}{{ message_cleaning_started_template }}
{%- elif event_kind == 'cleaning_completed' -%}{{ message_cleaning_completed_template }}
{%- elif event_kind == 'consumable' -%}{{ message_consumable_template }}
{%- elif event_kind == 'warning' -%}{{ message_warning_template }}
{%- elif event_kind == 'error' -%}{{ message_error_template }}
{%- elif event_kind == 'information' -%}{{ message_information_template }}
{%- else -%}{%- endif -%}
# Render the message. Placeholders that don't apply to this event are
# absent from the chosen template, so `replace()` is a no-op for them.
message: >
{%- set code_for_event = warning_code if event_kind == 'warning'
else (error_code if event_kind == 'error'
else (information_code if event_kind == 'information' else '')) -%}
{{ message_template
| replace('{vacuum_name}', vacuum_name)
| replace('{cleaning_mode}', task_cleaning_mode)
| replace('{status}', task_status_value)
| replace('{cleaned_area}', task_cleaned_area | string)
| replace('{cleaning_time}', task_cleaning_time | string)
| replace('{consumable}', consumable_name)
| replace('{warning}', warning_description)
| replace('{error}', error_description)
| replace('{information}', information_description)
| replace('{code}', code_for_event | string) }}
# =============================================================================
# CONDITIONS
# =============================================================================
condition:
# Only process events from the configured vacuum.
# Prefer device_id matching when the event payload carries it (most
# reliable across firmware revisions and avoids prefix collisions when
# multiple Dreame vacuums share an entity_id stem).
# Fall back to entity_id matching: the integration uses generate_entity_id(),
# which may append a numeric suffix (e.g., `_2`) when the base entity_id
# is taken — so we accept the configured entity_id with an optional
# purely numeric suffix and reject non-numeric suffixes (e.g., `_pro`).
- condition: template
value_template: >
{%- if event_device_id != '' and vacuum_device != '' -%}
{{ event_device_id == vacuum_device }}
{%- elif event_entity_id == vacuum_entity -%}
true
{%- elif event_entity_id.startswith(vacuum_entity ~ '_') -%}
{{ event_entity_id[(vacuum_entity | length) + 1:].isdigit() }}
{%- else -%}
false
{%- endif -%}
# =============================================================================
# ACTIONS
# =============================================================================
action:
# ---------------------------------------------------------------------------
# Debug Logging
# ---------------------------------------------------------------------------
- choose:
- conditions:
- condition: template
value_template: "{{ enable_debug_notifications }}"
sequence:
- action: persistent_notification.create
data:
notification_id: "dreame_vacuum_debug_{{ vacuum_entity }}"
title: "Dreame Vacuum Debug — {{ vacuum_name }}"
message: >
**Blueprint version:** {{ blueprint_version }}
**Trigger:** {{ trigger.id }}
**Event kind:** {{ event_kind }}
**Enabled:** {{ event_enabled }}
**Entity:** {{ event_entity_id }}
**Device:** {{ event_device_id }}
**Vacuum:** {{ vacuum_name }}
**Event Data:** {{ trigger.event.data }}
# ---------------------------------------------------------------------------
# Send Notification
# ---------------------------------------------------------------------------
# Single dispatch — message and the enable decision are computed in the
# variables block above. We just gate on the resolved flags here.
- choose:
- conditions:
- condition: template
value_template: "{{ event_kind != 'none' and (event_enabled | bool(false)) }}"
sequence:
- action: notify.send_message
target:
entity_id: "{{ notify_targets }}"
data:
message: "{{ message }}"