additional esphome devices and fixes

This commit is contained in:
root
2026-05-23 23:53:04 +12:00
parent 5e941eea06
commit 7eb81efd93
61 changed files with 7756 additions and 354 deletions
+389
View File
@@ -0,0 +1,389 @@
# yaml-language-server: $schema=null
###############################################################################
# PACKAGE: 16A EV Charger Control
###############################################################################
#
# VERSION:
# V1.1 2026-05-15
# - Reworked 1hr topup logic to use a hard deadline and watchdog.
# - Removed dependency on timer.finished event for relay shutoff.
# - Offpeak until charged now continues past offpeak end until charging stops.
# - 1hr topup now now rolls into Normal Offpeak if the hour ends during
# the offpeak window, without switching the relay off and back on.
#
# V1.0 2026-05-11
# - Initial package for 16A EV charger offpeak and charge-until-full control.
#
# PACKAGE SETTINGS:
# Car display name:
# - Leaf
#
# Charger relay output:
# - switch.garage_db_control_16a_wallcharger_operation
#
# Vehicle charging sensor:
# - binary_sensor.garage_db_control_16a_wallcharger_charging
#
# Default offpeak period:
# - Start: 21:00:00
# - End: 00:00:00
#
###############################################################################
input_datetime:
ev_16a_offpeak_start:
name: 16A EV Offpeak Start
has_date: false
has_time: true
initial: "21:00:00"
ev_16a_offpeak_end:
name: 16A EV Offpeak End
has_date: false
has_time: true
initial: "00:00:00"
ev_16a_1hr_topup_until:
name: 16A EV 1hr topup until
has_date: true
has_time: true
initial: "2000-01-01 00:00:00"
input_select:
ev_16a_charge_mode:
name: Leaf EV charge mode
icon: mdi:ev-station
options:
- "Normal (Offpeak)"
- "Offpeak until charged"
- "1hr topup now"
- "Charge now until full"
- "Stop charging now"
initial: "Normal (Offpeak)"
automation:
#############################################################################
# OFFPEAK START
#############################################################################
- id: ev_16a_charger_offpeak_start
alias: "16A EV Charger - Offpeak Start"
mode: single
triggers:
- trigger: time
at: input_datetime.ev_16a_offpeak_start
conditions:
- condition: template
value_template: >
{{ states('input_select.ev_16a_charge_mode') in
['Normal (Offpeak)', 'Offpeak until charged'] }}
actions:
- action: switch.turn_on
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
- choose:
- conditions:
- condition: state
entity_id: input_select.ev_16a_charge_mode
state: "Offpeak until charged"
sequence:
# If the car never starts charging, or is already full, turn off
# after a 5 minute grace period.
- delay: "00:05:00"
- condition: state
entity_id: input_select.ev_16a_charge_mode
state: "Offpeak until charged"
- condition: state
entity_id: binary_sensor.garage_db_control_16a_wallcharger_charging
state: "off"
- action: switch.turn_off
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
- action: input_select.select_option
target:
entity_id: input_select.ev_16a_charge_mode
data:
option: "Normal (Offpeak)"
#############################################################################
# OFFPEAK END
#############################################################################
- id: ev_16a_charger_offpeak_end
alias: "16A EV Charger - Offpeak End"
mode: single
triggers:
- trigger: time
at: input_datetime.ev_16a_offpeak_end
conditions:
- condition: state
entity_id: input_select.ev_16a_charge_mode
state: "Normal (Offpeak)"
actions:
- action: switch.turn_off
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
#############################################################################
# USER CHARGE MODE SELECTIONS
#############################################################################
- id: ev_16a_charger_charge_mode_selected
alias: "16A EV Charger - Charge Mode Selected"
mode: restart
triggers:
- trigger: state
entity_id: input_select.ev_16a_charge_mode
actions:
- variables:
selected_mode: "{{ trigger.to_state.state }}"
is_offpeak_now: >
{% set start = states('input_datetime.ev_16a_offpeak_start') %}
{% set end = states('input_datetime.ev_16a_offpeak_end') %}
{% set now_time = now().strftime('%H:%M:%S') %}
{% if start == end %}
{{ true }}
{% elif start < end %}
{{ start <= now_time < end }}
{% else %}
{{ now_time >= start or now_time < end }}
{% endif %}
- choose:
#####################################################################
# NORMAL OFFPEAK
#####################################################################
- conditions:
- condition: template
value_template: "{{ selected_mode == 'Normal (Offpeak)' }}"
sequence:
# No immediate action.
# Normal mode only acts when the offpeak start/end triggers fire.
- stop: "Normal offpeak mode selected."
#####################################################################
# OFFPEAK UNTIL CHARGED
#####################################################################
- conditions:
- condition: template
value_template: "{{ selected_mode == 'Offpeak until charged' }}"
sequence:
- if:
- condition: template
value_template: "{{ is_offpeak_now }}"
then:
- action: switch.turn_on
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
# If the car never starts charging, or is already full, turn
# off after a 5 minute grace period.
- delay: "00:05:00"
- condition: state
entity_id: input_select.ev_16a_charge_mode
state: "Offpeak until charged"
- condition: state
entity_id: binary_sensor.garage_db_control_16a_wallcharger_charging
state: "off"
- action: switch.turn_off
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
- action: input_select.select_option
target:
entity_id: input_select.ev_16a_charge_mode
data:
option: "Normal (Offpeak)"
#####################################################################
# 1 HOUR TOPUP NOW
#####################################################################
- conditions:
- condition: template
value_template: "{{ selected_mode == '1hr topup now' }}"
sequence:
- action: input_datetime.set_datetime
target:
entity_id: input_datetime.ev_16a_1hr_topup_until
data:
datetime: >
{{ (as_timestamp(now()) + 3600)
| timestamp_custom('%Y-%m-%d %H:%M:%S', true) }}
- action: switch.turn_on
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
#####################################################################
# CHARGE NOW UNTIL FULL
#####################################################################
- conditions:
- condition: template
value_template: "{{ selected_mode == 'Charge now until full' }}"
sequence:
- action: switch.turn_on
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
# If the car never starts charging, or is already full, turn off
# after a 5 minute grace period.
- delay: "00:05:00"
- condition: state
entity_id: input_select.ev_16a_charge_mode
state: "Charge now until full"
- condition: state
entity_id: binary_sensor.garage_db_control_16a_wallcharger_charging
state: "off"
- action: switch.turn_off
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
- action: input_select.select_option
target:
entity_id: input_select.ev_16a_charge_mode
data:
option: "Normal (Offpeak)"
#####################################################################
# STOP CHARGING NOW
#####################################################################
- conditions:
- condition: template
value_template: "{{ selected_mode == 'Stop charging now' }}"
sequence:
- action: switch.turn_off
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
- action: input_select.select_option
target:
entity_id: input_select.ev_16a_charge_mode
data:
option: "Normal (Offpeak)"
#############################################################################
# 1 HOUR TOPUP WATCHDOG
#############################################################################
- id: ev_16a_charger_1hr_topup_watchdog
alias: "16A EV Charger - 1hr Topup Watchdog"
mode: single
triggers:
- trigger: time_pattern
minutes: "/1"
- trigger: homeassistant
event: start
conditions:
- condition: state
entity_id: input_select.ev_16a_charge_mode
state: "1hr topup now"
- condition: template
value_template: >
{{ as_timestamp(now()) >=
as_timestamp(states('input_datetime.ev_16a_1hr_topup_until')) }}
actions:
- variables:
is_offpeak_now: >
{% set start = states('input_datetime.ev_16a_offpeak_start') %}
{% set end = states('input_datetime.ev_16a_offpeak_end') %}
{% set now_time = now().strftime('%H:%M:%S') %}
{% if start == end %}
{{ true }}
{% elif start < end %}
{{ start <= now_time < end }}
{% else %}
{{ now_time >= start or now_time < end }}
{% endif %}
- action: input_select.select_option
target:
entity_id: input_select.ev_16a_charge_mode
data:
option: "Normal (Offpeak)"
- choose:
# If the 1 hour topup finishes during offpeak, do not flick the relay.
# Leave it on and let the Normal Offpeak end automation turn it off.
- conditions:
- condition: template
value_template: "{{ is_offpeak_now }}"
sequence:
- if:
- condition: state
entity_id: switch.garage_db_control_16a_wallcharger_operation
state: "off"
then:
- action: switch.turn_on
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
default:
- if:
- condition: state
entity_id: switch.garage_db_control_16a_wallcharger_operation
state: "on"
then:
- action: switch.turn_off
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
#############################################################################
# CHARGING COMPLETE MONITOR
#############################################################################
- id: ev_16a_charger_stop_when_charging_complete
alias: "16A EV Charger - Stop When Charging Complete"
mode: single
triggers:
- trigger: state
entity_id: binary_sensor.garage_db_control_16a_wallcharger_charging
to: "off"
for: "00:05:00"
conditions:
- condition: template
value_template: >
{{ states('input_select.ev_16a_charge_mode') in
['Offpeak until charged', 'Charge now until full'] }}
actions:
- action: switch.turn_off
target:
entity_id: switch.garage_db_control_16a_wallcharger_operation
- action: input_select.select_option
target:
entity_id: input_select.ev_16a_charge_mode
data:
option: "Normal (Offpeak)"
+12 -11
View File
@@ -17,14 +17,14 @@ automation:
entity_id: input_button.announcement_test
action:
- action: script.view_road_announcement
data:
channels: "sony_tv_lounge"
title: "View Road Test"
short_announcement: "Test announcement"
long_announcement: "This is a test announcement from the package test button."
payload: "On"
indicator: ""
# - action: script.view_road_announcement
# data:
# channels: "sony_tv_lounge"
# title: "View Road Test"
# short_announcement: "Test announcement"
# long_announcement: "This is a test announcement from the package test button."
# payload: "On"
# indicator: ""
#- action: script.view_road_announcement
# data:
@@ -34,6 +34,7 @@ automation:
- action: script.view_road_announcement
data:
channels: "lounge_google_home_voice"
title: "View Road Test"
long_announcement: "This is a test announcement on the lounge Google Home."
channels: "lounge_google_home_voice, sony_tv_lounge"
title: "View Road "
short_announcement: "9pm, Free Power time"
long_announcement: "It is 9pm."
@@ -0,0 +1,64 @@
################################################################################
# PACKAGE: Underhouse Entrance Auto Lights
################################################################################
#
# Version:
# 1.2 - 2026-05-12
# - Added fast Zigbee2MQTT FP1-style event triggers:
# sensor.underhouse_mmwave_sensor_x23ms_presence_event = enter
# sensor.underhouse_mmwave_sensor_x23ms_presence_event = approach
# - Keeps binary presence as a backup trigger and as the clear/off condition.
# - This should behave closer to the previous Node-RED automation.
#
# Notes:
# - The UI may show the binary sensor as "Detected", but the YAML state is
# normally "on".
# - The presence_event sensor can react earlier than the binary presence sensor.
# - The event sensor is used to turn lights on quickly, but not to decide when
# the area is clear, because it may remain on its last event value.
#
################################################################################
automation:
- id: underhouse_entrance_auto_lights
alias: "Underhouse Entrance - Auto Lights"
description: "Turns underhouse entrance lights on from Zigbee2MQTT mmWave enter/approach/presence, then off 400 seconds after presence clears."
mode: restart
max_exceeded: silent
trigger:
- platform: state
entity_id: sensor.underhouse_mmwave_sensor_x23ms_presence_event
to: "enter"
- platform: state
entity_id: sensor.underhouse_mmwave_sensor_x23ms_presence_event
to: "approach"
- platform: state
entity_id: binary_sensor.underhouse_mmwave_sensor_x23ms_presence
to: "on"
action:
- alias: "Turn on the underhouse entrance lights"
action: switch.turn_on
target:
entity_id: switch.esp_underhouselights_underhouse_entrance_lights
- alias: "Wait until the mmWave presence sensor is clear"
wait_template: >
{{ is_state('binary_sensor.underhouse_mmwave_sensor_x23ms_presence', 'off') }}
- alias: "Keep lights on for 400 seconds after presence clears"
delay:
seconds: 400
- alias: "Only continue if presence is still clear"
condition: state
entity_id: binary_sensor.underhouse_mmwave_sensor_x23ms_presence
state: "off"
- alias: "Turn off the underhouse entrance lights"
action: switch.turn_off
target:
entity_id: switch.esp_underhouselights_underhouse_entrance_lights
@@ -0,0 +1,276 @@
#:########################################################################################:#
# TITLE: UNDERHOUSE STORAGE LIGHTS AUTO LIGHTS PACKAGE
#:########################################################################################:#
# DESCRIPTION:
# Replaces the Node-RED automation for the underhouse storage lights.
# Doors, PIR sensors, a remote switch, and local relay changes can start or
# extend a 1 hour lighting timer.
#
# VERSION:
# V1.0 2026-05-12
# - Initial Home Assistant package version.
#
# EDIT NOTES:
# - Add future door contacts in BOTH places marked FUTURE DOOR.
# - Add future PIR sensors in the PIR group marked FUTURE PIR.
# - The generated group entities used below should be:
# binary_sensor.underhouse_storage_door_contacts
# binary_sensor.underhouse_storage_pir_presence
#:########################################################################################:#
binary_sensor:
- platform: group
name: Underhouse Storage Door Contacts
unique_id: underhouse_storage_door_contacts
device_class: door
all: false
entities:
- binary_sensor.underhouse_stealth_door_x07rs_contact
- binary_sensor.underhouse_north_door_door
# FUTURE DOOR: add the next underhouse storage door contact here.
# - binary_sensor.underhouse_future_door_contact
- platform: group
name: Underhouse Storage PIR Presence
unique_id: underhouse_storage_pir_presence
device_class: occupancy
all: false
entities:
- binary_sensor.underhouse_pir_sensor_south_occupancy
# FUTURE PIR: uncomment this when the north PIR exists.
# - binary_sensor.underhouse_pir_sensor_north_occupancy
timer:
underhouse_storage_lights_runtime:
name: Underhouse Storage Lights Runtime
duration: "01:00:00"
restore: true
icon: mdi:timer-outline
script:
underhouse_storage_lights_start_runtime:
alias: Underhouse Storage Lights - Start Or Extend Runtime
mode: restart
sequence:
- choose:
- conditions:
- condition: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
state: "off"
sequence:
- action: switch.turn_on
target:
entity_id: switch.esp_underhouselights_underhouse_storage_lights
- action: timer.start
target:
entity_id: timer.underhouse_storage_lights_runtime
data:
duration: "0:20:00"
underhouse_storage_lights_stop_runtime:
alias: Underhouse Storage Lights - Stop Runtime
mode: restart
sequence:
- choose:
- conditions:
- condition: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
state: "on"
sequence:
- action: switch.turn_off
target:
entity_id: switch.esp_underhouselights_underhouse_storage_lights
- choose:
- conditions:
- condition: template
value_template: >-
{{ not is_state('timer.underhouse_storage_lights_runtime', 'idle') }}
sequence:
- action: timer.cancel
target:
entity_id: timer.underhouse_storage_lights_runtime
automation:
- id: underhouse_storage_lights_start_extend_runtime
alias: Underhouse Storage Lights - Start Or Extend Runtime
description: >-
Turns the storage lights on and starts or restarts the 1 hour timer when
a door opens, PIR detects occupancy, or the remote switch is pressed.
mode: restart
trigger:
- platform: state
entity_id: binary_sensor.underhouse_storage_door_contacts
to: "on"
- platform: state
entity_id: binary_sensor.underhouse_storage_pir_presence
to: "on"
- platform: state
entity_id: binary_sensor.esp_underhouselights_underhouse_storage_lights_remote_switch
to: "on"
action:
- action: script.underhouse_storage_lights_start_runtime
- id: underhouse_storage_lights_start_timer_when_relay_turned_on
alias: Underhouse Storage Lights - Start Timer When Relay Turned On
description: >-
Starts the timer if the relay is turned on locally by ESPHome or
by another Home Assistant automation.
mode: restart
trigger:
- platform: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
to: "on"
action:
- action: timer.start
target:
entity_id: timer.underhouse_storage_lights_runtime
data:
duration: "00:20:00"
- id: underhouse_storage_lights_timer_finished
alias: Underhouse Storage Lights - Timer Finished
description: >-
Turns the storage lights off after the runtime expires, even if a
door has been left open.
mode: single
trigger:
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.underhouse_storage_lights_runtime
action:
- choose:
- conditions:
- condition: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
state: "on"
sequence:
- action: switch.turn_off
target:
entity_id: switch.esp_underhouselights_underhouse_storage_lights
- id: underhouse_storage_lights_cancel_timer_when_relay_off
alias: Underhouse Storage Lights - Cancel Timer When Relay Off
description: >-
Keeps the timer helper tidy if the relay is turned off manually, locally,
or by another automation.
mode: restart
trigger:
- platform: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
to: "off"
condition:
- condition: template
value_template: >-
{{ not is_state('timer.underhouse_storage_lights_runtime', 'idle') }}
action:
- action: timer.cancel
target:
entity_id: timer.underhouse_storage_lights_runtime
- id: underhouse_storage_lights_all_doors_closed
alias: Underhouse Storage Lights - All Doors Closed
description: >-
When all door contacts are closed, turn the lights off immediately if no
PIR occupancy is active. If PIR is still active, the PIR clear automation
below will turn them off after 60 seconds without occupancy.
mode: restart
trigger:
- platform: state
entity_id: binary_sensor.underhouse_storage_door_contacts
from: "on"
to: "off"
condition:
- condition: state
entity_id: binary_sensor.underhouse_storage_pir_presence
state: "off"
action:
- action: script.underhouse_storage_lights_stop_runtime
- id: underhouse_storage_lights_individual_door_closed_check
alias: Underhouse Storage Lights - Individual Door Closed No Motion Check
description: >-
When a real door contact closes, wait 60 seconds and then turn the relay
off only if all doors are closed and there is no PIR occupancy.
mode: restart
trigger:
- platform: state
entity_id:
- binary_sensor.underhouse_stealth_door_x07rs_contact
- binary_sensor.underhouse_north_door_door
# FUTURE DOOR: add the next underhouse storage door contact here too.
# - binary_sensor.underhouse_future_door_contact
from: "on"
to: "off"
action:
- delay: "00:01:00"
- condition: state
entity_id: binary_sensor.underhouse_storage_door_contacts
state: "off"
- condition: state
entity_id: binary_sensor.underhouse_storage_pir_presence
state: "off"
- condition: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
state: "on"
- action: script.underhouse_storage_lights_stop_runtime
- id: underhouse_storage_lights_pir_clear_after_doors_closed
alias: Underhouse Storage Lights - PIR Clear After Doors Closed
description: >-
If the doors are closed and PIR occupancy clears for 60 seconds, turn the
storage lights off.
mode: restart
trigger:
- platform: state
entity_id: binary_sensor.underhouse_storage_pir_presence
to: "off"
for: "00:01:00"
condition:
- condition: state
entity_id: binary_sensor.underhouse_storage_door_contacts
state: "off"
- condition: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
state: "on"
action:
- action: script.underhouse_storage_lights_stop_runtime
- id: underhouse_storage_lights_startup_sync
alias: Underhouse Storage Lights - Startup Sync
description: >-
On Home Assistant startup, re-sync the package state so an already-open
door or already-active PIR still controls the lights after a restart.
mode: single
trigger:
- platform: homeassistant
event: start
action:
- delay: "00:00:20"
- choose:
- conditions:
- condition: template
value_template: >-
{{
is_state('binary_sensor.underhouse_storage_door_contacts', 'on')
or is_state('binary_sensor.underhouse_storage_pir_presence', 'on')
or is_state('binary_sensor.esp_underhouselights_underhouse_storage_lights_remote_switch', 'on')
}}
sequence:
- action: script.underhouse_storage_lights_start_runtime
- conditions:
- condition: state
entity_id: switch.esp_underhouselights_underhouse_storage_lights
state: "on"
- condition: state
entity_id: timer.underhouse_storage_lights_runtime
state: "idle"
sequence:
- action: timer.start
target:
entity_id: timer.underhouse_storage_lights_runtime
data:
duration: "00:20:00"
+40 -18
View File
@@ -1,20 +1,26 @@
###############################################################################
# Bedroom 1 Ikea Air Filter Package
# File: /config/packages/bedroom_1_ikea_air_filter.yaml
# Version: 1.0
# Date: 2026-04-29
# Version: 1.1
# Date: 2026-05-08
#
# Purpose:
# - Creates a dropdown helper called "Bedroom 1 Ikea Fan".
# - Auto mode controls the Bedroom 1 Ikea air filter speed by priority.
# - Auto mode controls the Bedroom 1 Ikea air filter speed by event and timing.
# - Manual dropdown modes set a fixed fan speed and disable auto control.
#
# Auto priority order:
# 1. Quiet time on: fan speed 2
# 2. Bedside light on: fan speed 2
# 3. Free power time, 21:00 to midnight: fan speed 5
# 4. Daytime, 09:00 to 15:00: fan speed 4
# 5. Default: fan speed 2
# Behaviour notes:
# - Quiet time turning on sets fan speed to 2.
# - Bedside lamp turning on sets fan speed to 2.
# - Bedside lamp turning off does not change the fan speed.
# - There is no 10-minute re-check, so the fan will not ramp back up just
# because the bedside lamp was switched off.
# - Time boundaries can still change the fan speed later.
#
# Auto timing:
# - 21:00 to midnight: fan speed 5
# - 09:00 to 15:00: fan speed 4
# - Default: fan speed 2
###############################################################################
input_select:
@@ -68,13 +74,17 @@ automation:
- trigger: homeassistant
event: start
# Highest priority condition.
# Quiet time only forces low when it turns on.
# Turning quiet time off does not automatically ramp the fan back up.
- trigger: state
entity_id: input_boolean.quiet_time
to: "on"
# Bedside lamp should force low speed while on.
# Bedside lamp only forces low when it turns on.
# Turning the lamp off does not change the fan speed.
- trigger: state
entity_id: light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb
to: "on"
# Main timing boundaries.
- trigger: time
@@ -84,10 +94,6 @@ automation:
- "15:00:00"
- "21:00:00"
# Safety/re-check trigger, especially for the bedside lamp rule.
- trigger: time_pattern
minutes: "/10"
conditions:
# Manual dropdown modes disable automatic control.
- condition: state
@@ -96,10 +102,26 @@ automation:
actions:
- variables:
trigger_entity: "{{ trigger.entity_id | default('') }}"
bedside_lamp_entity: light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb
bedside_lamp_on_trigger: >-
{{
trigger_entity == bedside_lamp_entity
and trigger.to_state is defined
and trigger.to_state.state == 'on'
}}
quiet_time_on_trigger: >-
{{
trigger_entity == 'input_boolean.quiet_time'
and trigger.to_state is defined
and trigger.to_state.state == 'on'
}}
auto_target_speed: >-
{% if is_state('input_boolean.quiet_time', 'on') %}
{% if bedside_lamp_on_trigger %}
2
{% elif is_state('light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb', 'on') %}
{% elif quiet_time_on_trigger %}
2
{% elif is_state('input_boolean.quiet_time', 'on') %}
2
{% elif now().hour >= 21 %}
5
@@ -142,7 +164,7 @@ automation:
entity_id: automation.bedroom_1_ikea_air_filter_auto_control
# Auto starts at speed 2, then immediately evaluates the
# current priority rules.
# current timing rules.
- action: script.bedroom_1_ikea_air_filter_set_speed_if_needed
data:
target_speed: 2
+37 -8
View File
@@ -3,6 +3,9 @@
###############################################################################
#
# VERSION:
# 1.4 - 2026-05-21
# - Added delayed lounge NSPanel touchscreen brightness reduction to 5.
#
# 1.3 - 2026-05-07
# - Added downstairs lights all off script.
# - Added main hallway nightlights 60 minute bedtime timer.
@@ -29,6 +32,7 @@
# - climate entities are turned off if they are not already "off".
# - Main hallway nightlights are turned on for 60 minutes when bedtime mode runs.
# - If the main hallway nightlights are turned off manually, the timer is cancelled.
# - Lounge NSPanel touchscreen brightness is set to 5 after 20 seconds.
#
###############################################################################
@@ -94,6 +98,18 @@ automation:
delay_seconds: 0
action:
# Turn hallway nightlights on immediately before any other bedtime actions.
- service: switch.turn_on
target:
entity_id: switch.main_hallway_nightlights_1_relay_1_main_hallway_nightlights
# Start or restart the 60 minute bedtime nightlight timer.
- service: timer.start
target:
entity_id: timer.main_hallway_nightlights_bedtime
data:
duration: "01:00:00"
- service: script.downstairs_lights_all_off
- service: script.lounge_set_scene
@@ -104,15 +120,10 @@ automation:
target:
entity_id: input_boolean.quiet_time
- service: switch.turn_on
# Reduce the lounge NSPanel screen brightness after 20 seconds.
- service: script.turn_on
target:
entity_id: switch.main_hallway_nightlights_1_relay_1_main_hallway_nightlights
- service: timer.start
target:
entity_id: timer.main_hallway_nightlights_bedtime
data:
duration: "01:00:00"
entity_id: script.bedtime_mode_set_lounge_nspanel_brightness_after_delay
- repeat:
for_each: "{{ bedtime_delayed_off_targets }}"
@@ -232,3 +243,21 @@ script:
mode: parallel
max: 50
bedtime_mode_set_lounge_nspanel_brightness_after_delay:
alias: "Bedtime Mode - Set Lounge NSPanel Brightness After Delay"
description: >
Waits 20 seconds after bedtime mode starts, then sets the lounge NSPanel
touchscreen display brightness to 5.
sequence:
- delay:
seconds: 20
- service: number.set_value
target:
entity_id: number.lounge_nspanel_touchscreen_display_brightness
data:
value: 1
mode: restart
-24
View File
@@ -1,24 +0,0 @@
mqtt:
switch:
- unique_id: lounge_blinds_control
name: "Lounge Blinds Control"
state_topic: "viewroad-status/blinds/lounge-verticalblinds"
command_topic: "viewroad-commands/blinds/lounge-verticalblinds"
payload_off: "off"
payload_on: "on"
state_on: "on"
state_off: "off"
icon: mdi:blinds
retain: false
automation:
- id: lounge_blinds_control_switch
alias: Publish lounge blind control to mqtt
trigger:
platform: state
entity_id: input_boolean.lounge_blinds
action:
service: mqtt.publish
data_template:
payload: "{{trigger.to_state.state}}"
topic: viewroad-status/blinds/lounge-verticalblinds
+35 -12
View File
@@ -4,6 +4,12 @@
#
# VERSION HISTORY
#
# 2026-05-07 - v1.0.2
# - Added binary_sensor.downstairs_flat_any_lights_on.
# - Updated all-on/all-off script to use the new binary sensor.
# - Kept direct entity lists instead of using a Home Assistant group, to avoid
# package merge errors from duplicate group/name keys.
#
# 2026-05-07 - v1.0.1
# - Removed group.downstairs_flat_lights from this package to avoid duplicate
# group/name package merge errors.
@@ -30,6 +36,11 @@
# - downstairs_light_toggle_all_group turns all listed lights OFF if any are ON.
# - downstairs_light_toggle_all_group turns all listed lights ON if they are all OFF.
#
# - binary_sensor.downstairs_flat_any_lights_on:
# - ON when any listed downstairs light is ON.
# - OFF when all listed downstairs lights are OFF.
# - This replaces the need for a group.downstairs_flat_lights entity.
#
###############################################################################
###############################################################################
@@ -41,6 +52,27 @@ input_boolean:
name: Downstairs Guest Occupied
icon: mdi:home-account
###############################################################################
# TEMPLATE SENSORS
###############################################################################
template:
- binary_sensor:
- name: Downstairs Flat Any Lights On
unique_id: downstairs_flat_any_lights_on
icon: mdi:lightbulb-group
state: >
{{
is_state('switch.esp_downstloungemain_relay_1_main_lights', 'on')
or is_state('switch.esp_downstloungemain_relay_2_back_wall_lights', 'on')
or is_state('switch.esp_downstmasterbedrmlights_relay_1_main_lights', 'on')
or is_state('switch.esp_downstbedrm2lights_relay_1_main_lights', 'on')
or is_state('switch.esp_downstkitchlights_relay_2_kitchen_light', 'on')
or is_state('switch.esp_downstkitchlights_relay_1_dining_light', 'on')
or is_state('switch.esp_downstbathswitch_relay_1_main_lights', 'on')
or is_state('switch.esp_downstbathswitch_relay_2_cabinet_light', 'on')
}}
###############################################################################
# SCRIPTS
###############################################################################
@@ -169,18 +201,9 @@ script:
- choose:
- conditions:
- condition: template
value_template: >
{{
is_state('switch.esp_downstloungemain_relay_1_main_lights', 'on')
or is_state('switch.esp_downstloungemain_relay_2_back_wall_lights', 'on')
or is_state('switch.esp_downstmasterbedrmlights_relay_1_main_lights', 'on')
or is_state('switch.esp_downstbedrm2lights_relay_1_main_lights', 'on')
or is_state('switch.esp_downstkitchlights_relay_2_kitchen_light', 'on')
or is_state('switch.esp_downstkitchlights_relay_1_dining_light', 'on')
or is_state('switch.esp_downstbathswitch_relay_1_main_lights', 'on')
or is_state('switch.esp_downstbathswitch_relay_2_cabinet_light', 'on')
}}
- condition: state
entity_id: binary_sensor.downstairs_flat_any_lights_on
state: "on"
sequence:
- action: homeassistant.turn_off
target:
-35
View File
@@ -1,35 +0,0 @@
mqtt:
sensor:
- unique_id: view_road_power_now
name: "Power Now"
state_topic: "viewroad-status/energy/PowerTotals"
unit_of_measurement: "kW"
- unique_id: view_road_power_now_red
name: "Power Now (Red)"
state_topic: "tele/tasmo-wemosd1-7280-powermon-1/SENSOR"
unit_of_measurement: "kW"
value_template: "{{ value_json.ENERGY.Power[0] }}"
- unique_id: view_road_power_now_white
name: "Power Now (White)"
state_topic: "tele/tasmo-wemosd1-7280-powermon-1/SENSOR"
unit_of_measurement: "kW"
value_template: "{{ value_json.ENERGY.Power[1] }}"
- unique_id: view_road_power_now_blue
name: "Power Now (Blue)"
state_topic: "tele/tasmo-wemosd1-7280-powermon-1/SENSOR"
unit_of_measurement: "kW"
value_template: "{{ value_json.ENERGY.Power[2] }}"
template:
- sensor:
- name: "Electricity Power Total"
unique_id: electricity_power_total
unit_of_measurement: "W"
device_class: power
state_class: measurement
state: >
{{
states('sensor.tasmo_wemosd1_7280_powermon_1_energy_power_0') | float(0)
+ states('sensor.tasmo_wemosd1_7280_powermon_1_energy_power_1') | float(0)
+ states('sensor.tasmo_wemosd1_7280_powermon_1_energy_power_2') | float(0)
}}
-105
View File
@@ -1,105 +0,0 @@
#mqtt:
# sensor:
# - unique_id: 32a_ev_wallcharger_power
# name: "32A EV Wallcharger Power"
# device_class: power
# unit_of_measurement: kW
# state_topic: "stat/tasmo-wemosd1-7280-powermon-1/EnergyMeterCount"
# value_template: "{{ value_json.EVChargerWhCount * 2 * 60 / 1000 }}"
# - unique_id: 16a_ev_wallcharger_power
# name: "16A EV Wallcharger Power"
# device_class: power
# unit_of_measurement: kW
# state_topic: "stat/tasmo-s4chan-7594-garage-1/EnergyMeterCount"
# value_template: "{{ value_json.EVChargerWhCount * 2 * 60 / 1000 }}"
# Use the Riemann sum integral to calculate energy in kWh
# from the contimuous power measuring sensors
sensor:
- platform: integration
unique_id: 32a_ev_wallcharger_power_total
name: "EV 32A Wallcharger Power Total (Integral)"
source: sensor.main_house_3_phase_power_monitor_32a_wallcharger_power
#device_class: energy
#unit_of_measurement: Wh
#unit_time: h
#unit_prefix: k # Show in kWh
round: 0 # Only need 0 decimals accuracy
- platform: integration
unique_id: 16a_ev_wallcharger_power_total
name: "EV 16A EV Wallcharger Power Total (Integral)"
source: sensor.garage_db_control_16a_wallcharger_power
#device_class: energy
#unit_of_measurement: Wh
#unit_time: h
#unit_prefix: k
round: 0
# - platform: filter
# name: "32A EV Charger Power 1m Avg"
# unique_id: ev_charger_32a_power_1m_avg
# entity_id: sensor.main_house_3_phase_power_monitor_ev_wallcharger_power
# filters:
# - filter: time_simple_moving_average
# window_size: "00:01"
# precision: 3
input_select:
leaf_ev_charging_mode:
icon: mdi:ev-plug-type1
name: Leaf EV Charge Mode
initial: "Normal (Offpeak)"
options:
- "Normal (Offpeak)"
- "Offpeak until charged"
- "1hr top-up now"
- "Charge now until full"
- "Stop charging now"
automation:
- id: set_the_leaf_ev_charging_mode
alias: Set the Leaf EV Charging Mode
trigger:
entity_id: input_select.leaf_ev_charging_mode
platform: state
action:
service: mqtt.publish
data:
topic: viewroad-status/evcharging/leaf-chargemode
payload:
'{% set mapping = { "Normal (Offpeak)":"normal", "Offpeak until charged":"offpeak-full",
"1hr top-up now":"boost", "Charge now until full":"now-full", "Stop charging now":"stop" } %} {% set dta = trigger.to_state.state %}
{{ mapping[dta] }}
'
#template:
# - trigger:
# - platform: time_pattern
# seconds: "/10"
# - platform: homeassistant
# event: start
# binary_sensor:
# - name: "32A EV Charger Charging"
# unique_id: ev_charger_32a_charging
# icon: mdi:car-electric
# state: >-
# {{ states('sensor.32a_ev_charger_power_1m_avg') | float(0) > 0.1 }}
# delay_on:
# seconds: 60
# delay_off:
# seconds: 60
#
# - name: "16A EV Charger Charging"
# unique_id: ev_charger_16a_charging
# icon: mdi:car-electric
# state: >-
# {{ (states('sensor.16a_ev_wallcharger_power') | float(0)) > 0.1 }}
# delay_on:
# seconds: 60
# delay_off:
# seconds: 60
#
# - binary_sensor:
# - name: 32A EV Charger Charging UI
# unique_id: ev_charger_charging_ui
# state: "{{ is_state('sensor.32a_ev_charger_charging', 'on') }}"
# icon: mdi:car-electric
+299
View File
@@ -0,0 +1,299 @@
###############################################################################
# PACKAGE: Free Power Time Automation
###############################################################################
# VERSION:
# 1.0.0 - 2026-05-08
# - Initial package.
# - Adds editable free power start/end times.
# - Adds master enable switch and per-action enable switches.
# - Adds announcement, gas-to-heatpump changeover, tool charger control,
# and underhouse dehumidifier control.
#
# NOTES:
# - Free power start/end times can be changed in Home Assistant.
# - Start time default is 9:00pm.
# - End time default is midnight.
# - YAML-only gas heater settings are in script.free_power_gas_heater_changeover:
# gas_heater_shutdown_delay_seconds
# heatpump_setpoint_offset_c
#
# IMPORTANT:
# - input_datetime initial values are used to provide defaults.
# - If you later want UI changes to survive every HA restart, remove the
# initial lines after the helpers have been created and set once.
###############################################################################
###############################################################################
# INPUT DATETIME
###############################################################################
input_datetime:
free_power_start_time:
name: Free Power - Start Time
has_date: false
has_time: true
initial: "21:00:00"
icon: mdi:clock-start
free_power_end_time:
name: Free Power - End Time
has_date: false
has_time: true
initial: "00:00:00"
icon: mdi:clock-end
###############################################################################
# ENABLE SWITCHES
###############################################################################
input_boolean:
free_power_automation_enabled:
name: Free Power - Master Automation Enable
icon: mdi:transmission-tower
free_power_announcement_enabled:
name: Free Power - Announcement Enable
icon: mdi:bullhorn
free_power_gas_heater_changeover_enabled:
name: Free Power - Gas Heater Changeover Enable
icon: mdi:heat-pump-outline
free_power_tool_battery_chargers_enabled:
name: Free Power - Tool Battery Chargers Enable
icon: mdi:battery-charging
free_power_underhouse_dehumidifier_enabled:
name: Free Power - Underhouse Dehumidifier Enable
icon: mdi:air-humidifier
###############################################################################
# TEMPLATE SENSORS
###############################################################################
template:
- binary_sensor:
- name: Free Power Time Active
unique_id: free_power_time_active
icon: mdi:transmission-tower
state: >-
{% set start = states('input_datetime.free_power_start_time') %}
{% set end = states('input_datetime.free_power_end_time') %}
{% set now_mins = now().hour * 60 + now().minute %}
{% set start_mins = (start[0:2] | int(0)) * 60 + (start[3:5] | int(0)) %}
{% set end_mins = (end[0:2] | int(0)) * 60 + (end[3:5] | int(0)) %}
{% if start_mins == end_mins %}
false
{% elif start_mins < end_mins %}
{{ start_mins <= now_mins < end_mins }}
{% else %}
{{ now_mins >= start_mins or now_mins < end_mins }}
{% endif %}
###############################################################################
# SCRIPTS
###############################################################################
script:
free_power_start_actions:
alias: Free Power - Start Actions
mode: single
sequence:
- condition: state
entity_id: input_boolean.free_power_automation_enabled
state: "on"
- variables:
free_power_time_label: >-
{%- set raw_time = states('input_datetime.free_power_start_time') -%}
{%- set hour = raw_time[0:2] | int(0) -%}
{%- set minute = raw_time[3:5] | int(0) -%}
{%- set suffix = 'am' if hour < 12 else 'pm' -%}
{%- set hour12 = hour % 12 -%}
{%- set hour12 = 12 if hour12 == 0 else hour12 -%}
{{- hour12 ~ suffix if minute == 0 else hour12 ~ ':' ~ '%02d' | format(minute) ~ suffix -}}
###########################################################################
# 1) Free Power Time Announcement
###########################################################################
- if:
- condition: state
entity_id: input_boolean.free_power_announcement_enabled
state: "on"
then:
- action: script.view_road_announcement
data:
channels: "lounge_google_home_voice, sony_tv_lounge"
title: "View Road "
short_announcement: "{{ free_power_time_label }}: Free power time"
long_announcement: "It is {{ free_power_time_label }}."
###########################################################################
# 2) Gas Heater Changeover
###########################################################################
- if:
- condition: state
entity_id: input_boolean.free_power_gas_heater_changeover_enabled
state: "on"
then:
- action: script.free_power_gas_heater_changeover
###########################################################################
# 3) Tool Battery Chargers On
###########################################################################
- if:
- condition: state
entity_id: input_boolean.free_power_tool_battery_chargers_enabled
state: "on"
then:
- action: switch.turn_on
target:
entity_id:
- switch.ryobi_charger_left_power_monitor_x17pp
- switch.ryobi_charger_right_power_monitor_x16pp
###########################################################################
# 4) Underhouse Dehumidifier On
###########################################################################
- if:
- condition: state
entity_id: input_boolean.free_power_underhouse_dehumidifier_enabled
state: "on"
then:
- action: switch.turn_on
target:
entity_id:
- switch.underhouse_dehumidifier_power_plug_x10pp
free_power_end_actions:
alias: Free Power - End Actions
mode: single
sequence:
- condition: state
entity_id: input_boolean.free_power_automation_enabled
state: "on"
###########################################################################
# 3) Tool Battery Chargers Off
#
# If this action is enabled, the chargers are switched off at free power
# end even if something else turned them on.
###########################################################################
- if:
- condition: state
entity_id: input_boolean.free_power_tool_battery_chargers_enabled
state: "on"
then:
- action: switch.turn_off
target:
entity_id:
- switch.ryobi_charger_left_power_monitor_x17pp
- switch.ryobi_charger_right_power_monitor_x16pp
###########################################################################
# 4) Underhouse Dehumidifier Off
#
# If this action is enabled, the dehumidifier is switched off at free power
# end even if something else turned it on.
###########################################################################
- if:
- condition: state
entity_id: input_boolean.free_power_underhouse_dehumidifier_enabled
state: "on"
then:
- action: switch.turn_off
target:
entity_id:
- switch.underhouse_dehumidifier_power_plug_x10pp
free_power_gas_heater_changeover:
alias: Free Power - Gas Heater Changeover
mode: single
sequence:
###########################################################################
# YAML-only settings
###########################################################################
- variables:
gas_heater_operation_entity: switch.rinnai_neo_gas_heater_heater_operation
gas_heater_setpoint_entity: number.rinnai_neo_gas_heater_rinnai_neo_gas_heater_setpoint
heatpump_climate_entity: climate.lounge
gas_heater_shutdown_delay_seconds: 60
heatpump_setpoint_offset_c: 0
heatpump_setpoint: >-
{{
(
(states(gas_heater_setpoint_entity) | float(0))
+ (heatpump_setpoint_offset_c | float(0))
) | round(1)
}}
###########################################################################
# Only change over if the gas heater is currently on.
###########################################################################
- condition: template
value_template: "{{ is_state(gas_heater_operation_entity, 'on') }}"
###########################################################################
# Only continue if the gas setpoint can be read.
###########################################################################
- condition: template
value_template: >-
{{ states(gas_heater_setpoint_entity) not in ['unknown', 'unavailable', 'none', 'None', ''] }}
###########################################################################
# Set the Panasonic heatpump to heat mode and match the gas heater setpoint,
# with the YAML-only offset applied.
###########################################################################
- action: climate.set_temperature
target:
entity_id: climate.lounge
data:
hvac_mode: heat
temperature: "{{ heatpump_setpoint }}"
###########################################################################
# Give the heatpump time to start before turning the gas heater off.
###########################################################################
- delay:
seconds: "{{ gas_heater_shutdown_delay_seconds | int(60) }}"
- action: switch.turn_off
target:
entity_id: switch.rinnai_neo_gas_heater_heater_operation
###############################################################################
# AUTOMATIONS
###############################################################################
automation:
- id: free_power_time_start_actions
alias: Free Power Time - Start Actions
mode: single
triggers:
- trigger: time
at: input_datetime.free_power_start_time
actions:
- action: script.free_power_start_actions
- id: free_power_time_end_actions
alias: Free Power Time - End Actions
mode: single
triggers:
- trigger: time
at: input_datetime.free_power_end_time
actions:
- action: script.free_power_end_actions
@@ -1,19 +0,0 @@
mqtt:
sensor:
- unique_id: gas_heater_operating
name: "Gas Heater Operating"
state_topic: "viewroad-status/gasheater/operating"
switch:
- unique_id: gasheater_switch
name: "Gas Heater"
state_topic: "viewroad-status/gasheater/operating"
command_topic: "viewroad-commands/gasheater/onoff"
#availability:
# - topic: "home/bedroom/switch1/available"
payload_on: "ON"
payload_off: "OFF"
state_on: "ON"
state_off: "OFF"
optimistic: false
qos: 0
retain: true # need this, or fire starts on HA reboot. Could fix in Node red too.
+368
View File
@@ -0,0 +1,368 @@
###############################################################################
# PACKAGE: Lounge Blinds - Sunrise / Sunset Automation
###############################################################################
#
# VERSION:
# v1.2 - 2026-05-08
# - Updated input_boolean.lounge_blinds control logic.
# - input_boolean.lounge_blinds ON now closes the blinds.
# - input_boolean.lounge_blinds OFF now opens the blinds.
# - Removed the sync guard helper.
# - Added state checks so cover feedback does not create command loops.
#
# v1.1 - 2026-05-08
# - Added input_boolean.lounge_blinds as a manual control/status helper.
# - Added cover state sync back to input_boolean.lounge_blinds.
#
# v1.0 - 2026-05-08
# - Initial package.
# - Opens lounge blinds at sunrise.
# - Closes lounge blinds at sunset.
# - Includes sunrise/sunset minute offsets.
# - Includes repeated command attempts for Zigbee reliability.
# - Opens blinds in list order: A, B, C.
# - Closes blinds in reverse list order: C, B, A.
#
# NOTES:
# - input_boolean.lounge_blinds is treated as:
# ON = blinds closed
# OFF = blinds open
#
# - Turning input_boolean.lounge_blinds ON will close the blinds.
# - Turning input_boolean.lounge_blinds OFF will open the blinds.
# - If all blinds are closed by another method, the boolean will turn ON.
# - If all blinds are opened by another method, the boolean will turn OFF.
# - If blinds are in a mixed/partial state, the boolean is left unchanged.
#
# - The blind entity list is inside:
# script.lounge_blinds_run_sequence
# script.lounge_blinds_sync_status
# automation.lounge_blinds_control_from_input_boolean
#
# - If you add more blinds, update the blind list in those three places.
#
###############################################################################
input_boolean:
lounge_blinds:
name: Lounge Blinds Closed
icon: mdi:blinds
input_number:
lounge_blinds_sunrise_offset_minutes:
name: Lounge Blinds Sunrise Offset
icon: mdi:weather-sunset-up
min: -180
max: 180
step: 1
mode: box
unit_of_measurement: min
initial: 0
lounge_blinds_sunset_offset_minutes:
name: Lounge Blinds Sunset Offset
icon: mdi:weather-sunset-down
min: -180
max: 180
step: 1
mode: box
unit_of_measurement: min
initial: 0
lounge_blinds_per_blind_delay_seconds:
name: Lounge Blinds Per-Blind Delay
icon: mdi:timer-outline
min: 0
max: 60
step: 1
mode: box
unit_of_measurement: sec
initial: 2
lounge_blinds_command_repeats:
name: Lounge Blinds Command Repeats
icon: mdi:repeat
min: 1
max: 5
step: 1
mode: box
initial: 2
lounge_blinds_retry_delay_seconds:
name: Lounge Blinds Retry Delay
icon: mdi:timer-refresh-outline
min: 0
max: 120
step: 1
mode: box
unit_of_measurement: sec
initial: 10
input_datetime:
lounge_blinds_next_open_time:
name: Lounge Blinds Next Open Time
has_date: true
has_time: true
lounge_blinds_next_close_time:
name: Lounge Blinds Next Close Time
has_date: true
has_time: true
script:
lounge_blinds_update_sun_times:
alias: Lounge Blinds - Update Sun Times
mode: single
sequence:
- variables:
sunrise_offset_seconds: >
{{ states('input_number.lounge_blinds_sunrise_offset_minutes') | int(0) * 60 }}
sunset_offset_seconds: >
{{ states('input_number.lounge_blinds_sunset_offset_minutes') | int(0) * 60 }}
next_sunrise_timestamp: >
{{ as_timestamp(state_attr('sun.sun', 'next_rising')) + sunrise_offset_seconds }}
next_sunset_timestamp: >
{{ as_timestamp(state_attr('sun.sun', 'next_setting')) + sunset_offset_seconds }}
- action: input_datetime.set_datetime
target:
entity_id: input_datetime.lounge_blinds_next_open_time
data:
datetime: >
{{ next_sunrise_timestamp | timestamp_custom('%Y-%m-%d %H:%M:%S', true) }}
- action: input_datetime.set_datetime
target:
entity_id: input_datetime.lounge_blinds_next_close_time
data:
datetime: >
{{ next_sunset_timestamp | timestamp_custom('%Y-%m-%d %H:%M:%S', true) }}
lounge_blinds_run_sequence:
alias: Lounge Blinds - Run Open/Close Sequence
mode: queued
fields:
blind_action:
name: Blind Action
description: Use open or close.
required: true
selector:
select:
options:
- open
- close
sequence:
- variables:
blind_list:
- cover.lounge_blind_a_xbl11
- cover.lounge_blind_b_xbl12
- cover.lounge_blind_c_xbl13
command_repeats: >
{{ states('input_number.lounge_blinds_command_repeats') | int(2) }}
retry_delay_seconds: >
{{ states('input_number.lounge_blinds_retry_delay_seconds') | int(10) }}
per_blind_delay_seconds: >
{{ states('input_number.lounge_blinds_per_blind_delay_seconds') | int(2) }}
- repeat:
count: "{{ command_repeats }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ blind_action == 'open' }}"
sequence:
- repeat:
for_each: "{{ blind_list }}"
sequence:
- action: cover.open_cover
target:
entity_id: "{{ repeat.item }}"
- delay:
seconds: "{{ per_blind_delay_seconds }}"
- conditions:
- condition: template
value_template: "{{ blind_action == 'close' }}"
sequence:
- repeat:
for_each: "{{ blind_list | reverse | list }}"
sequence:
- action: cover.close_cover
target:
entity_id: "{{ repeat.item }}"
- delay:
seconds: "{{ per_blind_delay_seconds }}"
- if:
- condition: template
value_template: "{{ repeat.index < command_repeats }}"
then:
- delay:
seconds: "{{ retry_delay_seconds }}"
- action: script.lounge_blinds_sync_status
lounge_blinds_sync_status:
alias: Lounge Blinds - Sync Status
mode: queued
sequence:
- variables:
blind_list:
- cover.lounge_blind_a_xbl11
- cover.lounge_blind_b_xbl12
- cover.lounge_blind_c_xbl13
blind_states: >
{{ expand(blind_list) | map(attribute='state') | list }}
all_blinds_closed: >
{{ blind_states | select('eq', 'closed') | list | count == blind_list | count }}
all_blinds_open: >
{{ blind_states | select('eq', 'open') | list | count == blind_list | count }}
- choose:
- conditions:
- condition: template
value_template: >
{{ all_blinds_closed and is_state('input_boolean.lounge_blinds', 'off') }}
sequence:
- action: input_boolean.turn_on
target:
entity_id: input_boolean.lounge_blinds
- conditions:
- condition: template
value_template: >
{{ all_blinds_open and is_state('input_boolean.lounge_blinds', 'on') }}
sequence:
- action: input_boolean.turn_off
target:
entity_id: input_boolean.lounge_blinds
automation:
- id: lounge_blinds_update_sun_times
alias: Lounge Blinds - Update Sun Times
mode: restart
trigger:
- platform: homeassistant
event: start
- platform: time
at: "00:05:00"
- platform: state
entity_id:
- input_number.lounge_blinds_sunrise_offset_minutes
- input_number.lounge_blinds_sunset_offset_minutes
action:
- action: script.lounge_blinds_update_sun_times
- id: lounge_blinds_open_at_sunrise
alias: Lounge Blinds - Open At Sunrise
mode: single
trigger:
- platform: time
at: input_datetime.lounge_blinds_next_open_time
action:
- action: script.lounge_blinds_run_sequence
data:
blind_action: open
- id: lounge_blinds_close_at_sunset
alias: Lounge Blinds - Close At Sunset
mode: single
trigger:
- platform: time
at: input_datetime.lounge_blinds_next_close_time
action:
- action: script.lounge_blinds_run_sequence
data:
blind_action: close
- id: lounge_blinds_control_from_input_boolean
alias: Lounge Blinds - Control From Input Boolean
mode: restart
trigger:
- platform: state
entity_id: input_boolean.lounge_blinds
to: "on"
- platform: state
entity_id: input_boolean.lounge_blinds
to: "off"
action:
- variables:
blind_list:
- cover.lounge_blind_a_xbl11
- cover.lounge_blind_b_xbl12
- cover.lounge_blind_c_xbl13
blind_states: >
{{ expand(blind_list) | map(attribute='state') | list }}
all_blinds_closed: >
{{ blind_states | select('eq', 'closed') | list | count == blind_list | count }}
all_blinds_open: >
{{ blind_states | select('eq', 'open') | list | count == blind_list | count }}
- choose:
- conditions:
- condition: state
entity_id: input_boolean.lounge_blinds
state: "on"
- condition: template
value_template: "{{ not all_blinds_closed }}"
sequence:
- action: script.lounge_blinds_run_sequence
data:
blind_action: close
- conditions:
- condition: state
entity_id: input_boolean.lounge_blinds
state: "off"
- condition: template
value_template: "{{ not all_blinds_open }}"
sequence:
- action: script.lounge_blinds_run_sequence
data:
blind_action: open
- id: lounge_blinds_sync_input_boolean_from_cover_states
alias: Lounge Blinds - Sync Input Boolean From Cover States
mode: restart
trigger:
- platform: homeassistant
event: start
- platform: state
entity_id:
- cover.lounge_blind_a_xbl11
- cover.lounge_blind_b_xbl12
- cover.lounge_blind_c_xbl13
to: "open"
- platform: state
entity_id:
- cover.lounge_blind_a_xbl11
- cover.lounge_blind_b_xbl12
- cover.lounge_blind_c_xbl13
to: "closed"
action:
- action: script.lounge_blinds_sync_status
+57 -9
View File
@@ -46,8 +46,10 @@ input_select:
- "Select Scene:"
- Bright
- TV General
- Balanced
- Movie
- Reading On/Off
- Dining On/Off
- Night Light
- Warm Cozy
- All Off
@@ -106,6 +108,7 @@ script:
excluded_scenes:
- "Select Scene:"
- "Reading On/Off"
- "Dining On/Off"
#- "Night Light"
#####################################################################
@@ -120,18 +123,20 @@ script:
light.esp_lounge6chdimmer_lounge_downlights_centre: 100
light.esp_lounge6chdimmer_lounge_downlights_south: 100
light.esp_lounge6chdimmer_lounge_rafter_buttons: 100
switch.esp_loungemiddleswitch_relay_3_downlights_north: "on"
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "on"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "on" # non dimmable pair
light.esp_breakfastbarleds_breakfast_bar_leds: 90
light.esp_loungecabinetleds2_lounge_cabinet_leds: 90
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 90
switch.lounge_cupboard_dual_usb_xus09_l2: "on"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "on"
switch.esp_loungesouthrightswitch_relay_2_wall_washer_right: "on"
switch.tasmo_ks811t_0702_lounge_3c: "on"
#switch.tasmo_ks811t_0702_lounge_3c: "on"
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 100
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 100
input_number.openhasp_1_backlight_level: 255
number.lounge_nspanel_touchscreen_display_brightness: 100
TV General:
light.esp_lounge6chdimmer_couch_spots_left: 60
@@ -143,7 +148,8 @@ script:
light.esp_breakfastbarleds_breakfast_bar_leds: 60
light.esp_loungecabinetleds2_lounge_cabinet_leds: 60
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 60
switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" # non-dimmable pair
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" # non-dimmable pair
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
switch.lounge_cupboard_dual_usb_xus09_l2: "on"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "off"
switch.esp_loungesouthrightswitch_relay_2_wall_washer_right: "off"
@@ -151,6 +157,28 @@ script:
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 60
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 60
input_number.openhasp_1_backlight_level: 120
number.lounge_nspanel_touchscreen_display_brightness: 80
Balanced:
light.esp_lounge6chdimmer_couch_spots_left: 40
light.esp_lounge6chdimmer_couch_spots_right: 40
#light.esp_lounge6chdimmer_dining_table_light: 100
light.esp_lounge6chdimmer_lounge_downlights_centre: 40
light.esp_lounge6chdimmer_lounge_downlights_south: 40
light.esp_lounge6chdimmer_lounge_rafter_buttons: 30
light.esp_breakfastbarleds_breakfast_bar_leds: 50
light.esp_loungecabinetleds2_lounge_cabinet_leds: 50
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 50
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off" # non-dimmable pair
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
switch.lounge_cupboard_dual_usb_xus09_l2: "on"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "off"
switch.esp_loungesouthrightswitch_relay_2_wall_washer_right: "off"
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 50
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 50
input_number.openhasp_1_backlight_level: 100
number.lounge_nspanel_touchscreen_display_brightness: 80
Movie:
light.esp_lounge6chdimmer_couch_spots_left: 20
@@ -162,7 +190,8 @@ script:
light.esp_breakfastbarleds_breakfast_bar_leds: 40
light.esp_loungecabinetleds2_lounge_cabinet_leds: 40
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 40
switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
switch.lounge_cupboard_dual_usb_xus09_l2: "on"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "off"
switch.esp_loungesouthrightswitch_relay_2_wall_washer_right: "off"
@@ -170,6 +199,17 @@ script:
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 40
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 40
input_number.openhasp_1_backlight_level: 15
switch.esp_mainkitchenlights_relay_1_main_lights: "off"
switch.esp_mainkitchenlights_relay_2_benchtop_lights: "off"
number.lounge_nspanel_touchscreen_display_brightness: 40
Dining On/Off:
light.esp_lounge6chdimmer_dining_table_light: "toggle_100"
#light.esp_lounge6chdimmer_dining_table_light: 60
#light.esp_lounge6chdimmer_lounge_downlights_centre: 45
#light.esp_lounge6chdimmer_lounge_downlights_south: 35
#light.esp_lounge6chdimmer_lounge_rafter_buttons: 20
#switch.tasmo_ks811t_0702_lounge_3c: "on"
Reading On/Off:
light.esp_lounge6chdimmer_couch_spots_left: "toggle_75"
@@ -190,14 +230,16 @@ script:
light.esp_breakfastbarleds_breakfast_bar_leds: 5
light.esp_loungecabinetleds2_lounge_cabinet_leds: 5
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 5
switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
switch.lounge_cupboard_dual_usb_xus09_l2: "off"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "off"
switch.esp_loungesouthrightswitch_relay_2_wall_washer_right: "off"
#switch.esp_loungenorthswitch_relay_1_main_lights: "on"
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 5
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 5
input_number.openhasp_1_backlight_level: 8
input_number.openhasp_1_backlight_level: 10
number.lounge_nspanel_touchscreen_display_brightness: 30
Warm Cozy:
light.esp_lounge6chdimmer_couch_spots_left: 20
@@ -206,8 +248,9 @@ script:
light.esp_breakfastbarleds_breakfast_bar_leds: 25
light.esp_loungecabinetleds2_lounge_cabinet_leds: 30
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 30
light.tasmo_h801_loungeled1_6180_a: 25
light.tasmo_h801_loungeled1_6180_b: 25
#light.tasmo_h801_loungeled1_6180_a: 25
#light.tasmo_h801_loungeled1_6180_b: 25
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
switch.lounge_cupboard_dual_usb_xus09_l2: "on"
switch.esp_loungesouthleftswitch_relay_1_wall_washer_left: "on"
switch.esp_loungesouthrightswitch_relay_2_wall_washer_right: "on"
@@ -215,6 +258,7 @@ script:
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 20
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 20
input_number.openhasp_1_backlight_level: 12
number.lounge_nspanel_touchscreen_display_brightness: 40
All Off:
light.esp_lounge6chdimmer_couch_spots_left: 0
@@ -223,7 +267,8 @@ script:
light.esp_lounge6chdimmer_lounge_downlights_centre: 0
light.esp_lounge6chdimmer_lounge_downlights_south: 0
light.esp_lounge6chdimmer_lounge_rafter_buttons: 0
switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
#switch.esp_loungemiddleswitch_relay_3_downlights_north: "off"
switch.lounge_nspanel_touchscreen_lounge_stair_downlights: "off" # non dimmable pair
light.esp_breakfastbarleds_breakfast_bar_leds: 0
light.esp_loungecabinetleds2_lounge_cabinet_leds: 0
light.esp_loungebookshelfleds_lounge_bookshelf_leds: 0
@@ -234,6 +279,9 @@ script:
number.esp_loungepelmetleds2_lounge_pelmet_leds_a_output_set_0_100: 0
number.esp_loungepelmetleds2_lounge_pelmet_leds_b_output_set_0_100: 0
#input_number.openhasp_1_backlight_level: 100
#switch.esp_mainkitchenlights_relay_1_main_lights: "off"
#switch.esp_mainkitchenlights_relay_2_benchtop_lights: "off"
number.lounge_nspanel_touchscreen_display_brightness: 80
#########################################################################
# REMEMBER LAST SCENE
View File
-20
View File
@@ -1,20 +0,0 @@
input_text:
teams_status:
name: Microsoft Teams status
icon: mdi:microsoft-teams
teams_activity:
name: Microsoft Teams activity
icon: mdi:phone-off
sensor:
- platform: template
sensors:
teams_status:
friendly_name: "Microsoft Teams status"
value_template: "{{states('input_text.teams_status')}}"
icon_template: "{{state_attr('input_text.teams_status','icon')}}"
unique_id: sensor.teams_status
teams_activity:
friendly_name: "Microsoft Teams activity"
value_template: "{{states('input_text.teams_activity')}}"
unique_id: sensor.teams_activity
-23
View File
@@ -1,23 +0,0 @@
template:
- light:
- name: "Inverted Quiet time as light"
unique_id: inverted_quiet_time_as_light
state: "{{ is_state('input_boolean.quiet_time', 'off') }}"
turn_on:
- service: light.turn_on
target:
entity_id: light.inverted_quiet_time_light
turn_off:
- service: light.turn_off
target:
entity_id: light.inverted_quiet_time_light
light:
- platform: group
name: "Entities to keep NSPanel Awake"
unique_id: entities_to_keep_nspanel_awake
entities:
- light.inverted_quiet_time_as_light_2
- light.master_bedroom_bedside_lamp_arlec_bulb_master_bedroom_bedside_lamp_arlec_bulb
- light.tasmo_ifan02_3793_bedrm1_1
- light.tasmo_ks811t_3647_bedrm1_1b
+732
View File
@@ -0,0 +1,732 @@
# yaml-language-server: $schema=null
#:########################################################################################:#
# TITLE: NSPANEL LOUNGE CONTROLLER
# zorruno.com Home Assistant package
#:########################################################################################:#
# VERSIONS:
# V1.5 2026-05-19
# - Added Reading button brightness display.
# - Reading brightness is shown as the highest brightness percentage of either
# couch spot light.
# - Changed Balanced button icon to mdi:scale / \uE472.
# - Added startup panel page refresh before full button state refresh.
#
# V1.4 2026-05-19
# - Changed button highlighting to targeted updates.
# - Remembered scene changes update only the old scene button and new scene button.
# - Reading/Dining changes update only the Reading and Dining buttons.
# - Full refresh is only used at HA start or when manually called.
# - ON icon colour is black [0, 0, 0].
# - OFF icon colour is white [255, 255, 255].
#
# V1.3 2026-05-19
# - Tested page refresh method, but it did not reliably refresh remembered scenes.
#
# V1.2 2026-05-19
# - Added explicit NSPanel button refresh actions using esphome.esp_nspanel2lounge_button.
# - Button states were pushed to the NSPanel when lounge_last_scene or the
# Reading/Dining light states changed.
#
# V1.1 2026-05-18
# - Added template switches so remembered lighting scenes can stay highlighted
# on the NSPanel button page.
# - Updated Blueprint button entities from script.* to switch.*.
#
# V1.0 2026-05-18
# - Initial NSPanel Lounge Controller package using NSPanel Easy Blueprint.
#:########################################################################################:#
# PURPOSE:
# - Configures the Lounge NSPanel Easy button page.
# - Provides Home Assistant script wrappers for lounge lighting scene actions.
# - Provides template switches for NSPanel button state/highlighting.
# - Pushes targeted NSPanel button highlight updates when relevant states change.
#:########################################################################################:#
# OPERATION NOTES:
# - The NSPanel display is configured by the NSPanel Easy Blueprint automation.
# - The screen buttons point to switch.nspanel_lounge_scene_* entities.
# - Remembered scenes are highlighted from input_text.lounge_last_scene.
# - Reading On/Off is highlighted from either couch spot light being on.
# - Reading On/Off shows the highest couch spot brightness percentage.
# - Dining On/Off is highlighted from the dining table light being on.
# - Pressing any NSPanel touch button activates the assigned scene/action.
# - Normal remembered scene transitions update only:
# a) the previous remembered scene button to OFF
# b) the new remembered scene button to ON
#:########################################################################################:#
# DEPENDENCIES:
# - script.lounge_set_scene
# - input_text.lounge_last_scene
# - light.esp_lounge6chdimmer_couch_spots_left
# - light.esp_lounge6chdimmer_couch_spots_right
# - light.esp_lounge6chdimmer_dining_table_light
# - NSPanel Easy Blueprint:
# edwardtfn/nspanel_easy_blueprint.yaml
# - ESPHome actions:
# esphome.esp_nspanel2lounge_button
# esphome.esp_nspanel2lounge_command
#:########################################################################################:#
# NOTES:
# - This is Home Assistant package YAML, not ESPHome YAML.
# - The nspanel_name value is the Home Assistant device ID selected by the
# Blueprint dropdown. Do not replace it with an entity_id or ESPHome hostname.
# - The icon values used by esphome.esp_nspanel2lounge_button are HASP/Nextion
# icon codepoints, not mdi: icon names.
#:########################################################################################:#
#:########################################################################################:#
# AUTOMATIONS
#:########################################################################################:#
automation:
#:######################################################################################:#
# AUTOMATION: NSPanel Easy Blueprint Instance
#:######################################################################################:#
- id: nspanel_lounge_controller
alias: "NSPanel Lounge Controller"
description: "NSPanel Easy configuration for the lounge lighting scene panel."
use_blueprint:
path: edwardtfn/nspanel_easy_blueprint.yaml
input:
nspanel_name: 369e58c3779ff3dd9a0b4c59fadeac4f
########################################################################
# BUTTON PAGE 01: Lounge Lighting Scenes
########################################################################
button_page01_label: Lounge Lighting Scenes
button_pages_icon_size: "10"
entity01: switch.nspanel_lounge_scene_bright
entity01_name: "Bright"
entity01_icon: mdi:brightness-7
entity01_confirm: false
entity02: switch.nspanel_lounge_scene_tv_general
entity02_name: "TV General"
entity02_icon: mdi:television
entity02_confirm: false
entity03: switch.nspanel_lounge_scene_movie
entity03_name: "Movie"
entity03_icon: mdi:movie-open
entity03_confirm: false
entity04: switch.nspanel_lounge_scene_balanced
entity04_name: "Balance"
entity04_icon: mdi:scale
entity04_confirm: false
entity05: switch.nspanel_lounge_scene_warm_cozy
entity05_name: "Warm Cozy"
entity05_icon: mdi:fireplace
entity05_confirm: false
entity06: switch.nspanel_lounge_scene_reading
entity06_name: "Reading On/Off"
entity06_icon: mdi:book-open-page-variant
entity06_confirm: false
entity07: switch.nspanel_lounge_scene_dining
entity07_name: "Dining On/Off"
entity07_icon: mdi:silverware-fork-knife
entity07_confirm: false
entity08: switch.nspanel_lounge_scene_all_off
entity08_name: "All Off"
entity08_icon: mdi:power
entity08_confirm: false
mode: single
#:######################################################################################:#
# AUTOMATION: Refresh Remembered Scene Button Highlights
#
# Only updates the previous remembered scene button and the new remembered
# scene button when input_text.lounge_last_scene changes.
#:######################################################################################:#
- id: nspanel_lounge_refresh_remembered_scene_buttons
alias: "NSPanel Lounge - Refresh Remembered Scene Buttons"
description: "Update only the old and new remembered scene buttons on the NSPanel."
mode: restart
trigger:
- platform: state
entity_id: input_text.lounge_last_scene
action:
- delay:
milliseconds: 500
- variables:
old_scene: "{{ trigger.from_state.state if trigger.from_state is not none else '' }}"
new_scene: "{{ trigger.to_state.state if trigger.to_state is not none else states('input_text.lounge_last_scene') }}"
remembered_scenes:
- "Bright"
- "TV General"
- "Balanced"
- "Movie"
- "Warm Cozy"
- "All Off"
- choose:
- conditions: "{{ old_scene in remembered_scenes and old_scene != new_scene }}"
sequence:
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "{{ old_scene }}"
button_state: false
- delay:
milliseconds: 100
- choose:
- conditions: "{{ new_scene in remembered_scenes }}"
sequence:
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "{{ new_scene }}"
button_state: true
#:######################################################################################:#
# AUTOMATION: Refresh Reading And Dining Button Highlights
#
# Reading/Dining are toggle/action scenes, so they are updated from the real
# light states rather than input_text.lounge_last_scene.
#:######################################################################################:#
- id: nspanel_lounge_refresh_toggle_scene_buttons
alias: "NSPanel Lounge - Refresh Toggle Scene Buttons"
description: "Update Reading and Dining buttons when their lights change."
mode: restart
trigger:
- platform: state
entity_id:
- light.esp_lounge6chdimmer_couch_spots_left
- light.esp_lounge6chdimmer_couch_spots_right
- light.esp_lounge6chdimmer_dining_table_light
- platform: state
entity_id:
- light.esp_lounge6chdimmer_couch_spots_left
- light.esp_lounge6chdimmer_couch_spots_right
- light.esp_lounge6chdimmer_dining_table_light
attribute: brightness
action:
- delay:
milliseconds: 500
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Reading On/Off"
button_state: >-
{{
(
is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on')
and (state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0)) > 0
)
or
(
is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on')
and (state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0)) > 0
)
}}
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Dining On/Off"
button_state: >-
{{
is_state('light.esp_lounge6chdimmer_dining_table_light', 'on')
and (state_attr('light.esp_lounge6chdimmer_dining_table_light', 'brightness') | int(0)) > 0
}}
#:######################################################################################:#
# AUTOMATION: Initial NSPanel Button Refresh
#
# Full refresh happens when HA starts, or when the NSPanel comes back online.
# Normal scene changes update only the required buttons.
#:######################################################################################:#
- id: nspanel_lounge_refresh_all_buttons_on_start
alias: "NSPanel Lounge - Refresh All Buttons On Start"
description: "Refresh all NSPanel lounge buttons when HA starts or the panel reconnects."
mode: restart
trigger:
- platform: homeassistant
event: start
- platform: state
entity_id: number.lounge_nspanel_touchscreen_display_brightness
from: "unavailable"
- platform: state
entity_id: number.lounge_nspanel_touchscreen_display_brightness
from: "unknown"
action:
- delay:
seconds: 20
- action: esphome.esp_nspanel2lounge_command
data:
cmd: "page buttonpage01"
- delay:
seconds: 1
- action: script.nspanel_lounge_refresh_all_button_states
#:########################################################################################:#
# SCRIPTS
#:########################################################################################:#
script:
#:######################################################################################:#
# SCRIPTS: NSPanel Lounge Scene Button Actions
#:######################################################################################:#
nspanel_lounge_scene_bright:
alias: "NSPanel Lounge Scene - Bright"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "Bright"
nspanel_lounge_scene_tv_general:
alias: "NSPanel Lounge Scene - TV General"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "TV General"
nspanel_lounge_scene_movie:
alias: "NSPanel Lounge Scene - Movie"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "Movie"
nspanel_lounge_scene_balanced:
alias: "NSPanel Lounge Scene - Balanced"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "Balanced"
nspanel_lounge_scene_warm_cozy:
alias: "NSPanel Lounge Scene - Warm Cozy"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "Warm Cozy"
nspanel_lounge_scene_reading:
alias: "NSPanel Lounge Scene - Reading"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "Reading On/Off"
nspanel_lounge_scene_dining:
alias: "NSPanel Lounge Scene - Dining"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "Dining On/Off"
nspanel_lounge_scene_all_off:
alias: "NSPanel Lounge Scene - All Off"
mode: single
sequence:
- action: script.lounge_set_scene
data:
scene_name: "All Off"
#:######################################################################################:#
# SCRIPT: Push One NSPanel Button State
#
# ON state:
# - Button highlighted
# - Icon colour black [0, 0, 0]
#
# OFF state:
# - Button not highlighted
# - Icon colour white [255, 255, 255]
#:######################################################################################:#
nspanel_lounge_push_button_state:
alias: "NSPanel Lounge - Push Button State"
mode: queued
max: 20
fields:
button_id:
description: "NSPanel button id, for example button01"
button_state:
description: "True for highlighted, false for normal"
icon_code:
description: "HASwitchPlate/Nextion icon codepoint"
button_label:
description: "Button label text"
button_bri:
description: "Optional brightness/value text shown on the NSPanel button"
sequence:
- variables:
button_is_on: >-
{{
button_state in [true, 'true', 'True', 'on', 'On', '1', 1]
}}
button_bri_text: "{{ button_bri if button_bri is defined else '' }}"
- choose:
- conditions: "{{ button_is_on }}"
sequence:
- action: esphome.esp_nspanel2lounge_button
data:
page: buttonpage01
id: "{{ button_id }}"
state: true
icon: "{{ icon_code }}"
icon_color:
- 0
- 0
- 0
icon_font: 10
bri: "{{ button_bri_text }}"
label: "{{ button_label }}"
is_page_render: false
default:
- action: esphome.esp_nspanel2lounge_button
data:
page: buttonpage01
id: "{{ button_id }}"
state: false
icon: "{{ icon_code }}"
icon_color:
- 255
- 255
- 255
icon_font: 10
bri: "{{ button_bri_text }}"
label: "{{ button_label }}"
is_page_render: false
#:######################################################################################:#
# SCRIPT: Push One Scene Button State
#
# Maps scene/action names to NSPanel button ids, labels and icon codepoints.
#:######################################################################################:#
nspanel_lounge_push_scene_button_state:
alias: "NSPanel Lounge - Push Scene Button State"
mode: queued
max: 20
fields:
scene_name:
description: "Lounge scene/action name"
button_state:
description: "True for highlighted, false for normal"
sequence:
- choose:
- conditions: "{{ scene_name == 'Bright' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button01
button_state: "{{ button_state }}"
icon_code: "\uE0E0"
button_label: "Bright"
button_bri: ""
- conditions: "{{ scene_name == 'TV General' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button02
button_state: "{{ button_state }}"
icon_code: "\uE502"
button_label: "TV General"
button_bri: ""
- conditions: "{{ scene_name == 'Movie' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button03
button_state: "{{ button_state }}"
icon_code: "\uEFCE"
button_label: "Movie"
button_bri: ""
- conditions: "{{ scene_name == 'Balanced' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button04
button_state: "{{ button_state }}"
icon_code: "\uE472"
button_label: "Balance"
button_bri: ""
- conditions: "{{ scene_name == 'Warm Cozy' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button05
button_state: "{{ button_state }}"
icon_code: "\uEE2E"
button_label: "Warm Cozy"
button_bri: ""
- conditions: "{{ scene_name == 'Reading On/Off' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button06
button_state: "{{ button_state }}"
icon_code: "\uE5DA"
button_label: "Reading On/Off"
button_bri: >-
{% set left_on = is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on') %}
{% set right_on = is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on') %}
{% set left_raw = state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0) if left_on else 0 %}
{% set right_raw = state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0) if right_on else 0 %}
{% set left_pct = ((left_raw / 255) * 100) | round(0) | int %}
{% set right_pct = ((right_raw / 255) * 100) | round(0) | int %}
{% set reading_pct = [left_pct, right_pct] | max %}
{% if reading_pct > 0 %}{{ reading_pct }}%{% else %}{% endif %}
- conditions: "{{ scene_name == 'Dining On/Off' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button07
button_state: "{{ button_state }}"
icon_code: "\uEA70"
button_label: "Dining On/Off"
button_bri: ""
- conditions: "{{ scene_name == 'All Off' }}"
sequence:
- action: script.nspanel_lounge_push_button_state
data:
button_id: button08
button_state: "{{ button_state }}"
icon_code: "\uE425"
button_label: "All Off"
button_bri: ""
#:######################################################################################:#
# SCRIPT: Refresh All NSPanel Lounge Button States
#
# Use this manually after a panel restart, or automatically once at HA start.
# Normal scene changes do not call this script.
#:######################################################################################:#
nspanel_lounge_refresh_all_button_states:
alias: "NSPanel Lounge - Refresh All Button States"
mode: restart
sequence:
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Bright"
button_state: "{{ is_state('switch.nspanel_lounge_scene_bright', 'on') }}"
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "TV General"
button_state: "{{ is_state('switch.nspanel_lounge_scene_tv_general', 'on') }}"
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Movie"
button_state: "{{ is_state('switch.nspanel_lounge_scene_movie', 'on') }}"
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Balanced"
button_state: "{{ is_state('switch.nspanel_lounge_scene_balanced', 'on') }}"
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Warm Cozy"
button_state: "{{ is_state('switch.nspanel_lounge_scene_warm_cozy', 'on') }}"
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Reading On/Off"
button_state: "{{ is_state('switch.nspanel_lounge_scene_reading', 'on') }}"
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "Dining On/Off"
button_state: "{{ is_state('switch.nspanel_lounge_scene_dining', 'on') }}"
- delay:
milliseconds: 100
- action: script.nspanel_lounge_push_scene_button_state
data:
scene_name: "All Off"
button_state: "{{ is_state('switch.nspanel_lounge_scene_all_off', 'on') }}"
#:######################################################################################:#
# SCRIPT: Compatibility Wrapper
#
# Older versions used this script name. Keep it as a manual full refresh.
#:######################################################################################:#
nspanel_lounge_refresh_button_states:
alias: "NSPanel Lounge - Refresh Button States"
mode: restart
sequence:
- action: script.nspanel_lounge_refresh_all_button_states
#:########################################################################################:#
# TEMPLATE SWITCHES: NSPANEL BUTTON STATE AND HIGHLIGHTING
#:########################################################################################:#
template:
- switch:
##########################################################################
# Remembered scenes
# These switches stay on when input_text.lounge_last_scene matches the
# last remembered scene name. This allows the NSPanel button to remain
# highlighted for the selected remembered scene.
##########################################################################
- name: "NSPanel Lounge Scene Bright"
unique_id: nspanel_lounge_scene_switch_bright
state: "{{ is_state('input_text.lounge_last_scene', 'Bright') }}"
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "Bright"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "Bright"
- name: "NSPanel Lounge Scene TV General"
unique_id: nspanel_lounge_scene_switch_tv_general
state: "{{ is_state('input_text.lounge_last_scene', 'TV General') }}"
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "TV General"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "TV General"
- name: "NSPanel Lounge Scene Balanced"
unique_id: nspanel_lounge_scene_switch_balanced
state: "{{ is_state('input_text.lounge_last_scene', 'Balanced') }}"
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "Balanced"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "Balanced"
- name: "NSPanel Lounge Scene Movie"
unique_id: nspanel_lounge_scene_switch_movie
state: "{{ is_state('input_text.lounge_last_scene', 'Movie') }}"
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "Movie"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "Movie"
- name: "NSPanel Lounge Scene Warm Cozy"
unique_id: nspanel_lounge_scene_switch_warm_cozy
state: "{{ is_state('input_text.lounge_last_scene', 'Warm Cozy') }}"
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "Warm Cozy"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "Warm Cozy"
- name: "NSPanel Lounge Scene All Off"
unique_id: nspanel_lounge_scene_switch_all_off
state: "{{ is_state('input_text.lounge_last_scene', 'All Off') }}"
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "All Off"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "All Off"
##########################################################################
# Toggle/action scenes
# These are excluded from input_text.lounge_last_scene, so their displayed
# state comes from the actual light entities they control.
##########################################################################
- name: "NSPanel Lounge Scene Reading"
unique_id: nspanel_lounge_scene_switch_reading
state: >-
{{
(
is_state('light.esp_lounge6chdimmer_couch_spots_left', 'on')
and (state_attr('light.esp_lounge6chdimmer_couch_spots_left', 'brightness') | int(0)) > 0
)
or
(
is_state('light.esp_lounge6chdimmer_couch_spots_right', 'on')
and (state_attr('light.esp_lounge6chdimmer_couch_spots_right', 'brightness') | int(0)) > 0
)
}}
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "Reading On/Off"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "Reading On/Off"
- name: "NSPanel Lounge Scene Dining"
unique_id: nspanel_lounge_scene_switch_dining
state: >-
{{
is_state('light.esp_lounge6chdimmer_dining_table_light', 'on')
and (state_attr('light.esp_lounge6chdimmer_dining_table_light', 'brightness') | int(0)) > 0
}}
turn_on:
- action: script.lounge_set_scene
data:
scene_name: "Dining On/Off"
turn_off:
- action: script.lounge_set_scene
data:
scene_name: "Dining On/Off"
@@ -0,0 +1,52 @@
automation:
- id: nspanel_lounge_controller
alias: "NSPanel Master Bedroom Controller"
description: ""
use_blueprint:
path: edwardtfn/nspanel_easy_blueprint.yaml
input:
nspanel_name: 084fb5b4a94e636d01244b1838156446
button_page01_label: Lounge Lighting Scenes
button_pages_icon_size: "10"
entity01: script.nspanel_lounge_scene_bright
entity01_name: "Bright"
entity01_icon: mdi:brightness-7
entity01_confirm: false
entity02: script.nspanel_lounge_scene_tv_general
entity02_name: "TV General"
entity02_icon: mdi:television
entity02_confirm: false
entity03: script.nspanel_lounge_scene_movie
entity03_name: "Movie"
entity03_icon: mdi:movie-open
entity03_confirm: false
entity04: script.nspanel_lounge_scene_balanced
entity04_name: "Balance"
entity04_icon: mdi:scale-balance
entity04_confirm: false
entity05: script.nspanel_lounge_scene_warm_cozy
entity05_name: "Warm Cozy"
entity05_icon: mdi:fireplace
entity05_confirm: false
entity06: script.nspanel_lounge_scene_reading
entity06_name: "Reading On/Off"
entity06_icon: mdi:book-open-page-variant
entity06_confirm: false
entity07: script.nspanel_lounge_scene_dining
entity07_name: "Dining On/Off"
entity07_icon: mdi:silverware-fork-knife
entity07_confirm: false
entity08: script.nspanel_lounge_scene_all_off
entity08_name: "All Off"
entity08_icon: mdi:power
entity08_confirm: false
mode: single
File diff suppressed because it is too large Load Diff
+123
View File
@@ -0,0 +1,123 @@
################################################################################
# Quiet Time Package
################################################################################
#
# TITLE:
# Quiet Time
#
# VERSIONS:
# V1.2 2026-05-21
# - Added MQTT publishing when input_boolean.quiet_time changes.
# - Publishes quiet_time state to viewroad-status/homeassistant/quiet-time.
#
# V1.1 2026-05-21
# - Reduced daily reset check frequency from every minute to every 30 minutes.
# - Reduced reset dropdown options to 00:30 through 10:00 only.
#
# V1.0 2026-05-21
# - Initial package.
# - Adds input_boolean.quiet_time.
# - Adds input_select.quiet_time_daily_reset.
# - Adds daily automation to turn quiet_time OFF at the selected reset time.
#
# OPERATION NOTES:
# - input_boolean.quiet_time is the master quiet time toggle.
# - Other packages can check input_boolean.quiet_time before sending
# announcements, notifications, TTS messages, or similar.
# - input_select.quiet_time_daily_reset selects the daily time that quiet_time
# will automatically be turned OFF.
# - Default reset time is 07:00.
# - The quiet_time state is published to MQTT whenever it changes.
#
# MQTT STATUS:
# - Topic:
# viewroad-status/homeassistant/quiet-time
# - Payload:
# on
# off
#
################################################################################
################################################################################
# INPUT BOOLEAN
################################################################################
input_boolean:
quiet_time:
name: Quiet Time
icon: mdi:bell-off
################################################################################
# INPUT SELECT
################################################################################
input_select:
quiet_time_daily_reset:
name: Quiet time daily reset
icon: mdi:clock-end
options:
- "00:30"
- "01:00"
- "01:30"
- "02:00"
- "02:30"
- "03:00"
- "03:30"
- "04:00"
- "04:30"
- "05:00"
- "05:30"
- "06:00"
- "06:30"
- "07:00"
- "07:30"
- "08:00"
- "08:30"
- "09:00"
- "09:30"
- "10:00"
initial: "07:00"
################################################################################
# AUTOMATIONS
################################################################################
automation:
- id: quiet_time_daily_reset_turn_off
alias: "Quiet Time - Daily Reset Off"
description: "Turns Quiet Time off once per day at the selected reset time."
mode: single
triggers:
- trigger: time_pattern
minutes: "/30"
seconds: "0"
conditions:
- condition: state
entity_id: input_boolean.quiet_time
state: "on"
- condition: template
value_template: >
{{ states('input_select.quiet_time_daily_reset') == now().strftime('%H:%M') }}
actions:
- action: input_boolean.turn_off
target:
entity_id: input_boolean.quiet_time
- id: quiet_time_settings_to_mqtt
alias: "Publish quiet time value to MQTT"
description: "Publishes the Quiet Time boolean state to MQTT whenever it changes."
mode: single
triggers:
- trigger: state
entity_id: input_boolean.quiet_time
actions:
- action: mqtt.publish
data:
topic: viewroad-status/homeassistant/quiet-time
payload: "{{ trigger.to_state.state }}"
-4
View File
@@ -1,4 +0,0 @@
# Text to speech
tts:
platform: google_translate
service_name: google_say
@@ -343,6 +343,31 @@ script:
- 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 }}"