276 lines
11 KiB
YAML
276 lines
11 KiB
YAML
################################################################################
|
|
# PACKAGE: Appliances Status Monitoring
|
|
################################################################################
|
|
#
|
|
# Version: 1.4
|
|
# Date: 2026-06-09
|
|
#
|
|
# Purpose:
|
|
# Appliance status monitoring package for multiple appliances.
|
|
#
|
|
# This package defines a central appliance registry and one automation that:
|
|
#
|
|
# 1. Publishes MQTT discovery config for each appliance monitor sensor.
|
|
# 2. Samples appliance power sensors once per minute.
|
|
# 3. Calls script.appliance_monitor_process_sample.
|
|
#
|
|
# Processor package required:
|
|
# appliance_monitor_processor.yaml
|
|
#
|
|
# Announcement router required:
|
|
# view_road_announcement_router.yaml
|
|
#
|
|
# MQTT:
|
|
# MQTT is used only as retained state storage for appliance monitor sensors.
|
|
# Sensor entities are created using MQTT discovery.
|
|
#
|
|
# Adding another appliance:
|
|
# Add one entry to the am_appliances list.
|
|
#
|
|
# Version 1.4:
|
|
# Added min_cycle_notify_seconds support.
|
|
# Default is 300 seconds, so cycles shorter than 5 minutes are recorded but
|
|
# do not send finished notifications.
|
|
# Per-appliance overrides can be set in the am_appliances list.
|
|
#
|
|
# Version 1.3:
|
|
# Removed the is_number gate before calling the processor. The processor is
|
|
# now always called once per appliance per sample, and power is safely converted
|
|
# to 0 if the source sensor is unavailable or non-numeric.
|
|
#
|
|
################################################################################
|
|
|
|
automation:
|
|
- id: appliances_status_monitoring_process_samples
|
|
alias: Appliances Status Monitoring - Process Samples
|
|
description: Publish MQTT discovery, sample appliance power sensors, and process appliance status/cycle data.
|
|
mode: queued
|
|
max: 20
|
|
|
|
trigger:
|
|
- platform: homeassistant
|
|
event: start
|
|
id: ha_start
|
|
|
|
- platform: time_pattern
|
|
minutes: "/1"
|
|
id: periodic_sample
|
|
|
|
variables:
|
|
##########################################################################
|
|
# MQTT LOCAL CONTROLS
|
|
##########################################################################
|
|
|
|
mqtt_device_name: "appliance_monitor"
|
|
mqtt_local_status_topic: !secret mqtt_status_main_topic
|
|
mqtt_discovery_prefix: "homeassistant"
|
|
|
|
##########################################################################
|
|
# DEFAULTS
|
|
##########################################################################
|
|
|
|
am_default_debug_flow: false
|
|
am_default_resolution: 2
|
|
am_default_standby_power: 2
|
|
am_default_operating_power_min: 12
|
|
am_default_min_cycle_notify_seconds: 300
|
|
|
|
#am_default_announcement_channels: "pushover_zorruno, sony_tv_lounge, lounge_google_home_voice, led_matrix_1"
|
|
am_default_announcement_channels: "pushover_zorruno"
|
|
|
|
# Optional appliance-specific overrides available:
|
|
# resolution: 4
|
|
# The number of samples for the average, with one sample per minute.
|
|
#
|
|
# standby_power: 3
|
|
# Below this value, the appliance will show "Off".
|
|
# Between this value and operating_power_min, it will show "Standby".
|
|
#
|
|
# operating_power_min: 20
|
|
# The minimum average power needed for the appliance to show "Operating".
|
|
#
|
|
# min_cycle_notify_seconds: 600
|
|
# Finished cycles shorter than this are recorded, but no notification
|
|
# is sent. Default is 300 seconds.
|
|
#
|
|
# announcement_channels: "pushover_zorruno"
|
|
# Announcement channels for this appliance.
|
|
#
|
|
# long_announcement: "The device has finished. Please empty it when convenient."
|
|
# Override the long announcement.
|
|
#
|
|
# min_cycle_notify_seconds: 600
|
|
# Minimum time for an appliance to be operating before a completion announcement generated.
|
|
|
|
##########################################################################
|
|
# APPLIANCE REGISTRY
|
|
##########################################################################
|
|
|
|
am_appliances:
|
|
- appliance_id: washing_machine
|
|
appliance_name: "Washing Machine"
|
|
appliance_action: "washing2"
|
|
power_entity: "sensor.esp_laundrywashpow_load_power"
|
|
icon: "mdi:washing-machine"
|
|
short_announcement: "/s/sWashing complete"
|
|
# long_announcement: # Created by the processor
|
|
matrix_indicator: "wash,1,15,10,6,5,1,0"
|
|
# Optional washing-machine-specific overrides
|
|
resolution: 5
|
|
standby_power: 3
|
|
operating_power_min: 10
|
|
announcement_channels: "pushover_zorruno"
|
|
|
|
- appliance_id: dryer
|
|
appliance_name: "Dryer"
|
|
appliance_action: "drying2"
|
|
power_entity: "sensor.esp_laundrydrypow_load_power"
|
|
icon: "mdi:tumble-dryer"
|
|
short_announcement: "/s/sDryer complete"
|
|
# long_announcement: # Created by the processor
|
|
matrix_indicator: "dry,1,15,10,6,5,1,0"
|
|
# Optional dryer-specific overrides
|
|
resolution: 4
|
|
standby_power: 3
|
|
operating_power_min: 10
|
|
announcement_channels: "pushover_zorruno"
|
|
|
|
- appliance_id: main_dishwasher
|
|
appliance_name: "Main Dishwasher"
|
|
appliance_action: "dishwashing2"
|
|
power_entity: "sensor.esp_maindishwasherpower_power"
|
|
icon: "mdi:dishwasher"
|
|
short_announcement: "/sDishwasher complete"
|
|
# long_announcement: # Created by the processor
|
|
matrix_indicator: "dish,1,15,10,6,5,1,0"
|
|
|
|
- appliance_id: evcharger_32a
|
|
appliance_name: "EV Charger (32A)"
|
|
appliance_action: "EV charging (32A)"
|
|
power_entity: "sensor.main_house_3_phase_power_monitor_32a_wallcharger_power"
|
|
monitor_sensor: "sensor.appliance_monitor_ev_charger_32a_monitor"
|
|
icon: "mdi:ev-plug-type2"
|
|
short_announcement: "/s/s32A EV Charging complete"
|
|
# long_announcement: # Created by the processor
|
|
matrix_indicator: "ev32a,1,15,10,6,5,1,0"
|
|
resolution: 6
|
|
standby_power: 3
|
|
operating_power_min: 50
|
|
announcement_channels: "pushover_zorruno"
|
|
|
|
action:
|
|
##########################################################################
|
|
# PUBLISH / REFRESH MQTT DISCOVERY CONFIG
|
|
##########################################################################
|
|
|
|
- repeat:
|
|
for_each: "{{ am_appliances }}"
|
|
sequence:
|
|
- variables:
|
|
am_state_topic: >-
|
|
{{ mqtt_local_status_topic }}/{{ mqtt_device_name }}/{{ repeat.item.appliance_id }}/state
|
|
|
|
am_discovery_topic: >-
|
|
{{ mqtt_discovery_prefix }}/sensor/{{ mqtt_device_name }}_{{ repeat.item.appliance_id }}/config
|
|
|
|
am_unique_id: >-
|
|
{{ repeat.item.appliance_id }}_monitor
|
|
|
|
am_object_id: >-
|
|
{{ mqtt_device_name }}_{{ repeat.item.appliance_id }}_monitor
|
|
|
|
- action: mqtt.publish
|
|
data:
|
|
topic: "{{ am_discovery_topic }}"
|
|
retain: true
|
|
qos: 0
|
|
payload: >-
|
|
{{
|
|
dict(
|
|
name=repeat.item.appliance_name ~ ' Monitor',
|
|
unique_id=am_unique_id,
|
|
object_id=am_object_id,
|
|
icon=repeat.item.icon | default('mdi:power-plug'),
|
|
state_topic=am_state_topic,
|
|
value_template='{{ value_json.state | default("Off") }}',
|
|
json_attributes_topic=am_state_topic,
|
|
device=dict(
|
|
identifiers=[mqtt_device_name],
|
|
name='Appliance Monitor',
|
|
manufacturer='View Road Home Assistant',
|
|
model='Shared appliance power monitor'
|
|
)
|
|
) | to_json
|
|
}}
|
|
|
|
##########################################################################
|
|
# PROCESS SAMPLES
|
|
##########################################################################
|
|
#
|
|
# Always process every appliance. The processor receives power_w as a safe
|
|
# float value, so unavailable/non-numeric sensors become 0 W.
|
|
#
|
|
##########################################################################
|
|
|
|
- repeat:
|
|
for_each: "{{ am_appliances }}"
|
|
sequence:
|
|
- variables:
|
|
am_state_topic: >-
|
|
{{ mqtt_local_status_topic }}/{{ mqtt_device_name }}/{{ repeat.item.appliance_id }}/state
|
|
|
|
am_monitor_sensor: >-
|
|
{{
|
|
repeat.item.monitor_sensor
|
|
| default('sensor.' ~ mqtt_device_name ~ '_' ~ repeat.item.appliance_id ~ '_monitor', true)
|
|
}}
|
|
|
|
am_title: >-
|
|
{{ repeat.item.title | default(repeat.item.appliance_name ~ ' Notification', true) }}
|
|
|
|
am_announcement_channels: >-
|
|
{{ repeat.item.announcement_channels | default(am_default_announcement_channels, true) }}
|
|
|
|
am_debug_flow: >-
|
|
{{ repeat.item.debug_flow | default(am_default_debug_flow, true) }}
|
|
|
|
am_resolution: >-
|
|
{{ repeat.item.resolution | default(am_default_resolution, true) }}
|
|
|
|
am_standby_power: >-
|
|
{{ repeat.item.standby_power | default(am_default_standby_power, true) }}
|
|
|
|
am_operating_power_min: >-
|
|
{{ repeat.item.operating_power_min | default(am_default_operating_power_min, true) }}
|
|
|
|
am_min_cycle_notify_seconds: >-
|
|
{{ repeat.item.min_cycle_notify_seconds | default(am_default_min_cycle_notify_seconds, true) }}
|
|
|
|
am_power_w: >-
|
|
{{ states(repeat.item.power_entity) | float(0) }}
|
|
|
|
am_long_announcement: >-
|
|
{{ repeat.item.long_announcement | default('', true) }}
|
|
|
|
- action: script.appliance_monitor_process_sample
|
|
data:
|
|
appliance_id: "{{ repeat.item.appliance_id }}"
|
|
appliance_name: "{{ repeat.item.appliance_name }}"
|
|
appliance_action: "{{ repeat.item.appliance_action }}"
|
|
|
|
power_w: "{{ am_power_w }}"
|
|
monitor_sensor: "{{ am_monitor_sensor }}"
|
|
state_topic: "{{ am_state_topic }}"
|
|
|
|
debug_flow: "{{ am_debug_flow }}"
|
|
resolution: "{{ am_resolution }}"
|
|
standby_power: "{{ am_standby_power }}"
|
|
operating_power_min: "{{ am_operating_power_min }}"
|
|
min_cycle_notify_seconds: "{{ am_min_cycle_notify_seconds }}"
|
|
|
|
announcement_channels: "{{ am_announcement_channels }}"
|
|
short_announcement: "{{ repeat.item.short_announcement }}"
|
|
long_announcement: "{{ am_long_announcement }}"
|
|
title: "{{ am_title }}"
|
|
matrix_indicator: "{{ repeat.item.matrix_indicator }}"
|