Files
zorruno-homeassistant/packages/view_road_announcement_router.yaml
2026-07-20 19:24:35 +12:00

734 lines
26 KiB
YAML

################################################################################
# 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
# such as Pushover without making voice announcements too long.
# 1.6:
# - Updated Sony TV Lounge channel to use short_announcement only.
# - Removed Sony TV Lounge payload suffix from message formatting.
# 1.5: Date: 2026-06-04
#
# Purpose:
# 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, indicator, and mqtt_feed.
#
# How to call this script:
#
# - action: script.view_road_announcement
# data:
# channels: "pushover_zorruno, lounge_google_home_voice, led_matrix_1"
# title: "View Road"
# short_announcement: "Washing complete"
# long_announcement: "The washing machine has finished."
# payload: ""
# indicator: "wash,1,15,10,6,5,1,0"
#
# Available channels:
#
# pushover_zorruno:
# Uses:
# title
# long_announcement
#
# pushover_kim:
# Uses:
# title
# long_announcement
#
# sony_tv_lounge:
# Uses:
# title
# short_announcement
# Message format:
# "<short_announcement>"
#
# lounge_google_home_voice:
# Also accepts alias:
# google_home_voice
# Uses:
# short_announcement
# Notes:
# /s prefixes are stripped before being sent to voice.
# Quiet time:
# Blocked by default when input_boolean.quiet_time is on.
#
# lounge_touchscreen_voice:
# Placeholder only.
# Quiet time:
# Blocked by default when input_boolean.quiet_time is on.
#
# mqtt_view_rd_feed:
# 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:
# short_announcement
# indicator
# Publishes to MQTT topic:
# viewroad-commands/ledmatrix1/announce
# Message format:
# "<short_announcement> [<indicator>]"
# Example:
# "Washing complete [wash,1,15,10,6,5,1,0]"
#
# led_matrix_2:
# Future channel.
# Uses the same format as led_matrix_1.
# Publishes to MQTT topic:
# viewroad-commands/ledmatrix2/announce
#
# LED matrix announcement format:
#
# Message text [identifier,transition_mode,speed,repeat_seconds,repeat_times,static_wait,sounder_quantity,sound_id]
#
# Example script call:
#
# - action: script.view_road_announcement
# data:
# channels: "led_matrix_1"
# short_announcement: "Washing complete"
# indicator: "wash,1,15,10,6,5,1,0"
#
# Result sent to MQTT:
#
# Washing complete [wash,1,15,10,6,5,1,0]
#
# Indicator fields:
#
# identifier:
# Announcement identifier used by the LED matrix ESPHome logic.
# It is cleaned by ESPHome to letters, numbers, underscore, or dash, and
# is limited to 8 characters.
#
# transition_mode:
# 0 = Slide up
# 1 = Slide down
# 2 = Pixel fall
# 3 = Static Up, Down
# 4 = Static Down, Up
#
# speed:
# Per-message scroll delay in ms.
# Clamped by ESPHome from 1 to 100.
#
# repeat_seconds:
# Delay between completed scrolls.
# Clamped by ESPHome from 0 to 99.
#
# repeat_times:
# Total number of scroll displays.
# Clamped by ESPHome from 0 to 99.
# 0 is treated as a one-shot announcement.
#
# static_wait:
# Per-message static wait time in seconds.
# Clamped by ESPHome from 0 to 30.
# Only affects transition modes 3 and 4.
# Other transition modes ignore it.
#
# sounder_quantity:
# Number of announcement displays that should beep first.
# 0 means no sounder beep.
#
# sound_id:
# Stored by the LED matrix ESPHome logic for future sounder logic.
# It is not currently used by the display logic.
#
# Notes:
# The announcement router does not parse, clean, or clamp the indicator
# fields. It passes the indicator through to the LED matrix in square
# brackets. The LED matrix ESPHome YAML handles validation and behaviour.
#
# The router does not intentionally trim leading spaces from
# short_announcement for LED matrix messages. The previous invisible leading
# space guard workaround has been removed.
#
# Changes:
# 1.5:
# - Removed LED matrix invisible leading-space guard workaround.
# - Updated LED matrix announcement comments for the current 8-field format.
# - Updated LED matrix transition comments for modes 0-4.
# - Added static_wait and sound_id documentation to router comments.
#
# 1.4:
# - Documented LED matrix indicator format.
# - Clarified that LED matrix indicator validation is handled by ESPHome.
#
# 1.3:
# - Added led_matrix_1 announcement channel.
# - Added future led_matrix_2 announcement channel.
# - Added MQTT topic settings for LED matrix announcement channels.
# - Added channel enable helpers for led_matrix_1 and led_matrix_2.
# - Added package instructions for calling script.view_road_announcement.
# - Moved more configurable values into the package settings section.
# - Added lounge Google Home cast chime suppression setting.
#
# 1.2:
# - Updated Lounge Google Home voice channel to use working Piper TTS setup.
# - Added Piper voice option en_GB-alba-medium.
# - Removed separate TTS language option from the voice channel.
#
# 1.1:
# - Removed old YAML Pushover notify service setup.
# - Uses existing Pushover integration notify entities.
# - Added quiet time channel blocking.
# - Added Lounge Google Home voice announcement channel.
#
# Notes:
# - Use input_boolean helpers for channel enable/disable control.
# - Binary sensors are read-only, so input_boolean is the correct helper type.
# - Channels with no action block yet intentionally do nothing.
#
################################################################################
################################################################################
# CHANNEL ENABLE HELPERS
################################################################################
input_boolean:
announcement_channel_pushover_zorruno:
name: Announcement Channel - Pushover Zorruno
icon: mdi:cellphone-message
initial: true
announcement_channel_pushover_kim:
name: Announcement Channel - Pushover Kim
icon: mdi:cellphone-message
initial: true
announcement_channel_sony_tv_lounge:
name: Announcement Channel - Sony TV Lounge
icon: mdi:television
initial: true
announcement_channel_lounge_google_home_voice:
name: Announcement Channel - Lounge Google Home Voice
icon: mdi:speaker
initial: true
announcement_channel_lounge_touchscreen_voice:
name: Announcement Channel - Lounge Touchscreen Voice
icon: mdi:tablet-dashboard
initial: true
announcement_channel_mqtt_view_rd_feed:
name: Announcement Channel - MQTT View Rd Feed
icon: mdi:message-processing
initial: true
announcement_channel_led_matrix_1:
name: Announcement Channel - LED Matrix 1
icon: mdi:led-strip-variant
initial: true
announcement_channel_led_matrix_2:
name: Announcement Channel - LED Matrix 2
icon: mdi:led-strip-variant
initial: true
################################################################################
# MAIN ANNOUNCEMENT ROUTER SCRIPT
################################################################################
script:
view_road_announcement:
alias: View Road Announcement
icon: mdi:bullhorn
mode: parallel
max: 20
fields:
channels:
name: Channels
description: Comma separated list of announcement channels to use.
example: "pushover_zorruno, sony_tv_lounge, led_matrix_1"
selector:
text:
title:
name: Title
description: Announcement title.
example: "View Road"
selector:
text:
short_announcement:
name: Short Announcement
description: Short announcement text.
example: "Garage door"
selector:
text:
long_announcement:
name: Long Announcement
description: Longer announcement text.
example: "The garage door has been opened."
selector:
text:
multiline: true
payload:
name: Payload
description: Payload value such as On, Off, Open, Closed, etc.
example: "Open"
selector:
text:
indicator:
name: Indicator
description: LED matrix indicator data in the format identifier,transition_mode,speed,repeat_seconds,repeat_times,static_wait,sounder_quantity,sound_id.
example: "wash,1,15,10,6,5,1,0"
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
##########################################################################
#
# Home Assistant packages do not support ESPHome-style substitutions.
# These variables act as the package-level settings for this script.
#
# If a value is not passed to the script, the default below is used.
# If a value is passed as "", it clears the default to blank.
#
##########################################################################
- variables:
default_channels: "pushover_zorruno, pushover_kim, sony_tv_lounge, lounge_google_home_voice, lounge_touchscreen_voice, mqtt_view_rd_feed, led_matrix_1, led_matrix_2"
default_title: "View Road"
default_short_announcement: "Home automation announcement"
default_long_announcement: "Home automation announcement"
default_payload: ""
default_indicator: ""
default_mqtt_feed: ""
quiet_time_blocked_channels:
- "google_home_voice"
- "lounge_google_home_voice"
- "lounge_touchscreen_voice"
lounge_google_home_voice_media_player: "media_player.lounge_google_tichome_speaker"
lounge_google_home_voice_tts_entity: "tts.piper"
lounge_google_home_voice_piper_voice: "en_GB-jenny_dioco-medium"
lounge_google_home_voice_volume_level: 0.80
lounge_google_home_voice_suppress_cast_chime: false
led_matrix_1_mqtt_topic: "viewroad-commands/ledmatrix1/announce"
led_matrix_2_mqtt_topic: "viewroad-commands/ledmatrix2/announce"
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
##########################################################################
#
# Lowercase field names are preferred:
# channels
# title
# short_announcement
# long_announcement
# payload
# indicator
# mqtt_feed
#
# Some uppercase variants are also accepted for tolerance.
#
##########################################################################
- variables:
ann_channels_raw: >-
{% if channels is defined %}
{{ channels }}
{% elif channel is defined %}
{{ channel }}
{% elif Channel is defined %}
{{ Channel }}
{% else %}
{{ default_channels }}
{% endif %}
ann_title: >-
{% if title is defined %}
{{ title }}
{% elif Title is defined %}
{{ Title }}
{% else %}
{{ default_title }}
{% endif %}
ann_short_announcement: >-
{% if short_announcement is defined %}
{{ short_announcement }}
{% elif Short_Announcement is defined %}
{{ Short_Announcement }}
{% else %}
{{ default_short_announcement }}
{% endif %}
ann_long_announcement: >-
{% if long_announcement is defined %}
{{ long_announcement }}
{% elif Long_Announcement is defined %}
{{ Long_Announcement }}
{% else %}
{{ default_long_announcement }}
{% endif %}
ann_payload: >-
{% if payload is defined %}
{{ payload }}
{% elif Payload is defined %}
{{ Payload }}
{% else %}
{{ default_payload }}
{% endif %}
ann_indicator: >-
{% if indicator is defined %}
{{ indicator }}
{% elif Indicator is defined %}
{{ Indicator }}
{% else %}
{{ 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
##########################################################################
- variables:
ann_channels_normalised: >-
{{ ',' ~ (ann_channels_raw | string | lower | replace(' ', '') | replace('\n', '') | trim(',')) ~ ',' }}
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 }}
{% elif Short_Announcement is defined %}
{{ Short_Announcement }}
{% else %}
{{ default_short_announcement }}
{% endif %}
ann_short_announcement_clean: >-
{{ ann_short_announcement_raw | string | regex_replace('^(?:/s)+', '') | trim }}
ann_sony_tv_message: >-
{{ ann_short_announcement_clean }}
ann_voice_message: >-
{{ ann_short_announcement_clean }}
ann_led_matrix_1_message: >-
{%- set short_text = ann_short_announcement_raw -%}
{%- set indicator_text = ann_indicator | string | trim -%}
{{- short_text | string -}}{{ ' [' ~ indicator_text ~ ']' if indicator_text | length > 0 else '' }}
ann_led_matrix_2_message: >-
{%- set short_text = ann_short_announcement_clean -%}
{%- set indicator_text = ann_indicator | string | trim -%}
{{- short_text | string -}}{{ ' [' ~ indicator_text ~ ']' if indicator_text | length > 0 else '' }}
##########################################################################
# CHANNEL: PUSHOVER ZORRUNO
##########################################################################
- if:
- condition: template
value_template: "{{ ',pushover_zorruno,' in ann_channels_normalised }}"
- condition: state
entity_id: input_boolean.announcement_channel_pushover_zorruno
state: "on"
then:
- action: notify.pushover_zorruno
data:
title: "{{ ann_title }}"
message: "{{ ann_long_announcement }}"
##########################################################################
# CHANNEL: PUSHOVER KIM
##########################################################################
- if:
- condition: template
value_template: "{{ ',pushover_kim,' in ann_channels_normalised }}"
- condition: state
entity_id: input_boolean.announcement_channel_pushover_kim
state: "on"
then:
- action: notify.pushover_kim
data:
title: "{{ ann_title }}"
message: "{{ ann_long_announcement }}"
##########################################################################
# CHANNEL: SONY TV LOUNGE
##########################################################################
- if:
- condition: template
value_template: "{{ ',sony_tv_lounge,' in ann_channels_normalised }}"
- condition: state
entity_id: input_boolean.announcement_channel_sony_tv_lounge
state: "on"
- condition: template
value_template: "{{ ann_sony_tv_message | string | trim | length > 0 }}"
then:
- action: notify.sony_android_tv_lounge
data:
title: "{{ ann_title }}"
message: "{{ ann_sony_tv_message }}"
##########################################################################
# CHANNEL: LOUNGE GOOGLE HOME VOICE
##########################################################################
#
# Also accepts google_home_voice as an alias channel name.
#
# This channel is blocked during quiet time by default.
#
##########################################################################
- if:
- condition: template
value_template: >-
{{
',lounge_google_home_voice,' in ann_channels_normalised
or ',google_home_voice,' in ann_channels_normalised
}}
- condition: state
entity_id: input_boolean.announcement_channel_lounge_google_home_voice
state: "on"
- condition: template
value_template: >-
{{ not (
is_state('input_boolean.quiet_time', 'on')
and (
',lounge_google_home_voice,' in ann_quiet_time_blocked_channels_normalised
or ',google_home_voice,' in ann_quiet_time_blocked_channels_normalised
)
) }}
- condition: template
value_template: "{{ ann_voice_message | string | trim | length > 0 }}"
then:
- choose:
- conditions:
- condition: template
value_template: "{{ lounge_google_home_voice_suppress_cast_chime | bool(false) }}"
- condition: template
value_template: "{{ states(lounge_google_home_voice_media_player) in ['off', 'unavailable', 'unknown'] }}"
sequence:
- action: media_player.volume_set
data:
entity_id: "{{ lounge_google_home_voice_media_player }}"
volume_level: 0
- action: media_player.turn_on
target:
entity_id: "{{ lounge_google_home_voice_media_player }}"
- wait_template: >-
{{ states(lounge_google_home_voice_media_player) in ['idle', 'paused', 'playing', 'on'] }}
timeout:
seconds: 5
continue_on_timeout: true
- delay:
seconds: 1
- action: media_player.volume_set
data:
entity_id: "{{ lounge_google_home_voice_media_player }}"
volume_level: "{{ lounge_google_home_voice_volume_level | float(0.8) }}"
- delay:
seconds: 1
- action: tts.speak
target:
entity_id: "{{ lounge_google_home_voice_tts_entity }}"
data:
cache: false
media_player_entity_id: "{{ lounge_google_home_voice_media_player }}"
message: "{{ ann_voice_message }}"
options:
voice: "{{ lounge_google_home_voice_piper_voice }}"
preferred_format: mp3
preferred_sample_rate: 44100
##########################################################################
# CHANNEL: LOUNGE TOUCHSCREEN VOICE
##########################################################################
#
# Placeholder only. No action yet.
#
# This channel is listed in quiet_time_blocked_channels for future use.
#
##########################################################################
##########################################################################
# CHANNEL: MQTT VIEW RD FEED
##########################################################################
#
# 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
##########################################################################
#
# Channel name:
# led_matrix_1
#
# Uses:
# short_announcement
# indicator
#
# Publishes:
# <short_announcement> [<indicator>]
#
# Example payload:
# Washing complete [wash,1,15,10,6,5,1,0]
#
# Indicator format:
# identifier,transition_mode,speed,repeat_seconds,repeat_times,static_wait,sounder_quantity,sound_id
#
##########################################################################
- if:
- condition: template
value_template: "{{ ',led_matrix_1,' in ann_channels_normalised }}"
- condition: state
entity_id: input_boolean.announcement_channel_led_matrix_1
state: "on"
- condition: template
value_template: "{{ ann_led_matrix_1_message | string | trim | length > 0 }}"
then:
- action: mqtt.publish
data:
topic: "{{ led_matrix_1_mqtt_topic }}"
payload: "{{ ann_led_matrix_1_message }}"
qos: "{{ led_matrix_mqtt_qos | int(0) }}"
retain: "{{ led_matrix_mqtt_retain | bool(false) }}"
##########################################################################
# CHANNEL: LOUNGE LED MATRIX DISPLAY - MATRIX 2
##########################################################################
#
# Future channel.
#
# Channel name:
# led_matrix_2
#
# Uses:
# short_announcement
# indicator
#
# Publishes:
# <short_announcement> [<indicator>]
#
# Indicator format:
# identifier,transition_mode,speed,repeat_seconds,repeat_times,static_wait,sounder_quantity,sound_id
#
##########################################################################
- if:
- condition: template
value_template: "{{ ',led_matrix_2,' in ann_channels_normalised }}"
- condition: state
entity_id: input_boolean.announcement_channel_led_matrix_2
state: "on"
- condition: template
value_template: "{{ ann_led_matrix_2_message | string | trim | length > 0 }}"
then:
- action: mqtt.publish
data:
topic: "{{ led_matrix_2_mqtt_topic }}"
payload: "{{ ann_led_matrix_2_message }}"
qos: "{{ led_matrix_mqtt_qos | int(0) }}"
retain: "{{ led_matrix_mqtt_retain | bool(false) }}"