various packages
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
# PACKAGE: Appliance Monitor Processor
|
||||
################################################################################
|
||||
#
|
||||
# Version: 1.2
|
||||
# Date: 2026-06-09
|
||||
# Version: 1.3
|
||||
# Date: 2026-07-11
|
||||
#
|
||||
# Purpose:
|
||||
# Shared appliance power monitoring processor.
|
||||
@@ -20,6 +20,7 @@
|
||||
# - One MQTT sensor per appliance.
|
||||
# - Timestamp-based energy and cost calculation.
|
||||
# - Rolling average state detection.
|
||||
# - Completion announcements through script.view_road_announcement.
|
||||
#
|
||||
# Default values:
|
||||
# debug_flow: false
|
||||
@@ -40,6 +41,16 @@
|
||||
# Finished
|
||||
#
|
||||
# Notes:
|
||||
# Version 1.3:
|
||||
# - Updated completion announcements to support all current View Road
|
||||
# announcement router channels.
|
||||
# - Added pushover_kim to the default appliance completion channels.
|
||||
# - Added mqtt_view_rd_feed support by passing mqtt_feed to the announcement
|
||||
# router.
|
||||
# - Added led_matrix_2 support.
|
||||
# - Added optional announcement_enabled and announcement_payload fields.
|
||||
# - Kept existing field names for backwards compatibility.
|
||||
#
|
||||
# Version 1.2:
|
||||
# - Added min_cycle_notify_seconds.
|
||||
# - Finished cycles shorter than this are still recorded, but do not send
|
||||
@@ -53,17 +64,39 @@
|
||||
#
|
||||
################################################################################
|
||||
# FINISHED ANNOUNCEMENT
|
||||
# The finishing script calls the package view_road_announcement_router.yaml.
|
||||
# If you want to use your own announcement system, it will occur at the end
|
||||
# at am_cycle_notify_allowed being true, so change to your own announcement
|
||||
# method there.
|
||||
################################################################################
|
||||
#
|
||||
# The finishing script calls:
|
||||
#
|
||||
# script.view_road_announcement
|
||||
#
|
||||
# Current View Road announcement router channels:
|
||||
# pushover_zorruno
|
||||
# pushover_kim
|
||||
# sony_tv_lounge
|
||||
# lounge_google_home_voice
|
||||
# google_home_voice
|
||||
# lounge_touchscreen_voice
|
||||
# mqtt_view_rd_feed
|
||||
# led_matrix_1
|
||||
# led_matrix_2
|
||||
#
|
||||
# Notes:
|
||||
# - google_home_voice is an alias for lounge_google_home_voice.
|
||||
# - lounge_touchscreen_voice is currently a placeholder route in the router.
|
||||
# - mqtt_view_rd_feed requires mqtt_feed to be populated.
|
||||
# - led_matrix_1 and led_matrix_2 use short_announcement and indicator.
|
||||
#
|
||||
# Announcements can use:
|
||||
# am_announcement_channels
|
||||
# am_announcement_title
|
||||
# am_short_announcement
|
||||
# am_long_announcement
|
||||
# am_matrix_indicator
|
||||
# announcement_enabled
|
||||
# announcement_channels
|
||||
# title
|
||||
# short_announcement
|
||||
# long_announcement
|
||||
# announcement_payload
|
||||
# payload
|
||||
# matrix_indicator
|
||||
# mqtt_feed
|
||||
#
|
||||
################################################################################
|
||||
|
||||
@@ -127,6 +160,59 @@ script:
|
||||
step: 1
|
||||
unit_of_measurement: s
|
||||
|
||||
announcement_enabled:
|
||||
name: Announcement Enabled
|
||||
description: Whether a valid finished cycle should send an announcement.
|
||||
default: true
|
||||
selector:
|
||||
boolean:
|
||||
|
||||
announcement_channels:
|
||||
name: Announcement Channels
|
||||
description: Comma-separated View Road announcement router channels.
|
||||
default: "pushover_zorruno, pushover_kim, sony_tv_lounge, lounge_google_home_voice, mqtt_view_rd_feed, led_matrix_1"
|
||||
selector:
|
||||
text:
|
||||
|
||||
title:
|
||||
name: Announcement Title
|
||||
description: Announcement title passed to the View Road announcement router.
|
||||
selector:
|
||||
text:
|
||||
|
||||
short_announcement:
|
||||
name: Short Announcement
|
||||
description: Short announcement text for TV, voice and LED matrix.
|
||||
selector:
|
||||
text:
|
||||
|
||||
long_announcement:
|
||||
name: Long Announcement
|
||||
description: Long announcement text for Pushover and detailed channels.
|
||||
selector:
|
||||
text:
|
||||
multiline: true
|
||||
|
||||
announcement_payload:
|
||||
name: Announcement Payload
|
||||
description: Optional payload passed to the announcement router.
|
||||
selector:
|
||||
text:
|
||||
|
||||
matrix_indicator:
|
||||
name: Matrix Indicator
|
||||
description: LED matrix indicator data.
|
||||
example: "wash,1,15,10,6,5,1,0"
|
||||
selector:
|
||||
text:
|
||||
|
||||
mqtt_feed:
|
||||
name: MQTT Activity Feed
|
||||
description: Activity feed topic suffix used by mqtt_view_rd_feed.
|
||||
example: "washing_machine"
|
||||
selector:
|
||||
text:
|
||||
|
||||
sequence:
|
||||
##########################################################################
|
||||
# CORE DEFAULTS AND PASSED VALUES
|
||||
@@ -156,10 +242,36 @@ script:
|
||||
##########################################################################
|
||||
# ANNOUNCEMENT DEFAULTS AND PASSED VALUES
|
||||
##########################################################################
|
||||
#
|
||||
# These values are passed to script.view_road_announcement when an
|
||||
# appliance cycle successfully finishes.
|
||||
#
|
||||
# Current supported router channels:
|
||||
# pushover_zorruno
|
||||
# pushover_kim
|
||||
# sony_tv_lounge
|
||||
# lounge_google_home_voice
|
||||
# google_home_voice
|
||||
# lounge_touchscreen_voice
|
||||
# mqtt_view_rd_feed
|
||||
# led_matrix_1
|
||||
# led_matrix_2
|
||||
#
|
||||
# Notes:
|
||||
# - google_home_voice is an alias for lounge_google_home_voice.
|
||||
# - lounge_touchscreen_voice is currently a placeholder route.
|
||||
# - mqtt_view_rd_feed requires mqtt_feed to be populated.
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
- variables:
|
||||
am_announcement_enabled: "{{ announcement_enabled | default(true, true) | bool(true) }}"
|
||||
|
||||
am_default_announcement_channels: >-
|
||||
pushover_zorruno, pushover_kim, sony_tv_lounge, lounge_google_home_voice, mqtt_view_rd_feed, led_matrix_1
|
||||
|
||||
am_announcement_channels: >-
|
||||
{{ announcement_channels | default('pushover_zorruno, sony_tv_lounge, lounge_google_home_voice, led_matrix_1', true) | string }}
|
||||
{{ announcement_channels | default(am_default_announcement_channels, true) | string }}
|
||||
|
||||
am_short_announcement: >-
|
||||
{{ short_announcement | default((am_appliance_action | title) ~ ' complete', true) | string }}
|
||||
@@ -170,7 +282,20 @@ script:
|
||||
am_announcement_title: >-
|
||||
{{ title | default(am_appliance_name ~ ' Notification', true) | string }}
|
||||
|
||||
am_matrix_indicator: "{{ matrix_indicator | default('', true) | string }}"
|
||||
am_announcement_payload: >-
|
||||
{% if announcement_payload is defined %}
|
||||
{{ announcement_payload }}
|
||||
{% elif payload is defined %}
|
||||
{{ payload }}
|
||||
{% else %}
|
||||
{{ '' }}
|
||||
{% endif %}
|
||||
|
||||
am_matrix_indicator: >-
|
||||
{{ matrix_indicator | default('', true) | string }}
|
||||
|
||||
am_mqtt_feed: >-
|
||||
{{ mqtt_feed | default(am_appliance_id, true) | string }}
|
||||
|
||||
##########################################################################
|
||||
# PREVIOUS STATE FROM MQTT MONITOR SENSOR ATTRIBUTES
|
||||
@@ -622,6 +747,12 @@ script:
|
||||
and (am_cycle_duration_seconds_new | int(0)) >= (am_min_cycle_notify_seconds | int(300))
|
||||
}}
|
||||
|
||||
am_cycle_announcement_allowed: >-
|
||||
{{
|
||||
am_cycle_notify_allowed | bool(false)
|
||||
and am_announcement_enabled | bool(true)
|
||||
}}
|
||||
|
||||
am_cycle_notification_suppressed: >-
|
||||
{{
|
||||
am_cycle_finished | bool(false)
|
||||
@@ -631,6 +762,8 @@ script:
|
||||
am_cycle_notification_suppressed_reason: >-
|
||||
{% if am_cycle_notification_suppressed | bool(false) %}
|
||||
Cycle was shorter than {{ am_min_cycle_notify_seconds | int(300) }} seconds
|
||||
{% elif am_cycle_notify_allowed | bool(false) and not (am_announcement_enabled | bool(true)) %}
|
||||
Announcement disabled for this appliance
|
||||
{% endif %}
|
||||
|
||||
##########################################################################
|
||||
@@ -673,6 +806,10 @@ script:
|
||||
|
||||
min_cycle_notify_seconds=am_min_cycle_notify_seconds | int(300),
|
||||
cycle_notify_allowed=am_cycle_notify_allowed | bool(false),
|
||||
cycle_announcement_allowed=am_cycle_announcement_allowed | bool(false),
|
||||
announcement_enabled=am_announcement_enabled | bool(true),
|
||||
announcement_channels=am_announcement_channels,
|
||||
mqtt_feed=am_mqtt_feed,
|
||||
cycle_notification_suppressed=am_cycle_notification_suppressed | bool(false),
|
||||
cycle_notification_suppressed_reason=am_cycle_notification_suppressed_reason | trim,
|
||||
|
||||
@@ -740,18 +877,45 @@ script:
|
||||
threshold. No announcement was sent.
|
||||
|
||||
##########################################################################
|
||||
# FINISHED ANNOUNCEMENT
|
||||
##########################################################################
|
||||
# This script is in additional package view_road_announcement_router.yaml.
|
||||
# If you want to use your own announcement system, it will occur here
|
||||
# at am_cycle_notify_allowed being true.
|
||||
#
|
||||
# Change to your own announcement method here if needed.
|
||||
# ANNOUNCEMENT DISABLED LOG
|
||||
##########################################################################
|
||||
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ am_cycle_notify_allowed | bool(false) }}"
|
||||
value_template: >-
|
||||
{{
|
||||
am_cycle_notify_allowed | bool(false)
|
||||
and not (am_announcement_enabled | bool(true))
|
||||
}}
|
||||
then:
|
||||
- action: logbook.log
|
||||
data:
|
||||
name: "Appliance Monitor"
|
||||
message: >-
|
||||
{{ am_appliance_name }} finished after
|
||||
{{ am_cycle_duration_formatted | trim }}, but appliance
|
||||
completion announcements are disabled for this appliance.
|
||||
|
||||
##########################################################################
|
||||
# FINISHED ANNOUNCEMENT
|
||||
##########################################################################
|
||||
# This calls script.view_road_announcement from the announcement router
|
||||
# package when a valid appliance cycle finishes.
|
||||
#
|
||||
# All supported router channels can be used through am_announcement_channels.
|
||||
#
|
||||
# mqtt_view_rd_feed requires:
|
||||
# mqtt_feed
|
||||
#
|
||||
# led_matrix_1 and led_matrix_2 require:
|
||||
# short_announcement
|
||||
# indicator
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ am_cycle_announcement_allowed | bool(false) }}"
|
||||
then:
|
||||
- action: script.view_road_announcement
|
||||
data:
|
||||
@@ -759,5 +923,6 @@ script:
|
||||
title: "{{ am_announcement_title }}"
|
||||
short_announcement: "{{ am_short_announcement }}"
|
||||
long_announcement: "{{ am_long_announcement }}"
|
||||
payload: ""
|
||||
payload: "{{ am_announcement_payload }}"
|
||||
indicator: "{{ am_matrix_indicator }}"
|
||||
mqtt_feed: "{{ am_mqtt_feed }}"
|
||||
|
||||
@@ -1,49 +1,85 @@
|
||||
################################################################################
|
||||
# PACKAGE: Appliances Status Monitoring
|
||||
################################################################################
|
||||
#:########################################################################################:#
|
||||
# Appliances Status Monitoring Package #
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# Version: 1.4
|
||||
# Date: 2026-06-09
|
||||
# FILE:
|
||||
# appliances_status_monitoring.yaml
|
||||
#
|
||||
# Purpose:
|
||||
# VERSION:
|
||||
# V1.5 2026-07-11
|
||||
#
|
||||
# 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.
|
||||
# 1. Publishes MQTT Discovery configuration for each appliance monitor
|
||||
# sensor.
|
||||
# 2. Samples appliance power sensors once per minute.
|
||||
# 3. Calls script.appliance_monitor_process_sample.
|
||||
# 4. Passes per-appliance completion announcement settings to the processor.
|
||||
#
|
||||
# Processor package required:
|
||||
# appliance_monitor_processor.yaml
|
||||
#
|
||||
# Announcement router required:
|
||||
# view_road_announcement_router.yaml
|
||||
# REQUIRED PACKAGES:
|
||||
# appliance_monitor_processor.yaml V1.3 or newer
|
||||
# view_road_announcement_router.yaml V1.8 or newer
|
||||
#
|
||||
# MQTT:
|
||||
# MQTT is used only as retained state storage for appliance monitor sensors.
|
||||
# Sensor entities are created using MQTT discovery.
|
||||
# MQTT is used 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.
|
||||
# ADDING AN APPLIANCE:
|
||||
# Add one entry to the am_appliances registry below.
|
||||
#
|
||||
# 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.
|
||||
# ANNOUNCEMENT ROUTER CHANNELS:
|
||||
# The following channel IDs are accepted by the current announcement router:
|
||||
#
|
||||
# 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.
|
||||
# pushover_zorruno
|
||||
# pushover_kim
|
||||
# sony_tv_lounge
|
||||
# lounge_google_home_voice
|
||||
# google_home_voice
|
||||
# lounge_touchscreen_voice
|
||||
# mqtt_view_rd_feed
|
||||
# led_matrix_1
|
||||
# led_matrix_2
|
||||
#
|
||||
################################################################################
|
||||
# Notes:
|
||||
# - google_home_voice is an alias for lounge_google_home_voice.
|
||||
# - lounge_touchscreen_voice is currently a placeholder route.
|
||||
# - mqtt_view_rd_feed requires mqtt_feed.
|
||||
# - led_matrix_1 and led_matrix_2 use short_announcement and
|
||||
# matrix_indicator.
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.5 2026-07-11
|
||||
# - Added full View Road announcement router parameter support.
|
||||
# - Added per-appliance announcement_enabled.
|
||||
# - Added per-appliance announcement_payload.
|
||||
# - Added per-appliance mqtt_feed for mqtt_view_rd_feed.
|
||||
# - Added safe defaults for short announcement and matrix indicator.
|
||||
# - Documented all current announcement router channel names.
|
||||
# - Existing per-appliance channel selections retained unchanged.
|
||||
#
|
||||
# V1.4 2026-06-09
|
||||
# - 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.
|
||||
#
|
||||
# V1.3:
|
||||
# - Removed the is_number gate before calling the processor.
|
||||
# - The processor is always called once per appliance per sample.
|
||||
# - Power is safely converted to 0 if 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.
|
||||
alias: "Appliances Status Monitoring - Process Samples"
|
||||
description: >-
|
||||
Publishes MQTT Discovery, samples appliance power sensors, processes
|
||||
appliance status and cycle data, and passes completion announcement
|
||||
settings to the shared processor.
|
||||
mode: queued
|
||||
max: 20
|
||||
|
||||
@@ -57,17 +93,17 @@ automation:
|
||||
id: periodic_sample
|
||||
|
||||
variables:
|
||||
##########################################################################
|
||||
# MQTT LOCAL CONTROLS
|
||||
##########################################################################
|
||||
#:####################################################################################:#
|
||||
# MQTT LOCAL CONTROLS #
|
||||
#:####################################################################################:#
|
||||
|
||||
mqtt_device_name: "appliance_monitor"
|
||||
mqtt_local_status_topic: !secret mqtt_status_main_topic
|
||||
mqtt_discovery_prefix: "homeassistant"
|
||||
|
||||
##########################################################################
|
||||
# DEFAULTS
|
||||
##########################################################################
|
||||
#:####################################################################################:#
|
||||
# PROCESSOR DEFAULTS #
|
||||
#:####################################################################################:#
|
||||
|
||||
am_default_debug_flow: false
|
||||
am_default_resolution: 2
|
||||
@@ -75,91 +111,184 @@ automation:
|
||||
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"
|
||||
#:####################################################################################:#
|
||||
# ANNOUNCEMENT DEFAULTS #
|
||||
#:####################################################################################:#
|
||||
#
|
||||
# These defaults apply when an appliance does not define its own values.
|
||||
#
|
||||
# A conservative default channel is retained to prevent additional
|
||||
# notifications suddenly being enabled for every appliance.
|
||||
#
|
||||
# To make all implemented channels the default, this could instead be:
|
||||
#
|
||||
# am_default_announcement_channels: >-
|
||||
# pushover_zorruno,pushover_kim,sony_tv_lounge,
|
||||
# lounge_google_home_voice,mqtt_view_rd_feed,
|
||||
# led_matrix_1,led_matrix_2
|
||||
#
|
||||
# Available channels:
|
||||
# pushover_zorruno
|
||||
# pushover_kim
|
||||
# sony_tv_lounge
|
||||
# lounge_google_home_voice
|
||||
# google_home_voice
|
||||
# lounge_touchscreen_voice
|
||||
# mqtt_view_rd_feed
|
||||
# led_matrix_1
|
||||
# led_matrix_2
|
||||
|
||||
am_default_announcement_enabled: true
|
||||
am_default_announcement_channels: "pushover_zorruno"
|
||||
am_default_announcement_payload: ""
|
||||
|
||||
# Optional appliance-specific overrides available:
|
||||
# resolution: 4
|
||||
# The number of samples for the average, with one sample per minute.
|
||||
#:####################################################################################:#
|
||||
# OPTIONAL PER-APPLIANCE OVERRIDES #
|
||||
#:####################################################################################:#
|
||||
#
|
||||
# standby_power: 3
|
||||
# Below this value, the appliance will show "Off".
|
||||
# Between this value and operating_power_min, it will show "Standby".
|
||||
# debug_flow: true
|
||||
# Writes state-processing details to the Home Assistant logbook.
|
||||
#
|
||||
# operating_power_min: 20
|
||||
# The minimum average power needed for the appliance to show "Operating".
|
||||
# resolution: 4
|
||||
# Number of one-minute samples used for the rolling average.
|
||||
#
|
||||
# min_cycle_notify_seconds: 600
|
||||
# Finished cycles shorter than this are recorded, but no notification
|
||||
# is sent. Default is 300 seconds.
|
||||
# standby_power: 3
|
||||
# Below this value, the appliance shows Off.
|
||||
# Between standby_power and operating_power_min, it shows Standby.
|
||||
#
|
||||
# announcement_channels: "pushover_zorruno"
|
||||
# Announcement channels for this appliance.
|
||||
# operating_power_min: 20
|
||||
# Minimum rolling-average power required for Operating.
|
||||
#
|
||||
# long_announcement: "The device has finished. Please empty it when convenient."
|
||||
# Override the long announcement.
|
||||
# min_cycle_notify_seconds: 600
|
||||
# Minimum cycle duration before a completion announcement is allowed.
|
||||
#
|
||||
# min_cycle_notify_seconds: 600
|
||||
# Minimum time for an appliance to be operating before a completion announcement generated.
|
||||
# announcement_enabled: false
|
||||
# Disables cycle-completion announcements for this appliance.
|
||||
#
|
||||
# announcement_channels: >-
|
||||
# pushover_zorruno,pushover_kim,sony_tv_lounge,
|
||||
# lounge_google_home_voice,mqtt_view_rd_feed,
|
||||
# led_matrix_1,led_matrix_2
|
||||
# Comma-separated View Road announcement router channels.
|
||||
#
|
||||
# title: "Washing Machine Notification"
|
||||
# Optional announcement title.
|
||||
#
|
||||
# short_announcement: "Washing complete"
|
||||
# Used by TV, voice and LED matrix channels.
|
||||
#
|
||||
# long_announcement: "The washing machine has finished."
|
||||
# Used by Pushover and other detailed channels.
|
||||
# If omitted, the processor creates a detailed cycle summary.
|
||||
#
|
||||
# announcement_payload: ""
|
||||
# Optional payload passed to the announcement router.
|
||||
#
|
||||
# matrix_indicator: "wash,1,15,10,6,5,1,0"
|
||||
# LED matrix indicator data.
|
||||
#
|
||||
# mqtt_feed: "washing_machine"
|
||||
# Activity-feed suffix used by mqtt_view_rd_feed.
|
||||
# If omitted, appliance_id is used.
|
||||
#
|
||||
#:####################################################################################:#
|
||||
|
||||
##########################################################################
|
||||
# APPLIANCE REGISTRY
|
||||
##########################################################################
|
||||
#:####################################################################################:#
|
||||
# APPLIANCE REGISTRY #
|
||||
#:####################################################################################:#
|
||||
|
||||
am_appliances:
|
||||
#:##################################################################################:#
|
||||
# Washing Machine #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: washing_machine
|
||||
appliance_name: "Washing Machine"
|
||||
appliance_action: "washing"
|
||||
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"
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno,pushover_kim,sony_tv_lounge,led_matrix_1"
|
||||
short_announcement: "/s/sWashing complete"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "wash,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Washer_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# Dryer #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: dryer
|
||||
appliance_name: "Dryer"
|
||||
appliance_action: "drying"
|
||||
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"
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno,pushover_kim,sony_tv_lounge,led_matrix_1"
|
||||
short_announcement: "/s/sDryer complete"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "dry,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Dryer_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# Main Dishwasher #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: main_dishwasher
|
||||
appliance_name: "Main Dishwasher"
|
||||
appliance_action: "dishwashing"
|
||||
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"
|
||||
|
||||
resolution: 5
|
||||
standby_power: 3
|
||||
operating_power_min: 30
|
||||
announcement_channels: "pushover_zorruno"
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno,pushover_kim,sony_tv_lounge,led_matrix_1"
|
||||
short_announcement: "/sDishwasher complete"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "dish,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Dishwasher_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# Downstairs Dishwasher #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: downstairs_dishwasher
|
||||
appliance_name: "Downstairs Dishwasher"
|
||||
appliance_action: "dishwashing"
|
||||
power_entity: "sensor.esp_downstdishwasher_power"
|
||||
icon: "mdi:dishwasher"
|
||||
short_announcement: "/sDownstairs Dishwasher complete"
|
||||
# long_announcement: # Created by the processor
|
||||
matrix_indicator: "dish2,1,15,10,6,5,1,0"
|
||||
|
||||
resolution: 5
|
||||
standby_power: 3
|
||||
operating_power_min: 30
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno"
|
||||
short_announcement: "/sDownstairs Dishwasher complete"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "dish2,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Downstairs_dishwasher_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# EV Charger 32A #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: evcharger_32a
|
||||
appliance_name: "EV Charger (32A)"
|
||||
@@ -167,88 +296,134 @@ automation:
|
||||
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: 100
|
||||
announcement_channels: "pushover_zorruno"
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno,pushover_kim"
|
||||
short_announcement: "/s/s32A EV Charging complete"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "ev32a,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Atto_Charger_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# EV Charger 16A #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: evcharger_16a
|
||||
appliance_name: "EV Charger (16A)"
|
||||
appliance_action: "charging"
|
||||
power_entity: "sensor.main_house_3_phase_power_monitor_32a_wallcharger_power"
|
||||
monitor_sensor: "sensor.garage_db_control_16a_wallcharger_power"
|
||||
power_entity: "sensor.garage_db_control_16a_wallcharger_power"
|
||||
monitor_sensor: "sensor.appliance_monitor_ev_charger_16a_monitor"
|
||||
icon: "mdi:ev-plug-type1"
|
||||
short_announcement: "/s/s16A EV Charging complete"
|
||||
# long_announcement: # Created by the processor
|
||||
matrix_indicator: "ev16a,1,15,10,6,5,1,0"
|
||||
|
||||
resolution: 6
|
||||
standby_power: 3
|
||||
operating_power_min: 100
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno"
|
||||
short_announcement: "/s/s16A EV Charging complete"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "ev16a,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Leaf_Charger_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# Ryobi Charger Left #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: ryobicharger_left
|
||||
appliance_name: "Ryobi Charger Left"
|
||||
appliance_action: "charging"
|
||||
power_entity: "sensor.ryobi_charger_left_power_monitor_x17pp_power"
|
||||
#monitor_sensor: "sensor.ryobi_charger_left_power_monitor_x17pp_power"
|
||||
icon: "mdi:battery-charging-medium"
|
||||
short_announcement: "/s/sRyobi Charging Left"
|
||||
# long_announcement: # Created by the processor
|
||||
matrix_indicator: "ryo1,1,15,10,6,5,1,0"
|
||||
|
||||
resolution: 4
|
||||
standby_power: 1
|
||||
operating_power_min: 20
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno"
|
||||
short_announcement: "/s/sRyobi Charging Left"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "ryo1,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Ryobi_Charger_1_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# Ryobi Charger Right #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: ryobicharger_right
|
||||
appliance_name: "Ryobi Charger Right"
|
||||
appliance_action: "charging"
|
||||
power_entity: "sensor.ryobi_charger_right_power_monitor_x16pp_power"
|
||||
#monitor_sensor: "sensor.ryobi_charger_right_power_monitor_x16pp_power"
|
||||
icon: "mdi:battery-charging-medium"
|
||||
short_announcement: "/s/sRyobi Charging Right"
|
||||
# long_announcement: # Created by the processor
|
||||
matrix_indicator: "ryo2,1,15,10,6,5,1,0"
|
||||
|
||||
resolution: 4
|
||||
standby_power: 1
|
||||
operating_power_min: 20
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno"
|
||||
short_announcement: "/s/sRyobi Charging Right"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "ryo2,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "Ryobi_Charger_2_complete"
|
||||
|
||||
#:##################################################################################:#
|
||||
# Pool Pump #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: pool_pump
|
||||
appliance_name: "Pool Pump"
|
||||
appliance_action: "pumping"
|
||||
power_entity: "sensor.esp_poolpumppower_power"
|
||||
#monitor_sensor: "sensor.ryobi_charger_right_power_monitor_x16pp_power"
|
||||
icon: "mdi:pool"
|
||||
short_announcement: "Pool Pump Off"
|
||||
# long_announcement: # Created by the processor
|
||||
matrix_indicator: "pump,1,15,10,6,5,1,0"
|
||||
|
||||
resolution: 4
|
||||
standby_power: 5
|
||||
operating_power_min: 20
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno"
|
||||
short_announcement: "Pool Pump Off"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "pump,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "pool_pump"
|
||||
|
||||
#:##################################################################################:#
|
||||
# 3D Printer #
|
||||
#:##################################################################################:#
|
||||
|
||||
- appliance_id: 3d_printer
|
||||
appliance_name: "3D Printer"
|
||||
appliance_action: "printing"
|
||||
power_entity: "sensor.esp_3dprinterpow_load_power"
|
||||
#monitor_sensor: "sensor.ryobi_charger_right_power_monitor_x16pp_power"
|
||||
icon: "mdi:printer-3d"
|
||||
short_announcement: "3D printer finished"
|
||||
# long_announcement: # Created by the processor
|
||||
matrix_indicator: "pump,1,15,10,6,5,1,0"
|
||||
|
||||
resolution: 4
|
||||
standby_power: 2
|
||||
operating_power_min: 20
|
||||
|
||||
announcement_enabled: true
|
||||
announcement_channels: "pushover_zorruno"
|
||||
short_announcement: "3D printer finished"
|
||||
# long_announcement: # Generated by the processor
|
||||
announcement_payload: ""
|
||||
matrix_indicator: "pump,1,15,10,6,5,1,0"
|
||||
mqtt_feed: "3d_printer"
|
||||
|
||||
action:
|
||||
##########################################################################
|
||||
# PUBLISH / REFRESH MQTT DISCOVERY CONFIG
|
||||
##########################################################################
|
||||
#:####################################################################################:#
|
||||
# PUBLISH / REFRESH MQTT DISCOVERY CONFIG #
|
||||
#:####################################################################################:#
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ am_appliances }}"
|
||||
@@ -285,19 +460,18 @@ automation:
|
||||
identifiers=[mqtt_device_name],
|
||||
name='Appliance Monitor',
|
||||
manufacturer='View Road Home Assistant',
|
||||
model='Shared appliance power monitor'
|
||||
model='Shared appliance power monitor',
|
||||
sw_version='1.5'
|
||||
)
|
||||
) | to_json
|
||||
}}
|
||||
|
||||
##########################################################################
|
||||
# PROCESS SAMPLES
|
||||
##########################################################################
|
||||
#:####################################################################################:#
|
||||
# PROCESS SAMPLES #
|
||||
#:####################################################################################:#
|
||||
#
|
||||
# Always process every appliance. The processor receives power_w as a safe
|
||||
# float value, so unavailable/non-numeric sensors become 0 W.
|
||||
#
|
||||
##########################################################################
|
||||
# float value, so unavailable or non-numeric sensors become 0 W.
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ am_appliances }}"
|
||||
@@ -309,36 +483,97 @@ automation:
|
||||
am_monitor_sensor: >-
|
||||
{{
|
||||
repeat.item.monitor_sensor
|
||||
| default('sensor.' ~ mqtt_device_name ~ '_' ~ repeat.item.appliance_id ~ '_monitor', true)
|
||||
| default(
|
||||
'sensor.'
|
||||
~ mqtt_device_name
|
||||
~ '_'
|
||||
~ repeat.item.appliance_id
|
||||
~ '_monitor',
|
||||
true
|
||||
)
|
||||
}}
|
||||
|
||||
am_title: >-
|
||||
{{ repeat.item.title | default(repeat.item.appliance_name ~ ' Notification', true) }}
|
||||
{{
|
||||
repeat.item.title
|
||||
| default(
|
||||
repeat.item.appliance_name ~ ' Notification',
|
||||
true
|
||||
)
|
||||
}}
|
||||
|
||||
am_announcement_enabled: >-
|
||||
{{
|
||||
repeat.item.announcement_enabled
|
||||
| default(am_default_announcement_enabled)
|
||||
}}
|
||||
|
||||
am_announcement_channels: >-
|
||||
{{ repeat.item.announcement_channels | default(am_default_announcement_channels, true) }}
|
||||
{{
|
||||
repeat.item.announcement_channels
|
||||
| default(am_default_announcement_channels, true)
|
||||
}}
|
||||
|
||||
am_debug_flow: >-
|
||||
{{ repeat.item.debug_flow | default(am_default_debug_flow, true) }}
|
||||
am_announcement_payload: >-
|
||||
{{
|
||||
repeat.item.announcement_payload
|
||||
| default(am_default_announcement_payload, true)
|
||||
}}
|
||||
|
||||
am_resolution: >-
|
||||
{{ repeat.item.resolution | default(am_default_resolution, true) }}
|
||||
am_mqtt_feed: >-
|
||||
{{
|
||||
repeat.item.mqtt_feed
|
||||
| default(repeat.item.appliance_id, true)
|
||||
}}
|
||||
|
||||
am_standby_power: >-
|
||||
{{ repeat.item.standby_power | default(am_default_standby_power, true) }}
|
||||
am_short_announcement: >-
|
||||
{{
|
||||
repeat.item.short_announcement
|
||||
| default(
|
||||
(repeat.item.appliance_action | title) ~ ' complete',
|
||||
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_matrix_indicator: >-
|
||||
{{ repeat.item.matrix_indicator | default('', true) }}
|
||||
|
||||
am_long_announcement: >-
|
||||
{{ repeat.item.long_announcement | default('', true) }}
|
||||
|
||||
am_debug_flow: >-
|
||||
{{
|
||||
repeat.item.debug_flow
|
||||
| default(am_default_debug_flow)
|
||||
}}
|
||||
|
||||
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) }}
|
||||
|
||||
- action: script.appliance_monitor_process_sample
|
||||
data:
|
||||
appliance_id: "{{ repeat.item.appliance_id }}"
|
||||
@@ -355,8 +590,11 @@ automation:
|
||||
operating_power_min: "{{ am_operating_power_min }}"
|
||||
min_cycle_notify_seconds: "{{ am_min_cycle_notify_seconds }}"
|
||||
|
||||
announcement_enabled: "{{ am_announcement_enabled }}"
|
||||
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 }}"
|
||||
short_announcement: "{{ am_short_announcement }}"
|
||||
long_announcement: "{{ am_long_announcement }}"
|
||||
announcement_payload: "{{ am_announcement_payload }}"
|
||||
matrix_indicator: "{{ am_matrix_indicator }}"
|
||||
mqtt_feed: "{{ am_mqtt_feed }}"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
################################################################################
|
||||
# Jobs Tracker Processor Package
|
||||
################################################################################
|
||||
#:########################################################################################:#
|
||||
# Jobs Tracker Processor Package #
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# TITLE:
|
||||
# Jobs Tracker Processor
|
||||
@@ -9,20 +9,122 @@
|
||||
# jobs_tracker_processor.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.3.1 2026-06-20
|
||||
# V1.6 2026-07-10
|
||||
#
|
||||
# CHANGELOG:
|
||||
# V1.3.1:
|
||||
# PURPOSE:
|
||||
# Generic processing engine for the Jobs Tracker system.
|
||||
#
|
||||
# OPERATION:
|
||||
# This package is the generic processing engine for the Jobs Tracker system.
|
||||
# It is not normally edited when adding, removing or changing household jobs.
|
||||
# Jobs are defined in the separate job-list package, which calls this processor
|
||||
# through script.jobs_tracker_update_job. The processor calculates whether each
|
||||
# job is Not Due, Missed, Due, Overdue or Complete, then publishes the
|
||||
# result as retained MQTT JSON to that job's configured MQTT topic. The retained
|
||||
# MQTT payload stores the last completion timestamp, so after a Home Assistant
|
||||
# restart the processor can recalculate the correct state from the last physical
|
||||
# button/action press.
|
||||
#
|
||||
# Normal operation is automatic. The job-list package refreshes all jobs on a
|
||||
# regular timer and after Home Assistant starts, and it calls this processor with
|
||||
# mark_complete: true when a physical button, event, sensor, MQTT button or other
|
||||
# completion action confirms a job has been completed. A job is considered
|
||||
# Complete when its stored last_completed_ts is within the current reset period.
|
||||
#
|
||||
# Daily jobs reset at 00:00 but only become Due at their configured due_time.
|
||||
# Weekly jobs reset at the week rollover, currently Monday 00:00. Monthly jobs
|
||||
# reset at the month rollover, currently the 1st day of the month at 00:00.
|
||||
#
|
||||
# If the previous reset period was missed, jobs without a completion window are
|
||||
# marked Missed after the reset and before the current due time. Jobs with a
|
||||
# completion window are marked Missed after the current completion window ends.
|
||||
# This lets jobs such as morning dog feeding show Missed after the morning
|
||||
# window, but then reset to Not Due/Due again the next morning.
|
||||
#
|
||||
# Once the current due time arrives, a job changes to Due, then Overdue after
|
||||
# the configured threshold unless the job has reached the end of its completion
|
||||
# window, in which case it changes to Missed. Completing a job early is allowed
|
||||
# once the current reset period has started.
|
||||
#
|
||||
# SETTINGS:
|
||||
# The job-list package passes these settings into this processor for each job:
|
||||
#
|
||||
# job_id:
|
||||
# Machine-safe ID used for matching and MQTT topic naming.
|
||||
# Example: dog_feeding_morning
|
||||
#
|
||||
# job_name:
|
||||
# Human-readable job name used in the retained MQTT JSON.
|
||||
# Example: Dog Feeding Morning
|
||||
#
|
||||
# repeat_type:
|
||||
# Schedule type. Valid values are daily, weekly or monthly.
|
||||
#
|
||||
# due_time:
|
||||
# Time the job is due, in HH:MM 24-hour format.
|
||||
# Example: "06:00"
|
||||
#
|
||||
# due_weekday:
|
||||
# Weekly jobs only. Monday=0, Tuesday=1, Wednesday=2, Thursday=3,
|
||||
# Friday=4, Saturday=5, Sunday=6.
|
||||
#
|
||||
# due_day:
|
||||
# Monthly jobs only. Use 1-28 for best reliability across all months.
|
||||
#
|
||||
# mqtt_topic:
|
||||
# Retained MQTT state topic for this job.
|
||||
# Example: viewroad-status/jobs_tracker/dog_feeding_morning
|
||||
#
|
||||
# state_entity:
|
||||
# MQTT sensor entity that reads this job's retained JSON payload.
|
||||
# Example: sensor.jobs_tracker_dog_feeding_morning
|
||||
#
|
||||
# mark_complete:
|
||||
# false when refreshing/calculating the job state.
|
||||
# true when a physical/manual completion action has just occurred.
|
||||
#
|
||||
# completion_window_start / completion_window_end:
|
||||
# Optional HH:MM window used for jobs that share a physical button or have
|
||||
# a clear daily completion window. If the current window ends before the
|
||||
# job is completed, the job is marked Missed instead of remaining Overdue.
|
||||
# Example: "00:00" to "11:59" for morning dog feeding.
|
||||
#
|
||||
# Current built-in overdue thresholds are:
|
||||
# - Daily jobs: 2 hours after due_time
|
||||
# - Weekly jobs: 2 days after due_time
|
||||
# - Monthly jobs: 2 weeks after due_time
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.6 2026-07-10
|
||||
# - Renamed displayed state from Missed to Missed.
|
||||
# - Added optional completion_window_start and completion_window_end fields.
|
||||
# - Windowed jobs now become Missed when the completion window has ended.
|
||||
# - Windowed jobs reset normally into Not Due / Due in the next period.
|
||||
#
|
||||
# V1.5 2026-07-07
|
||||
# - Documentation update for the refactored registry-driven job-list package.
|
||||
# - No functional processing change from V1.4.
|
||||
#
|
||||
# V1.4 2026-07-06
|
||||
# - Added Missed state.
|
||||
# - If the previous reset period was missed, the job now shows Previous
|
||||
# Missed until the current period's due time.
|
||||
# - Missed applies to daily, weekly and monthly jobs.
|
||||
# - Due now starts at the configured due time for daily, weekly and monthly
|
||||
# jobs.
|
||||
# - Early completion remains supported after the current reset period starts.
|
||||
#
|
||||
# V1.3.1 2026-06-20
|
||||
# - Corrected script field definitions so Home Assistant reliably creates
|
||||
# script.jobs_tracker_update_job.
|
||||
#
|
||||
# V1.3:
|
||||
# V1.3 2026-06-20
|
||||
# - Daily jobs reset at 00:00 but do not become Due until their configured
|
||||
# due time.
|
||||
# - Added "Not Due" state.
|
||||
# - Added Not Due state.
|
||||
# - Completion is recalculated from retained last_completed_ts after restart.
|
||||
#
|
||||
################################################################################
|
||||
#:########################################################################################:#
|
||||
|
||||
script:
|
||||
jobs_tracker_update_job:
|
||||
@@ -59,6 +161,12 @@ script:
|
||||
mark_complete:
|
||||
description: "Set true when a human has completed the job."
|
||||
example: true
|
||||
completion_window_start:
|
||||
description: "Optional HH:MM completion window start."
|
||||
example: "00:00"
|
||||
completion_window_end:
|
||||
description: "Optional HH:MM completion window end."
|
||||
example: "11:59"
|
||||
|
||||
sequence:
|
||||
- variables:
|
||||
@@ -73,6 +181,17 @@ script:
|
||||
now_ts: "{{ as_timestamp(now()) }}"
|
||||
today_midnight_ts: "{{ as_timestamp(today_at('00:00')) }}"
|
||||
topic_safe: "{{ mqtt_topic | default('viewroad-status/jobs_tracker/' ~ job_id) }}"
|
||||
completion_window_start_safe: "{{ completion_window_start | default('') }}"
|
||||
completion_window_end_safe: "{{ completion_window_end | default('') }}"
|
||||
has_completion_window: >-
|
||||
{{
|
||||
completion_window_start_safe not in ['', none, 'unknown', 'unavailable']
|
||||
and completion_window_end_safe not in ['', none, 'unknown', 'unavailable']
|
||||
}}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Current and next reset periods #
|
||||
#:####################################################################################:#
|
||||
|
||||
- variables:
|
||||
current_period_start_ts: >-
|
||||
@@ -98,6 +217,28 @@ script:
|
||||
{{ (today_midnight_ts | float(0)) + 86400 }}
|
||||
{% endif %}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Previous reset period #
|
||||
#:####################################################################################:#
|
||||
|
||||
- variables:
|
||||
previous_period_start_ts: >-
|
||||
{% if repeat_type_safe == 'daily' %}
|
||||
{{ (current_period_start_ts | float(0)) - 86400 }}
|
||||
{% elif repeat_type_safe == 'weekly' %}
|
||||
{{ (current_period_start_ts | float(0)) - 604800 }}
|
||||
{% elif repeat_type_safe == 'monthly' %}
|
||||
{% set first_day_this_month = now().replace(day=1, hour=0, minute=0, second=0, microsecond=0) %}
|
||||
{% set last_day_previous_month = first_day_this_month - timedelta(days=1) %}
|
||||
{{ as_timestamp(last_day_previous_month.replace(day=1, hour=0, minute=0, second=0, microsecond=0)) }}
|
||||
{% else %}
|
||||
{{ (current_period_start_ts | float(0)) - 86400 }}
|
||||
{% endif %}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Due times #
|
||||
#:####################################################################################:#
|
||||
|
||||
- variables:
|
||||
current_due_ts: >-
|
||||
{% if repeat_type_safe == 'daily' %}
|
||||
@@ -110,6 +251,19 @@ script:
|
||||
{{ (current_period_start_ts | float(0)) + (due_seconds | int) }}
|
||||
{% endif %}
|
||||
|
||||
previous_due_ts: >-
|
||||
{% if repeat_type_safe == 'daily' %}
|
||||
{{ (previous_period_start_ts | float(0)) + (due_seconds | int) }}
|
||||
{% elif repeat_type_safe == 'weekly' %}
|
||||
{{ (previous_period_start_ts | float(0)) + ((due_weekday_safe | int) * 86400) + (due_seconds | int) }}
|
||||
{% elif repeat_type_safe == 'monthly' %}
|
||||
{% set first_day_this_month = now().replace(day=1, hour=0, minute=0, second=0, microsecond=0) %}
|
||||
{% set last_day_previous_month = first_day_this_month - timedelta(days=1) %}
|
||||
{{ as_timestamp(last_day_previous_month.replace(day=(due_day_safe | int), hour=(due_hour | int), minute=(due_minute | int), second=0, microsecond=0)) }}
|
||||
{% else %}
|
||||
{{ (previous_period_start_ts | float(0)) + (due_seconds | int) }}
|
||||
{% endif %}
|
||||
|
||||
next_due_ts: >-
|
||||
{% if repeat_type_safe == 'daily' %}
|
||||
{{ (next_period_start_ts | float(0)) + (due_seconds | int) }}
|
||||
@@ -133,6 +287,60 @@ script:
|
||||
120
|
||||
{% endif %}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Completion window timing #
|
||||
#:####################################################################################:#
|
||||
#
|
||||
# For windowed jobs, Missed begins when the completion window has ended.
|
||||
# The window is anchored to the current due date. End times are treated as
|
||||
# inclusive through the final minute, so "11:59" ends at 11:59:59.
|
||||
|
||||
- variables:
|
||||
completion_window_start_seconds: >-
|
||||
{% if has_completion_window | bool %}
|
||||
{% set t = completion_window_start_safe.split(':') %}
|
||||
{{ ((t[0] | int(0)) * 3600) + ((t[1] | int(0)) * 60) }}
|
||||
{% else %}
|
||||
0
|
||||
{% endif %}
|
||||
|
||||
completion_window_end_seconds: >-
|
||||
{% if has_completion_window | bool %}
|
||||
{% set t = completion_window_end_safe.split(':') %}
|
||||
{{ ((t[0] | int(23)) * 3600) + ((t[1] | int(59)) * 60) + 59 }}
|
||||
{% else %}
|
||||
86399
|
||||
{% endif %}
|
||||
|
||||
current_due_day_start_ts: >-
|
||||
{% set d = (current_due_ts | float(0)) | timestamp_custom('%Y-%m-%d', true) %}
|
||||
{{ as_timestamp(strptime(d ~ ' 00:00:00', '%Y-%m-%d %H:%M:%S')) }}
|
||||
|
||||
current_completion_window_start_ts: >-
|
||||
{% if has_completion_window | bool %}
|
||||
{{ (current_due_day_start_ts | float(0)) + (completion_window_start_seconds | int(0)) }}
|
||||
{% else %}
|
||||
0
|
||||
{% endif %}
|
||||
|
||||
current_completion_window_end_ts: >-
|
||||
{% if has_completion_window | bool %}
|
||||
{% set start_seconds = completion_window_start_seconds | int(0) %}
|
||||
{% set end_seconds = completion_window_end_seconds | int(86399) %}
|
||||
{% set base_end = (current_due_day_start_ts | float(0)) + end_seconds %}
|
||||
{% if end_seconds < start_seconds %}
|
||||
{{ base_end + 86400 }}
|
||||
{% else %}
|
||||
{{ base_end }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
0
|
||||
{% endif %}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Restore retained completion timestamp #
|
||||
#:####################################################################################:#
|
||||
|
||||
- variables:
|
||||
stored_last_completed_ts: >-
|
||||
{% set v = state_attr(state_entity, 'last_completed_ts') %}
|
||||
@@ -141,20 +349,52 @@ script:
|
||||
last_completed_ts: >-
|
||||
{{ now_ts if mark_complete_bool else stored_last_completed_ts }}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Completion and timing state #
|
||||
#:####################################################################################:#
|
||||
|
||||
- variables:
|
||||
complete_bool: >-
|
||||
{{ (last_completed_ts | float(0)) >= (current_period_start_ts | float(0)) }}
|
||||
|
||||
previous_completed_bool: >-
|
||||
{{
|
||||
(last_completed_ts | float(0)) >= (previous_period_start_ts | float(0))
|
||||
and (last_completed_ts | float(0)) < (current_period_start_ts | float(0))
|
||||
}}
|
||||
|
||||
previous_missed_bool: >-
|
||||
{{ not (previous_completed_bool | bool) }}
|
||||
|
||||
due_started_bool: >-
|
||||
{% if repeat_type_safe == 'daily' %}
|
||||
{{ (now_ts | float(0)) >= (current_due_ts | float(0)) }}
|
||||
{% else %}
|
||||
true
|
||||
{% endif %}
|
||||
{{ (now_ts | float(0)) >= (current_due_ts | float(0)) }}
|
||||
|
||||
overdue_started_bool: >-
|
||||
{{ (now_ts | float(0)) >= ((current_due_ts | float(0)) + ((overdue_after_minutes | int(0)) * 60)) }}
|
||||
|
||||
previous_missed_active_bool: >-
|
||||
{{
|
||||
previous_missed_bool | bool
|
||||
and not (complete_bool | bool)
|
||||
and not (due_started_bool | bool)
|
||||
}}
|
||||
|
||||
completion_window_missed_bool: >-
|
||||
{{
|
||||
has_completion_window | bool
|
||||
and not (complete_bool | bool)
|
||||
and (now_ts | float(0)) > (current_completion_window_end_ts | float(0))
|
||||
}}
|
||||
|
||||
missed_bool: >-
|
||||
{{
|
||||
completion_window_missed_bool | bool
|
||||
or (
|
||||
previous_missed_active_bool | bool
|
||||
and not (has_completion_window | bool)
|
||||
)
|
||||
}}
|
||||
|
||||
minutes_since_required: >-
|
||||
{% if (now_ts | float(0)) <= (current_due_ts | float(0)) %}
|
||||
0
|
||||
@@ -169,10 +409,16 @@ script:
|
||||
{{ (((now_ts | float(0)) - (current_due_ts | float(0))) / 3600) | round(0) | int }}
|
||||
{% endif %}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Display state #
|
||||
#:####################################################################################:#
|
||||
|
||||
- variables:
|
||||
job_status: >-
|
||||
{% if complete_bool | bool %}
|
||||
Complete
|
||||
{% elif missed_bool | bool %}
|
||||
Missed
|
||||
{% elif not (due_started_bool | bool) %}
|
||||
Not Due
|
||||
{% elif overdue_started_bool | bool %}
|
||||
@@ -265,52 +511,64 @@ script:
|
||||
{{ ts | timestamp_custom('%Y-%m-%d @ %H:%M', true) }}
|
||||
{% endif %}
|
||||
|
||||
#:####################################################################################:#
|
||||
# Publish retained MQTT JSON #
|
||||
#:####################################################################################:#
|
||||
|
||||
- variables:
|
||||
completed_for_period_ts_safe: >-
|
||||
{% if complete_bool | bool %}
|
||||
{{ current_period_start_ts | float(0) }}
|
||||
{% else %}
|
||||
0
|
||||
{% endif %}
|
||||
|
||||
- action: mqtt.publish
|
||||
data:
|
||||
topic: "{{ topic_safe }}"
|
||||
retain: true
|
||||
qos: 1
|
||||
payload: >-
|
||||
{{
|
||||
{
|
||||
"job_id": job_id,
|
||||
"job_name": job_name,
|
||||
"repeat": repeat_type_safe,
|
||||
"due_time": due_time_safe,
|
||||
"due_weekday": due_weekday_safe | int,
|
||||
"due_day": due_day_safe | int,
|
||||
|
||||
"state": job_status | trim,
|
||||
"complete": complete_bool | bool,
|
||||
|
||||
"last_completed_ts": last_completed_ts | float(0),
|
||||
"last_completed_time": last_completed_time,
|
||||
"last_completed_human": last_completed_human,
|
||||
|
||||
"completed_for_period_ts": current_period_start_ts | float(0) if complete_bool | bool else 0,
|
||||
"completed_for_due_ts": current_period_start_ts | float(0) if complete_bool | bool else 0,
|
||||
|
||||
"current_period_start_ts": current_period_start_ts | float(0),
|
||||
"next_period_start_ts": next_period_start_ts | float(0),
|
||||
|
||||
"current_due_ts": current_due_ts | float(0),
|
||||
"next_due_ts": next_due_ts | float(0),
|
||||
"display_due_ts": display_due_ts | float(0),
|
||||
"next_due_human": next_due_human,
|
||||
|
||||
"due_started": due_started_bool | bool,
|
||||
"overdue_started": overdue_started_bool | bool,
|
||||
|
||||
"minutes_since_required": minutes_since_required | int(0),
|
||||
"hours_since_required": hours_since_required | int(0),
|
||||
|
||||
"overdue_after_minutes": overdue_after_minutes | int(0),
|
||||
"overdue_minutes": overdue_minutes | int(0),
|
||||
"overdue_hours": overdue_hours | int(0),
|
||||
|
||||
"hours_since_completed": hours_since_completed,
|
||||
|
||||
"last_updated_local": (now_ts | float(0)) | timestamp_custom('%Y-%m-%d %H:%M:%S', true),
|
||||
"mqtt_topic": topic_safe
|
||||
} | tojson
|
||||
}}
|
||||
{
|
||||
"job_id": {{ job_id | tojson }},
|
||||
"job_name": {{ job_name | tojson }},
|
||||
"repeat": {{ repeat_type_safe | tojson }},
|
||||
"due_time": {{ due_time_safe | tojson }},
|
||||
"due_weekday": {{ due_weekday_safe | int }},
|
||||
"due_day": {{ due_day_safe | int }},
|
||||
"state": {{ job_status | trim | tojson }},
|
||||
"complete": {{ complete_bool | bool | tojson }},
|
||||
"last_completed_ts": {{ last_completed_ts | float(0) }},
|
||||
"last_completed_time": {{ last_completed_time | tojson }},
|
||||
"last_completed_human": {{ last_completed_human | tojson }},
|
||||
"previous_period_start_ts": {{ previous_period_start_ts | float(0) }},
|
||||
"previous_due_ts": {{ previous_due_ts | float(0) }},
|
||||
"previous_completed": {{ previous_completed_bool | bool | tojson }},
|
||||
"previous_missed": {{ previous_missed_bool | bool | tojson }},
|
||||
"previous_missed_active": {{ previous_missed_active_bool | bool | tojson }},
|
||||
"missed": {{ missed_bool | bool | tojson }},
|
||||
"completion_window_start": {{ completion_window_start_safe | tojson }},
|
||||
"completion_window_end": {{ completion_window_end_safe | tojson }},
|
||||
"has_completion_window": {{ has_completion_window | bool | tojson }},
|
||||
"completion_window_missed": {{ completion_window_missed_bool | bool | tojson }},
|
||||
"current_completion_window_start_ts": {{ current_completion_window_start_ts | float(0) }},
|
||||
"current_completion_window_end_ts": {{ current_completion_window_end_ts | float(0) }},
|
||||
"completed_for_period_ts": {{ completed_for_period_ts_safe | float(0) }},
|
||||
"completed_for_due_ts": {{ completed_for_period_ts_safe | float(0) }},
|
||||
"current_period_start_ts": {{ current_period_start_ts | float(0) }},
|
||||
"next_period_start_ts": {{ next_period_start_ts | float(0) }},
|
||||
"current_due_ts": {{ current_due_ts | float(0) }},
|
||||
"next_due_ts": {{ next_due_ts | float(0) }},
|
||||
"display_due_ts": {{ display_due_ts | float(0) }},
|
||||
"next_due_human": {{ next_due_human | tojson }},
|
||||
"due_started": {{ due_started_bool | bool | tojson }},
|
||||
"overdue_started": {{ overdue_started_bool | bool | tojson }},
|
||||
"minutes_since_required": {{ minutes_since_required | int(0) }},
|
||||
"hours_since_required": {{ hours_since_required | int(0) }},
|
||||
"overdue_after_minutes": {{ overdue_after_minutes | int(0) }},
|
||||
"overdue_minutes": {{ overdue_minutes | int(0) }},
|
||||
"overdue_hours": {{ overdue_hours | int(0) }},
|
||||
"hours_since_completed": {{ hours_since_completed | tojson }},
|
||||
"last_updated_local": {{ ((now_ts | float(0)) | timestamp_custom('%Y-%m-%d %H:%M:%S', true)) | tojson }},
|
||||
"mqtt_topic": {{ topic_safe | tojson }}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ mqtt:
|
||||
name: "Dishwasher Finished"
|
||||
state_topic: "viewroad-status/activityfeed/Dishwasher_complete"
|
||||
icon: mdi:dishwasher
|
||||
- unique_id: downstairs_dishwasher_finished
|
||||
name: "Downstairs Dishwasher Finished"
|
||||
state_topic: "viewroad-status/activityfeed/Downstairs_dishwasher_complete"
|
||||
icon: mdi:dishwasher
|
||||
- unique_id: 16Acharger_finished
|
||||
name: "Leaf Done"
|
||||
state_topic: "viewroad-status/activityfeed/Leaf_Charger_complete"
|
||||
|
||||
@@ -67,6 +67,12 @@ automation:
|
||||
|
||||
variables:
|
||||
bedtime_delayed_off_targets:
|
||||
- entity_id: switch.esp_centralstairs_bottom_relay_1_main_stair_lights_lower
|
||||
delay_seconds: 0
|
||||
|
||||
- entity_id: switch.esp_centralstairs_bottom_relay_2_stair_footer_lights
|
||||
delay_seconds: 0
|
||||
|
||||
- entity_id: switch.esp_mainkitchenlights_relay_1_main_lights
|
||||
delay_seconds: 4
|
||||
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
#:########################################################################################:#
|
||||
# Open-Meteo Rain Chance Package #
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# TITLE:
|
||||
# Open-Meteo Rain Chance
|
||||
#
|
||||
# FILE:
|
||||
# open_meteo_rain_chance.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.2 2026-07-19
|
||||
# - Changed today's forecast period to use remaining daylight hours.
|
||||
# - Before sunrise, today's forecast covers sunrise through sunset.
|
||||
# - During daylight, today's forecast covers now through sunset.
|
||||
# - At sunset or later, today's forecast covers now through midnight.
|
||||
# - Tomorrow continues to cover daylight hours only.
|
||||
#
|
||||
# V1.1 2026-07-19
|
||||
# - Changed today's prediction to use only the remaining forecast hours
|
||||
# from the current local hour until midnight.
|
||||
# - Changed tomorrow's prediction to cover daylight hours only.
|
||||
# - Added hourly precipitation probability data.
|
||||
# - Added today's and tomorrow's sunrise and sunset data.
|
||||
#
|
||||
# V1.0 2026-07-18
|
||||
# - Initial version.
|
||||
# - Used the full-day maximum precipitation probability for today and
|
||||
# tomorrow.
|
||||
#
|
||||
# PURPOSE:
|
||||
# Creates dedicated Home Assistant sensors for the maximum hourly
|
||||
# probability of precipitation during useful forecast periods today and
|
||||
# tomorrow.
|
||||
#
|
||||
# SOURCE:
|
||||
# Open-Meteo Forecast API
|
||||
#
|
||||
# LOCATION:
|
||||
# Uses the latitude and longitude attributes of zone.home.
|
||||
#
|
||||
# OUTPUT ENTITIES:
|
||||
# sensor.open_meteo_rain_chance_today
|
||||
# sensor.open_meteo_rain_chance_tomorrow
|
||||
#
|
||||
# FORECAST PERIODS:
|
||||
# Today before sunrise:
|
||||
# Sunrise through sunset.
|
||||
#
|
||||
# Today during daylight:
|
||||
# Current time through sunset.
|
||||
#
|
||||
# Today at or after sunset:
|
||||
# Current time through midnight.
|
||||
#
|
||||
# Tomorrow:
|
||||
# Sunrise through sunset.
|
||||
#
|
||||
# UPDATE RATE:
|
||||
# Every 30 minutes.
|
||||
#
|
||||
# NOTES:
|
||||
# - No API key is required.
|
||||
# - timezone=auto makes Open-Meteo return forecast times in the local
|
||||
# timezone determined from the zone.home coordinates.
|
||||
# - Each Open-Meteo hourly precipitation probability applies to the
|
||||
# preceding hour.
|
||||
# - Hourly forecast periods that partly overlap sunrise or sunset are
|
||||
# included.
|
||||
# - The displayed result is the highest hourly probability within the
|
||||
# applicable period.
|
||||
# - The result is not a separately calculated probability of receiving
|
||||
# rain at any point across the whole selected period.
|
||||
# - Sensor values and forecast-period changes are recalculated whenever
|
||||
# the REST request updates.
|
||||
#
|
||||
#:########################################################################################:#
|
||||
|
||||
rest:
|
||||
- resource_template: >-
|
||||
https://api.open-meteo.com/v1/forecast?latitude={{ state_attr('zone.home', 'latitude') }}&longitude={{ state_attr('zone.home', 'longitude') }}&hourly=precipitation_probability&daily=sunrise,sunset&timezone=auto&forecast_days=2
|
||||
|
||||
method: GET
|
||||
scan_interval: 1800
|
||||
timeout: 20
|
||||
|
||||
sensor:
|
||||
#:###################################################################################:#
|
||||
# Rain Chance Today #
|
||||
#:###################################################################################:#
|
||||
#
|
||||
# Before sunrise:
|
||||
# Uses today's sunrise through sunset.
|
||||
#
|
||||
# During daylight:
|
||||
# Uses the current time through today's sunset.
|
||||
#
|
||||
# At or after sunset:
|
||||
# Uses the current time through midnight.
|
||||
#
|
||||
|
||||
- name: "Open Meteo Rain Chance Today"
|
||||
unique_id: open_meteo_rain_chance_today
|
||||
unit_of_measurement: "%"
|
||||
state_class: measurement
|
||||
icon: mdi:weather-rainy
|
||||
|
||||
value_template: >-
|
||||
{% set current_timestamp =
|
||||
as_timestamp(now())
|
||||
%}
|
||||
|
||||
{% set sunrise_timestamp =
|
||||
as_timestamp(
|
||||
value_json.daily.sunrise[0],
|
||||
0
|
||||
)
|
||||
%}
|
||||
|
||||
{% set sunset_timestamp =
|
||||
as_timestamp(
|
||||
value_json.daily.sunset[0],
|
||||
0
|
||||
)
|
||||
%}
|
||||
|
||||
{% set tomorrow_midnight_timestamp =
|
||||
as_timestamp(
|
||||
value_json.daily.time[1] ~ 'T00:00',
|
||||
0
|
||||
)
|
||||
%}
|
||||
|
||||
{% if current_timestamp < sunrise_timestamp %}
|
||||
|
||||
{% set period_start_timestamp =
|
||||
sunrise_timestamp
|
||||
%}
|
||||
|
||||
{% set period_end_timestamp =
|
||||
sunset_timestamp
|
||||
%}
|
||||
|
||||
{% elif current_timestamp < sunset_timestamp %}
|
||||
|
||||
{% set period_start_timestamp =
|
||||
current_timestamp
|
||||
%}
|
||||
|
||||
{% set period_end_timestamp =
|
||||
sunset_timestamp
|
||||
%}
|
||||
|
||||
{% else %}
|
||||
|
||||
{% set period_start_timestamp =
|
||||
current_timestamp
|
||||
%}
|
||||
|
||||
{% set period_end_timestamp =
|
||||
tomorrow_midnight_timestamp
|
||||
%}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% set ns = namespace(
|
||||
maximum=0,
|
||||
found=false
|
||||
) %}
|
||||
|
||||
{% for index in range(
|
||||
value_json.hourly.time | count
|
||||
) %}
|
||||
|
||||
{% set forecast_end_timestamp =
|
||||
as_timestamp(
|
||||
value_json.hourly.time[index],
|
||||
0
|
||||
)
|
||||
%}
|
||||
|
||||
{% set probability =
|
||||
value_json.hourly.precipitation_probability[index]
|
||||
%}
|
||||
|
||||
{% if
|
||||
forecast_end_timestamp > period_start_timestamp
|
||||
and forecast_end_timestamp < period_end_timestamp + 3600
|
||||
and probability is not none
|
||||
%}
|
||||
|
||||
{% set ns.found = true %}
|
||||
|
||||
{% if probability | int(0) > ns.maximum %}
|
||||
|
||||
{% set ns.maximum =
|
||||
probability | int(0)
|
||||
%}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{{ ns.maximum if ns.found else 0 }}
|
||||
|
||||
#:###################################################################################:#
|
||||
# Rain Chance Tomorrow — Daylight #
|
||||
#:###################################################################################:#
|
||||
#
|
||||
# Uses hourly forecast periods that overlap tomorrow's daylight
|
||||
# period between sunrise and sunset.
|
||||
#
|
||||
|
||||
- name: "Open Meteo Rain Chance Tomorrow"
|
||||
unique_id: open_meteo_rain_chance_tomorrow
|
||||
unit_of_measurement: "%"
|
||||
state_class: measurement
|
||||
icon: mdi:weather-sunset-up
|
||||
|
||||
value_template: >-
|
||||
{% set sunrise_timestamp =
|
||||
as_timestamp(
|
||||
value_json.daily.sunrise[1],
|
||||
0
|
||||
)
|
||||
%}
|
||||
|
||||
{% set sunset_timestamp =
|
||||
as_timestamp(
|
||||
value_json.daily.sunset[1],
|
||||
0
|
||||
)
|
||||
%}
|
||||
|
||||
{% set ns = namespace(
|
||||
maximum=0,
|
||||
found=false
|
||||
) %}
|
||||
|
||||
{% for index in range(
|
||||
value_json.hourly.time | count
|
||||
) %}
|
||||
|
||||
{% set forecast_end_timestamp =
|
||||
as_timestamp(
|
||||
value_json.hourly.time[index],
|
||||
0
|
||||
)
|
||||
%}
|
||||
|
||||
{% set probability =
|
||||
value_json.hourly.precipitation_probability[index]
|
||||
%}
|
||||
|
||||
{% if
|
||||
forecast_end_timestamp > sunrise_timestamp
|
||||
and forecast_end_timestamp < sunset_timestamp + 3600
|
||||
and probability is not none
|
||||
%}
|
||||
|
||||
{% set ns.found = true %}
|
||||
|
||||
{% if probability | int(0) > ns.maximum %}
|
||||
|
||||
{% set ns.maximum =
|
||||
probability | int(0)
|
||||
%}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{{ ns.maximum if ns.found else 0 }}
|
||||
@@ -1,6 +1,11 @@
|
||||
################################################################################
|
||||
# PACKAGE: View Road Announcement Router
|
||||
################################################################################
|
||||
# 1.8: Date: 2026-07-11
|
||||
# - Added MQTT View Rd Feed announcement channel.
|
||||
# - Added mqtt_feed script field.
|
||||
# - MQTT feed publishes the current local date/time to a topic built from
|
||||
# mqtt_view_rd_feed_topic_template by replacing TOPIC with mqtt_feed.
|
||||
# 1.7:
|
||||
# - Updated Lounge Google Home Voice to speak short_announcement only.
|
||||
# - This allows long_announcement to remain available for detailed channels
|
||||
@@ -14,7 +19,7 @@
|
||||
# Central announcement router for general Home Assistant announcements.
|
||||
# Other scripts and automations can call script.view_road_announcement and pass
|
||||
# values such as channels, title, short_announcement, long_announcement,
|
||||
# payload, and indicator.
|
||||
# payload, indicator, and mqtt_feed.
|
||||
#
|
||||
# How to call this script:
|
||||
#
|
||||
@@ -62,7 +67,13 @@
|
||||
# Blocked by default when input_boolean.quiet_time is on.
|
||||
#
|
||||
# mqtt_view_rd_feed:
|
||||
# Placeholder only.
|
||||
# Uses:
|
||||
# mqtt_feed
|
||||
# Publishes the current local date/time to MQTT.
|
||||
# Topic format:
|
||||
# viewroad-status/activityfeed/<mqtt_feed>
|
||||
# Payload format:
|
||||
# YYYY-MM-DD HH:MM:SS
|
||||
#
|
||||
# led_matrix_1:
|
||||
# Uses:
|
||||
@@ -285,6 +296,13 @@ script:
|
||||
selector:
|
||||
text:
|
||||
|
||||
mqtt_feed:
|
||||
name: MQTT Feed Topic
|
||||
description: Activity feed topic suffix. Replaces TOPIC in mqtt_view_rd_feed_topic_template.
|
||||
example: "washing_machine"
|
||||
selector:
|
||||
text:
|
||||
|
||||
sequence:
|
||||
##########################################################################
|
||||
# PACKAGE SETTINGS / SUBSTITUTIONS
|
||||
@@ -305,6 +323,7 @@ script:
|
||||
default_long_announcement: "Home automation announcement"
|
||||
default_payload: ""
|
||||
default_indicator: ""
|
||||
default_mqtt_feed: ""
|
||||
|
||||
quiet_time_blocked_channels:
|
||||
- "google_home_voice"
|
||||
@@ -322,6 +341,11 @@ script:
|
||||
led_matrix_mqtt_qos: 0
|
||||
led_matrix_mqtt_retain: false
|
||||
|
||||
mqtt_view_rd_feed_topic_template: "viewroad-status/activityfeed/TOPIC"
|
||||
mqtt_view_rd_feed_datetime_format: "%Y-%m-%d %H:%M:%S"
|
||||
mqtt_view_rd_feed_mqtt_qos: 0
|
||||
mqtt_view_rd_feed_mqtt_retain: true
|
||||
|
||||
##########################################################################
|
||||
# RESOLVE PASSED VALUES
|
||||
##########################################################################
|
||||
@@ -333,6 +357,7 @@ script:
|
||||
# long_announcement
|
||||
# payload
|
||||
# indicator
|
||||
# mqtt_feed
|
||||
#
|
||||
# Some uppercase variants are also accepted for tolerance.
|
||||
#
|
||||
@@ -395,6 +420,17 @@ script:
|
||||
{{ default_indicator }}
|
||||
{% endif %}
|
||||
|
||||
ann_mqtt_feed: >-
|
||||
{% if mqtt_feed is defined %}
|
||||
{{ mqtt_feed }}
|
||||
{% elif MQTT_Feed is defined %}
|
||||
{{ MQTT_Feed }}
|
||||
{% elif Mqtt_Feed is defined %}
|
||||
{{ Mqtt_Feed }}
|
||||
{% else %}
|
||||
{{ default_mqtt_feed }}
|
||||
{% endif %}
|
||||
|
||||
##########################################################################
|
||||
# NORMALISE CHANNEL LISTS AND MESSAGE TEXT
|
||||
##########################################################################
|
||||
@@ -406,6 +442,15 @@ script:
|
||||
ann_quiet_time_blocked_channels_normalised: >-
|
||||
{{ ',' ~ (quiet_time_blocked_channels | join(',') | lower | replace(' ', '') | replace('\n', '') | trim(',')) ~ ',' }}
|
||||
|
||||
ann_mqtt_feed_topic_suffix: >-
|
||||
{{ ann_mqtt_feed | string | trim }}
|
||||
|
||||
ann_mqtt_feed_topic: >-
|
||||
{{ mqtt_view_rd_feed_topic_template | replace('TOPIC', ann_mqtt_feed_topic_suffix) }}
|
||||
|
||||
ann_mqtt_feed_datetime: >-
|
||||
{{ now().strftime(mqtt_view_rd_feed_datetime_format) }}
|
||||
|
||||
ann_short_announcement_raw: >-
|
||||
{% if short_announcement is defined %}
|
||||
{{ short_announcement }}
|
||||
@@ -575,10 +620,43 @@ script:
|
||||
# CHANNEL: MQTT VIEW RD FEED
|
||||
##########################################################################
|
||||
#
|
||||
# Placeholder only. No action yet.
|
||||
# Channel name:
|
||||
# mqtt_view_rd_feed
|
||||
#
|
||||
# Uses:
|
||||
# mqtt_feed
|
||||
#
|
||||
# Publishes the current Home Assistant local time in AM/PM format.
|
||||
#
|
||||
# Topic format:
|
||||
# viewroad-status/activityfeed/<mqtt_feed>
|
||||
#
|
||||
# Example:
|
||||
# mqtt_feed: "dogfed"
|
||||
#
|
||||
# Publishes:
|
||||
# Topic: viewroad-status/activityfeed/dogfed
|
||||
# Payload: 12:32 PM
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
- if:
|
||||
- condition: template
|
||||
value_template: "{{ ',mqtt_view_rd_feed,' in ann_channels_normalised }}"
|
||||
- condition: state
|
||||
entity_id: input_boolean.announcement_channel_mqtt_view_rd_feed
|
||||
state: "on"
|
||||
- condition: template
|
||||
value_template: "{{ ann_mqtt_feed_topic_suffix | string | trim | length > 0 }}"
|
||||
then:
|
||||
- action: mqtt.publish
|
||||
data:
|
||||
topic: "{{ ann_mqtt_feed_topic }}"
|
||||
#payload: "{{ now().strftime('%I:%M %p') | regex_replace('^0', '') }}"
|
||||
payload: "{{ now().strftime('%H:%M') }}"
|
||||
qos: "{{ mqtt_view_rd_feed_mqtt_qos | int(0) }}"
|
||||
retain: "{{ mqtt_view_rd_feed_mqtt_retain | bool(true) }}"
|
||||
|
||||
##########################################################################
|
||||
# CHANNEL: LOUNGE LED MATRIX DISPLAY - MATRIX 1
|
||||
##########################################################################
|
||||
|
||||
Reference in New Issue
Block a user