various tidyups
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@@ -1 +1 @@
|
||||
{"pid": 71, "version": 1, "ha_version": "2026.8.3", "start_ts": 1788051080.3314128}
|
||||
{"pid": 71, "version": 1, "ha_version": "2026.9.2", "start_ts": 1789211351.1286738}
|
||||
@@ -0,0 +1,67 @@
|
||||
TP-Link Deco Guest Wi-Fi Recovery Archive
|
||||
==========================================
|
||||
|
||||
Version: 1.0.0
|
||||
Created: 2026-09-02
|
||||
Project: P026 Flounder downstairs guest-area controls
|
||||
|
||||
Purpose
|
||||
-------
|
||||
|
||||
This archive preserves the locally maintained TP-Link Deco Guest Wi-Fi
|
||||
customisation. The upstream tplink_deco integration does not provide this
|
||||
service or sensor. Reinstalling or overwriting custom_components/tplink_deco
|
||||
can remove them.
|
||||
|
||||
Archive
|
||||
-------
|
||||
|
||||
File: docs/tplink_deco_guest_wifi_recovery_2026-09-02.tgz
|
||||
SHA-256: 452ed7b7be5e8c469dc7740d5297959179204d24593a22c965f1915ca727c48d
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
- custom_components/tplink_deco/api.py
|
||||
- custom_components/tplink_deco/__init__.py
|
||||
- custom_components/tplink_deco/const.py
|
||||
- custom_components/tplink_deco/services.yaml
|
||||
- custom_components/tplink_deco/coordinator.py
|
||||
- custom_components/tplink_deco/binary_sensor.py
|
||||
- packages/tplink_deco_guest_wifi.yaml
|
||||
|
||||
Behaviour Preserved
|
||||
-------------------
|
||||
|
||||
- Service: tplink_deco.set_guest_network
|
||||
- Service field: enable (boolean)
|
||||
- Router state: binary_sensor.data_cupboard_new_sundamage_12_deco_guest_network
|
||||
- Requested state: input_boolean.wifi_guest_network
|
||||
- Flounder control: the requested-state helper; the package reconciles it to
|
||||
the router-confirmed sensor.
|
||||
- Write protocol: read each returned wireless band, retain its host, guest and
|
||||
backhaul settings, set only guest.enable, add radio.channel from host.channel,
|
||||
write each band separately, then read back and verify every written band.
|
||||
- Deco firmware can return a malformed successful response containing
|
||||
{"error_code": 0}; the integration accepts that response only for writes and
|
||||
relies on the read-back verification as the final confirmation.
|
||||
|
||||
Recovery Procedure
|
||||
------------------
|
||||
|
||||
1. Stop before updating, reinstalling, or deleting custom_components/tplink_deco.
|
||||
2. Verify the archive checksum above.
|
||||
3. Extract the archive from /homeassistant, preserving the listed paths.
|
||||
4. Run Home Assistant configuration validation and Python compilation for the
|
||||
restored integration files.
|
||||
5. Restart Home Assistant. A restart is required for custom integration code.
|
||||
6. Confirm tplink_deco.set_guest_network is registered and the Guest Network
|
||||
binary sensor is available before operating Guest Wi-Fi.
|
||||
|
||||
Update Policy
|
||||
-------------
|
||||
|
||||
Do not replace custom_components/tplink_deco with an upstream or HACS update
|
||||
without first comparing it to this archive and deliberately reapplying the
|
||||
Guest Wi-Fi customisation. The archive contains no credentials, tokens, session
|
||||
cookies, or router address.
|
||||
@@ -0,0 +1,223 @@
|
||||
--- a/esp-bedside-panel.yaml
|
||||
+++ b/esp-bedside-panel.yaml
|
||||
@@ -5,6 +5,7 @@
|
||||
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedside-panel.yaml
|
||||
#:########################################################################################:#
|
||||
# VERSIONS:
|
||||
+# V1.56 2026-09-04 Added latched blackout after 10 seconds below 1 lx with immediate exit
|
||||
# V1.55 2026-08-16 Show only Clock time and date in Blackout ambient-light mode
|
||||
# V1.54 2026-08-16 Dimmed Clock time and date palette in Blackout ambient-light mode
|
||||
@@ -248,7 +249,6 @@
|
||||
# Bright light: approximately 642-643 lx
|
||||
ambient_lux_multiplier_default: "200"
|
||||
-
|
||||
- display_blackout_lux_threshold_default: "2"
|
||||
display_dark_lux_threshold_default: "20"
|
||||
display_bright_lux_threshold_default: "250"
|
||||
@@ -921,21 +921,6 @@
|
||||
step: 5
|
||||
mode: box
|
||||
|
||||
- - platform: template
|
||||
- id: display_blackout_lux_threshold
|
||||
- name: "${friendly_name} Blackout Lux Threshold"
|
||||
- icon: mdi:brightness-1
|
||||
- entity_category: config
|
||||
- optimistic: true
|
||||
- restore_value: true
|
||||
- initial_value: "${display_blackout_lux_threshold_default}"
|
||||
- unit_of_measurement: "lx"
|
||||
- min_value: 0
|
||||
- max_value: 20
|
||||
- step: 0.5
|
||||
- mode: box
|
||||
-
|
||||
- platform: template
|
||||
id: display_dark_lux_threshold
|
||||
@@ -1228,6 +1213,45 @@
|
||||
update_interval: 3s
|
||||
lambda: |-
|
||||
const float voltage = id(ambient_light_voltage).state;
|
||||
+
|
||||
+ if (isnan(voltage)) {
|
||||
+ return NAN;
|
||||
+ }
|
||||
+
|
||||
+ float multiplier = id(ambient_lux_multiplier).state;
|
||||
+
|
||||
+ if (isnan(multiplier) || multiplier <= 0.0f) {
|
||||
+ multiplier = 200.0f;
|
||||
+ }
|
||||
+
|
||||
+ return voltage * multiplier;
|
||||
+ on_value:
|
||||
+ then:
|
||||
+ - if:
|
||||
+ condition:
|
||||
+ lambda: |-
|
||||
+ return !isnan(x) && x >= 1.0f;
|
||||
+ then:
|
||||
+ - script.stop: latch_display_blackout
|
||||
+ - lambda: |-
|
||||
+ id(display_blackout_active) = false;
|
||||
+ - if:
|
||||
+ condition:
|
||||
+ lambda: |-
|
||||
+ return id(lvgl_ready) && id(display_is_dimmed);
|
||||
+ then:
|
||||
+ - script.execute: apply_dim_backlight
|
||||
+ else:
|
||||
+ - if:
|
||||
+ condition:
|
||||
+ lambda: |-
|
||||
+ return id(lvgl_ready);
|
||||
+ then:
|
||||
+ - script.execute: apply_active_backlight
|
||||
+ else:
|
||||
+ - if:
|
||||
+ condition:
|
||||
+ lambda: |-
|
||||
+ return !isnan(x) && x < 1.0f && !id(display_blackout_active);
|
||||
+ then:
|
||||
+ - script.execute: latch_display_blackout
|
||||
- float multiplier = id(ambient_lux_multiplier).state;
|
||||
-
|
||||
- if (isnan(voltage)) {
|
||||
- return NAN;
|
||||
- }
|
||||
-
|
||||
- if (isnan(multiplier) || multiplier <= 0.0f) {
|
||||
- multiplier = 200.0f;
|
||||
- }
|
||||
-
|
||||
- return voltage * multiplier;
|
||||
|
||||
- platform: homeassistant
|
||||
@@ -1918,6 +1942,12 @@
|
||||
restore_value: false
|
||||
initial_value: "false"
|
||||
|
||||
+ # True after ambient light remains below 1 lx for 10 continuous seconds.
|
||||
+ - id: display_blackout_active
|
||||
+ type: bool
|
||||
+ restore_value: false
|
||||
+ initial_value: "false"
|
||||
+
|
||||
# True only while the Security page is visible.
|
||||
@@ -3133,31 +3163,52 @@
|
||||
- # Four ambient ranges are used:
|
||||
- # Blackout: lux < Blackout Lux Threshold
|
||||
- # Dark: Blackout threshold to Dark Lux Threshold
|
||||
- # Normal: between Dark and Bright thresholds
|
||||
- # Bright: lux >= Bright Lux Threshold
|
||||
+ # Blackout latches after ambient light remains below 1 lx for 10 seconds and
|
||||
+ # exits immediately when ambient light reaches 1 lx. The remaining ranges are:
|
||||
+ # Dark: lux <= Dark Lux Threshold
|
||||
+ # Normal: between Dark and Bright thresholds
|
||||
+ # Bright: lux >= Bright Lux Threshold
|
||||
#
|
||||
# The active and clock/idle brightness levels are independently adjustable
|
||||
# and restored after reboot.
|
||||
|
||||
+ - id: latch_display_blackout
|
||||
+ mode: single
|
||||
+ then:
|
||||
+ - delay: 10s
|
||||
+ - if:
|
||||
+ condition:
|
||||
+ lambda: |-
|
||||
+ const float lux = id(ambient_light_illuminance).state;
|
||||
+ return !isnan(lux) && lux < 1.0f;
|
||||
+ then:
|
||||
+ - lambda: |-
|
||||
+ id(display_blackout_active) = true;
|
||||
+ - if:
|
||||
+ condition:
|
||||
+ lambda: |-
|
||||
+ return id(lvgl_ready) && id(display_is_dimmed);
|
||||
+ then:
|
||||
+ - script.execute: apply_dim_backlight
|
||||
+ else:
|
||||
+ - if:
|
||||
+ condition:
|
||||
+ lambda: |-
|
||||
+ return id(lvgl_ready);
|
||||
+ then:
|
||||
+ - script.execute: apply_active_backlight
|
||||
+
|
||||
# Keep the idle Clock unobtrusive at the minimum usable backlight level.
|
||||
- id: apply_clock_blackout_palette
|
||||
@@ -3146,15 +3197,7 @@
|
||||
- if:
|
||||
condition:
|
||||
lambda: |-
|
||||
- const float lux = id(ambient_light_illuminance).state;
|
||||
- float blackout_threshold =
|
||||
- id(display_blackout_lux_threshold).state;
|
||||
-
|
||||
- if (isnan(blackout_threshold)) {
|
||||
- blackout_threshold = 2.0f;
|
||||
- }
|
||||
-
|
||||
- return !isnan(lux) && lux < blackout_threshold;
|
||||
+ return id(display_blackout_active);
|
||||
@@ -3212,22 +3255,12 @@
|
||||
brightness: !lambda |-
|
||||
const float lux = id(ambient_light_illuminance).state;
|
||||
|
||||
- float blackout_threshold =
|
||||
- id(display_blackout_lux_threshold).state;
|
||||
float dark_threshold =
|
||||
id(display_dark_lux_threshold).state;
|
||||
float bright_threshold =
|
||||
id(display_bright_lux_threshold).state;
|
||||
|
||||
- if (isnan(blackout_threshold)) {
|
||||
- blackout_threshold = 2.0f;
|
||||
- }
|
||||
-
|
||||
if (
|
||||
isnan(dark_threshold) ||
|
||||
- dark_threshold <= blackout_threshold
|
||||
+ dark_threshold <= 0.0f
|
||||
) {
|
||||
dark_threshold = 20.0f;
|
||||
}
|
||||
@@ -3239,7 +3272,7 @@
|
||||
|
||||
float brightness_percent;
|
||||
|
||||
- if (!isnan(lux) && lux < blackout_threshold) {
|
||||
+ if (id(display_blackout_active)) {
|
||||
brightness_percent =
|
||||
id(display_blackout_brightness).state;
|
||||
@@ -3280,22 +3313,12 @@
|
||||
brightness: !lambda |-
|
||||
const float lux = id(ambient_light_illuminance).state;
|
||||
|
||||
- float blackout_threshold =
|
||||
- id(display_blackout_lux_threshold).state;
|
||||
float dark_threshold =
|
||||
id(display_dark_lux_threshold).state;
|
||||
float bright_threshold =
|
||||
id(display_bright_lux_threshold).state;
|
||||
|
||||
- if (isnan(blackout_threshold)) {
|
||||
- blackout_threshold = 2.0f;
|
||||
- }
|
||||
-
|
||||
if (
|
||||
isnan(dark_threshold) ||
|
||||
- dark_threshold <= blackout_threshold
|
||||
+ dark_threshold <= 0.0f
|
||||
) {
|
||||
dark_threshold = 20.0f;
|
||||
}
|
||||
@@ -3307,7 +3330,7 @@
|
||||
|
||||
float brightness_percent;
|
||||
|
||||
- if (!isnan(lux) && lux < blackout_threshold) {
|
||||
+ if (id(display_blackout_active)) {
|
||||
brightness_percent =
|
||||
id(display_blackout_brightness).state;
|
||||
@@ -1,26 +1,28 @@
|
||||
#:########################################################################################:#
|
||||
# PACKAGE: Office Lights Home Assistant Fallback Synchronization
|
||||
# FILE: Lighting_2Way_Sync/office_lights_ha_fallback_sync.yaml
|
||||
# VERSION: v1.0.0
|
||||
# DATE: 2026-08-16
|
||||
# VERSION: v1.2.0
|
||||
# DATE: 2026-09-12
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# PURPOSE:
|
||||
# Provides the Home Assistant API transport for Office two-way light control
|
||||
# when MQTT is unavailable. Direct MQTT remains the HA-down transport.
|
||||
# Provides Home Assistant-primary synchronization for the Office two-way
|
||||
# light controls. Direct MQTT peer control is the HA-down transport.
|
||||
#
|
||||
# OPERATION:
|
||||
# - Synchronizes the Office bunker and overhead control pairs in both directions.
|
||||
# - Uses idempotent Home Assistant actions, so MQTT and HA may both be online
|
||||
# without creating a control loop.
|
||||
# - ESPHome permits direct MQTT peer synchronization only while HA's native
|
||||
# API state subscription is disconnected, preventing competing controllers.
|
||||
# - Does not reconcile state during Home Assistant startup, preventing a stale
|
||||
# restored entity state from changing a physical light.
|
||||
#
|
||||
# DEPENDENCIES:
|
||||
# - Blueprint: zorruno/two_three_way_sync.yaml
|
||||
# - esp-officelights and esp-officeduallights native ESPHome API connections.
|
||||
# - esp-officelights v3.2 and esp-officeduallights v3.0 or later.
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# - v1.2.0 (2026-09-12): Enable after guarded HA-primary firmware deployment.
|
||||
# - v1.1.0 (2026-09-12): Disabled until guarded HA-primary firmware deployment.
|
||||
# - v1.0.0 (2026-08-16): Initial MQTT-down HA fallback for Office lights.
|
||||
#:########################################################################################:#
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#:########################################################################################:#
|
||||
# PACKAGE: Office Lights Home Assistant Fallback Synchronization
|
||||
# FILE: Lighting_2Way_Sync/office_lights_ha_fallback_sync.yaml
|
||||
# VERSION: v1.1.0
|
||||
# DATE: 2026-09-12
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# PURPOSE:
|
||||
# Provides the Home Assistant API transport for Office two-way light control
|
||||
# when MQTT is unavailable. Direct MQTT remains the HA-down transport.
|
||||
#
|
||||
# OPERATION:
|
||||
# - Synchronizes the Office bunker and overhead control pairs in both directions.
|
||||
# - The automations remain disabled until both ESPHome devices enforce the
|
||||
# HA-primary/MQTT-fallback authority boundary.
|
||||
# - Does not reconcile state during Home Assistant startup, preventing a stale
|
||||
# restored entity state from changing a physical light.
|
||||
#
|
||||
# DEPENDENCIES:
|
||||
# - Blueprint: zorruno/two_three_way_sync.yaml
|
||||
# - esp-officelights and esp-officeduallights native ESPHome API connections.
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# - v1.1.0 (2026-09-12): Disable until guarded HA-primary firmware is deployed.
|
||||
# - v1.0.0 (2026-08-16): Initial MQTT-down HA fallback for Office lights.
|
||||
#:########################################################################################:#
|
||||
|
||||
automation:
|
||||
#:##########################################################################:#
|
||||
# BUNKER LIGHTS
|
||||
#:##########################################################################:#
|
||||
- id: office_bunker_lights_ha_fallback_sync
|
||||
alias: "Office Bunker Lights HA Fallback Sync"
|
||||
initial_state: false
|
||||
use_blueprint:
|
||||
path: zorruno/two_three_way_sync.yaml
|
||||
input:
|
||||
members:
|
||||
- switch.office_office_main_lightswitch_3_relay_1_bunker_lights
|
||||
- light.esp_officeduallights_light_1_right_hand_bunker_light
|
||||
sync_on_start: false
|
||||
startup_delay: 5
|
||||
|
||||
#:##########################################################################:#
|
||||
# OVERHEAD LIGHTS
|
||||
#:##########################################################################:#
|
||||
- id: office_overhead_lights_ha_fallback_sync
|
||||
alias: "Office Overhead Lights HA Fallback Sync"
|
||||
initial_state: false
|
||||
use_blueprint:
|
||||
path: zorruno/two_three_way_sync.yaml
|
||||
input:
|
||||
members:
|
||||
- switch.office_office_main_lightswitch_3_relay_2_overhead_lights
|
||||
- light.esp_officeduallights_light_2_cool_white_overhead_lights
|
||||
sync_on_start: false
|
||||
startup_delay: 5
|
||||
@@ -9,9 +9,13 @@
|
||||
# packages/Pool_Controls/pool_light_operation.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.2 2026-07-20
|
||||
# V1.3 2026-09-06
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.3 2026-09-06
|
||||
# - Treat the colour selector's "0= OFF" as a true Operation Mode OFF and
|
||||
# arm the midnight TIMER reset.
|
||||
#
|
||||
# V1.2 2026-07-20
|
||||
# - Corrected the documented package filename.
|
||||
# - Documented the relationship with the native ESPHome controls.
|
||||
@@ -151,6 +155,40 @@ automation:
|
||||
target:
|
||||
entity_id: input_boolean.timer_light_midnight_pending
|
||||
|
||||
- id: pool_light_schedule_timer_when_operation_mode_off
|
||||
alias: "Pool Light - Schedule TIMER When Operation Mode Is OFF"
|
||||
description: "Arms the midnight TIMER reset for direct Operation Mode OFF commands."
|
||||
mode: single
|
||||
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: select.esp_poollightpower2_operation_mode
|
||||
to: "OFF"
|
||||
|
||||
action:
|
||||
- action: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.timer_light_midnight_pending
|
||||
|
||||
- id: pool_light_send_off_when_colour_off_selected
|
||||
alias: "Pool Light - Send OFF When Colour Off Is Selected"
|
||||
description: "Converts colour selector 0= OFF into Operation Mode OFF with midnight reset."
|
||||
mode: restart
|
||||
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: select.esp_poollightpower2_pool_light_mode
|
||||
to: "0= OFF"
|
||||
|
||||
action:
|
||||
- action: mqtt.publish
|
||||
data:
|
||||
topic: "viewroad-commands/poollight-timer/operation"
|
||||
payload: "OFF"
|
||||
- action: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.timer_light_midnight_pending
|
||||
|
||||
- id: pool_light_sync_ui_switch_with_real_output
|
||||
alias: "Pool Light - Sync UI Switch With Real Output"
|
||||
description: "Keeps the UI switch aligned with the real ESPHome pool light output without sending MQTT commands."
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Package: BYD Lock Button
|
||||
# Purpose:
|
||||
# Provides a voice-assistant-safe BYD lock control that can only issue a lock command.
|
||||
# Notes:
|
||||
# The icon reflects the live state of the underlying BYD lock. This button has no
|
||||
# unlock action.
|
||||
# Version history:
|
||||
# - 1.0.0: Initial lock-only BYD button.
|
||||
#
|
||||
#:########################################################################################:#
|
||||
# Template Button
|
||||
#:########################################################################################:#
|
||||
template:
|
||||
- button:
|
||||
- name: "BYD Lock"
|
||||
unique_id: byd_lock_button
|
||||
default_entity_id: button.byd_lock
|
||||
availability: "{{ has_value('lock.atto_3_lock') }}"
|
||||
icon: >-
|
||||
{{ 'mdi:lock' if is_state('lock.atto_3_lock', 'locked') else 'mdi:lock-open' }}
|
||||
press:
|
||||
- action: lock.lock
|
||||
target:
|
||||
entity_id: lock.atto_3_lock
|
||||
@@ -2,8 +2,8 @@
|
||||
# PACKAGE: Energy Cost Monitoring
|
||||
################################################################################
|
||||
#
|
||||
# Version: 1.3.0
|
||||
# Date: 2026-08-23
|
||||
# Version: 1.3.1
|
||||
# Date: 2026-09-01
|
||||
#
|
||||
# Purpose:
|
||||
# Track GST-inclusive electricity costs for the three-phase grid supply and
|
||||
@@ -18,6 +18,8 @@
|
||||
# boundary without averaging the old and new rates.
|
||||
#
|
||||
# Version history:
|
||||
# 1.3.1 (2026-09-01): Move Downstairs Fridge and Freezer shared power-cost
|
||||
# telemetry from X41PP to X68PM.
|
||||
# 1.3.0 (2026-08-24): Add Drinks Fridge and Vertical Freezer energy and
|
||||
# cost monitoring.
|
||||
# 1.2.0 (2026-08-23): Add Downstairs Lounge North GPO (X48PM) energy and
|
||||
@@ -326,11 +328,11 @@ template:
|
||||
unique_id: energy_cost_downstairs_fridge_rate
|
||||
unit_of_measurement: "NZD/h"
|
||||
state_class: measurement
|
||||
availability: "{{ has_value('sensor.downstairs_fridge_power_x41pp_power') }}"
|
||||
availability: "{{ has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') }}"
|
||||
state: >-
|
||||
{{
|
||||
(
|
||||
states('sensor.downstairs_fridge_power_x41pp_power') | float(0)
|
||||
states('sensor.downstairs_fridge_gpo_power_x68pm_power') | float(0)
|
||||
/ 1000
|
||||
* states('sensor.electricity_current_price') | float(0)
|
||||
) | round(6)
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
#:########################################################################################:#
|
||||
# PACKAGE: Fridge and Freezer Monitoring
|
||||
# FILE: packages/fridge_freezer_monitoring.yaml
|
||||
# VERSION: v1.11.0 2026-08-30
|
||||
# VERSION: v1.13.0 2026-09-03
|
||||
# - Moves Downstairs Freezer temperature, humidity, and battery monitoring
|
||||
# from X62TS to X70TS.
|
||||
# - Moves shared Downstairs Fridge and Freezer power monitoring from X41PP to
|
||||
# the metering-only X68PM GPO.
|
||||
# - Reports an unavailable Main Kitchen Fridge battery monitor explicitly,
|
||||
# rather than showing an unqualified issue.
|
||||
# - Moves Main Kitchen Fridge temperature, humidity, and battery monitoring to
|
||||
# X65TS and adds X64LS illuminance-based door monitoring.
|
||||
# - v1.10.0 2026-08-29: Adds Downstairs Freezer temperature, battery, door, humidity, and shared
|
||||
@@ -61,8 +67,7 @@
|
||||
# - Seven configured fridge/freezer temperature and battery monitor pairs.
|
||||
# - switch.upstairs_fridge_power_x31pp
|
||||
# - sensor.upstairs_fridge_power_x31pp_power
|
||||
# - switch.downstairs_fridge_power_x41pp
|
||||
# - sensor.downstairs_fridge_power_x41pp_power
|
||||
# - sensor.downstairs_fridge_gpo_power_x68pm_power
|
||||
# - switch.drinks_fridge_power_x59pm
|
||||
# - sensor.drinks_fridge_power_x59pm_power
|
||||
# - switch.vertical_freezer_power_x60pm
|
||||
@@ -173,7 +178,7 @@ sensor:
|
||||
- platform: statistics
|
||||
name: "Downstairs Freezer Temperature Average 7 Days"
|
||||
unique_id: downstairs_freezer_temperature_average_7_days
|
||||
entity_id: sensor.downstairs_freezer_temperature_x62ts_temperature
|
||||
entity_id: sensor.downstairs_freezer_temperature_x70ts_temperature
|
||||
state_characteristic: average_step
|
||||
max_age:
|
||||
days: 7
|
||||
@@ -182,7 +187,7 @@ sensor:
|
||||
- platform: statistics
|
||||
name: "Downstairs Freezer Temperature 95th Percentile 7 Days"
|
||||
unique_id: downstairs_freezer_temperature_95th_percentile_7_days
|
||||
entity_id: sensor.downstairs_freezer_temperature_x62ts_temperature
|
||||
entity_id: sensor.downstairs_freezer_temperature_x70ts_temperature
|
||||
state_characteristic: percentile
|
||||
percentile: 95
|
||||
max_age:
|
||||
@@ -192,7 +197,7 @@ sensor:
|
||||
- platform: derivative
|
||||
name: "Downstairs Freezer Temperature Change Rate"
|
||||
unique_id: downstairs_freezer_temperature_change_rate
|
||||
source: sensor.downstairs_freezer_temperature_x62ts_temperature
|
||||
source: sensor.downstairs_freezer_temperature_x70ts_temperature
|
||||
unit_time: h
|
||||
time_window: "00:30:00"
|
||||
max_sub_interval: "00:05:00"
|
||||
@@ -414,11 +419,10 @@ template:
|
||||
unique_id: downstairs_fridge_power_draw_lost
|
||||
device_class: problem
|
||||
state: >-
|
||||
{% set power = states('sensor.downstairs_fridge_power_x41pp_power') | float(none) %}
|
||||
{% set changed = states.sensor.downstairs_fridge_power_x41pp_power.last_changed %}
|
||||
{% set power = states('sensor.downstairs_fridge_gpo_power_x68pm_power') | float(none) %}
|
||||
{% set changed = states.sensor.downstairs_fridge_gpo_power_x68pm_power.last_changed %}
|
||||
{{
|
||||
is_state('switch.downstairs_fridge_power_x41pp', 'on')
|
||||
and power is not none
|
||||
power is not none
|
||||
and power < 1
|
||||
and (now() - changed).total_seconds() >= 4 * 60 * 60
|
||||
}}
|
||||
@@ -450,7 +454,11 @@ template:
|
||||
{{
|
||||
temperature_missing
|
||||
or illuminance_missing
|
||||
or (states('sensor.main_kitchen_fridge_temperature_x65ts_battery') | float(-1)) <= 20
|
||||
or battery_missing
|
||||
or (
|
||||
not battery_missing
|
||||
and (states('sensor.main_kitchen_fridge_temperature_x65ts_battery') | float(0)) <= 20
|
||||
)
|
||||
or is_state('binary_sensor.main_kitchen_fridge_door_open_too_long', 'on')
|
||||
or (
|
||||
not temperature_missing
|
||||
@@ -477,7 +485,9 @@ template:
|
||||
{% if illuminance_missing %}
|
||||
{% set ns.items = ns.items + ['Door monitor unavailable'] %}
|
||||
{% endif %}
|
||||
{% if not battery_missing and (states('sensor.main_kitchen_fridge_temperature_x65ts_battery') | float(-1)) <= 20 %}
|
||||
{% if battery_missing %}
|
||||
{% set ns.items = ns.items + ['Battery monitor unavailable'] %}
|
||||
{% elif (states('sensor.main_kitchen_fridge_temperature_x65ts_battery') | float(0)) <= 20 %}
|
||||
{% set ns.items = ns.items + ['Low monitor battery'] %}
|
||||
{% endif %}
|
||||
{% if states('switch.upstairs_fridge_power_x31pp') in ['unknown', 'unavailable'] or power_missing %}
|
||||
@@ -596,7 +606,6 @@ template:
|
||||
{% set threshold = [9, percentile + 0.5] | min if percentile is not none else 9 %}
|
||||
{{
|
||||
temperature_missing
|
||||
or battery_missing
|
||||
or (states('sensor.lcd_temp_humidity_btt04_battery') | float(-1)) <= 20
|
||||
or (not temperature_missing and (states('sensor.lcd_temp_humidity_btt04_temperature') | float(0)) > threshold)
|
||||
}}
|
||||
@@ -608,8 +617,8 @@ template:
|
||||
{% set battery_missing = not has_value('sensor.lcd_temp_humidity_btt04_battery') %}
|
||||
{% set percentile = states('sensor.wine_fridge_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{% set threshold = [9, percentile + 0.5] | min if percentile is not none else 9 %}
|
||||
{% if temperature_missing or battery_missing %}
|
||||
{% set ns.items = ns.items + ['Monitor offline'] %}
|
||||
{% if temperature_missing %}
|
||||
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
|
||||
{% endif %}
|
||||
{% if not battery_missing and (states('sensor.lcd_temp_humidity_btt04_battery') | float(-1)) <= 20 %}
|
||||
{% set ns.items = ns.items + ['Low monitor battery'] %}
|
||||
@@ -638,7 +647,7 @@ template:
|
||||
{% set temperature_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_temperature') %}
|
||||
{% set battery_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_battery') %}
|
||||
{% set illuminance_missing = not has_value('sensor.downstairs_fridge_light_sensor_x58ls_illuminance') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_power_x41pp_power') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
|
||||
{% set percentile = states('sensor.downstairs_fridge_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{% set threshold = [10, percentile + 0.5] | min if percentile is not none else 10 %}
|
||||
{{
|
||||
@@ -651,7 +660,6 @@ template:
|
||||
and not is_state('binary_sensor.downstairs_fridge_temperature_recovery_grace', 'on')
|
||||
and (states('sensor.downstairs_fridge_temperature_x43ts_temperature') | float(0)) > threshold
|
||||
)
|
||||
or states('switch.downstairs_fridge_power_x41pp') != 'on'
|
||||
or power_missing
|
||||
or is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on')
|
||||
}}
|
||||
@@ -662,7 +670,7 @@ template:
|
||||
{% set temperature_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_temperature') %}
|
||||
{% set battery_missing = not has_value('sensor.downstairs_fridge_temperature_x43ts_battery') %}
|
||||
{% set illuminance_missing = not has_value('sensor.downstairs_fridge_light_sensor_x58ls_illuminance') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_power_x41pp_power') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
|
||||
{% set percentile = states('sensor.downstairs_fridge_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{% set threshold = [10, percentile + 0.5] | min if percentile is not none else 10 %}
|
||||
{% if temperature_missing %}
|
||||
@@ -674,10 +682,8 @@ template:
|
||||
{% if not battery_missing and (states('sensor.downstairs_fridge_temperature_x43ts_battery') | float(-1)) <= 20 %}
|
||||
{% set ns.items = ns.items + ['Low monitor battery'] %}
|
||||
{% endif %}
|
||||
{% if states('switch.downstairs_fridge_power_x41pp') in ['unknown', 'unavailable'] or power_missing %}
|
||||
{% if power_missing %}
|
||||
{% set ns.items = ns.items + ['Power monitoring unavailable'] %}
|
||||
{% elif not is_state('switch.downstairs_fridge_power_x41pp', 'on') %}
|
||||
{% set ns.items = ns.items + ['Power switched off'] %}
|
||||
{% elif is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on') %}
|
||||
{% set ns.items = ns.items + ['Power lost - no power draw for 4 hours'] %}
|
||||
{% endif %}
|
||||
@@ -701,7 +707,7 @@ template:
|
||||
{{ [10, percentile + 0.5] | min if percentile is not none else 10 }}
|
||||
change_rate: "{{ states('sensor.downstairs_fridge_temperature_change_rate') }}"
|
||||
battery: "{{ states('sensor.downstairs_fridge_temperature_x43ts_battery') }}"
|
||||
power: "{{ states('sensor.downstairs_fridge_power_x41pp_power') }}"
|
||||
power: "{{ states('sensor.downstairs_fridge_gpo_power_x68pm_power') }}"
|
||||
door_open: "{{ is_state('binary_sensor.downstairs_fridge_door_open', 'on') }}"
|
||||
illuminance: "{{ states('sensor.downstairs_fridge_light_sensor_x58ls_illuminance') }}"
|
||||
|
||||
@@ -710,22 +716,22 @@ template:
|
||||
device_class: problem
|
||||
delay_on: "00:01:00"
|
||||
state: >-
|
||||
{% set temperature_missing = not has_value('sensor.downstairs_freezer_temperature_x62ts_temperature') %}
|
||||
{% set battery_missing = not has_value('sensor.downstairs_freezer_temperature_x62ts_battery') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_power_x41pp_power') %}
|
||||
{% set temperature_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_temperature') %}
|
||||
{% set battery_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_battery') %}
|
||||
{% set illuminance_missing = not has_value('sensor.downstairs_freezer_light_sensor_x61ls_illuminance') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
|
||||
{% set percentile = states('sensor.downstairs_freezer_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
|
||||
{{
|
||||
temperature_missing
|
||||
or battery_missing
|
||||
or (states('sensor.downstairs_freezer_temperature_x62ts_battery') | float(-1)) <= 20
|
||||
or illuminance_missing
|
||||
or (states('sensor.downstairs_freezer_temperature_x70ts_battery') | float(-1)) <= 20
|
||||
or is_state('binary_sensor.downstairs_freezer_door_open_too_long', 'on')
|
||||
or (
|
||||
not temperature_missing
|
||||
and not is_state('binary_sensor.downstairs_freezer_temperature_recovery_grace', 'on')
|
||||
and (states('sensor.downstairs_freezer_temperature_x62ts_temperature') | float(0)) > threshold
|
||||
and (states('sensor.downstairs_freezer_temperature_x70ts_temperature') | float(0)) > threshold
|
||||
)
|
||||
or states('switch.downstairs_fridge_power_x41pp') != 'on'
|
||||
or power_missing
|
||||
or is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on')
|
||||
}}
|
||||
@@ -733,21 +739,23 @@ template:
|
||||
appliance: "Downstairs Freezer"
|
||||
issues: >-
|
||||
{% set ns = namespace(items=[]) %}
|
||||
{% set temperature_missing = not has_value('sensor.downstairs_freezer_temperature_x62ts_temperature') %}
|
||||
{% set battery_missing = not has_value('sensor.downstairs_freezer_temperature_x62ts_battery') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_power_x41pp_power') %}
|
||||
{% set temperature_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_temperature') %}
|
||||
{% set battery_missing = not has_value('sensor.downstairs_freezer_temperature_x70ts_battery') %}
|
||||
{% set illuminance_missing = not has_value('sensor.downstairs_freezer_light_sensor_x61ls_illuminance') %}
|
||||
{% set power_missing = not has_value('sensor.downstairs_fridge_gpo_power_x68pm_power') %}
|
||||
{% set percentile = states('sensor.downstairs_freezer_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
|
||||
{% if temperature_missing or battery_missing %}
|
||||
{% set ns.items = ns.items + ['Monitor offline'] %}
|
||||
{% if temperature_missing %}
|
||||
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
|
||||
{% endif %}
|
||||
{% if not battery_missing and (states('sensor.downstairs_freezer_temperature_x62ts_battery') | float(-1)) <= 20 %}
|
||||
{% if illuminance_missing %}
|
||||
{% set ns.items = ns.items + ['Door monitor unavailable'] %}
|
||||
{% endif %}
|
||||
{% if not battery_missing and (states('sensor.downstairs_freezer_temperature_x70ts_battery') | float(-1)) <= 20 %}
|
||||
{% set ns.items = ns.items + ['Low monitor battery'] %}
|
||||
{% endif %}
|
||||
{% if states('switch.downstairs_fridge_power_x41pp') in ['unknown', 'unavailable'] or power_missing %}
|
||||
{% if power_missing %}
|
||||
{% set ns.items = ns.items + ['Shared power monitoring unavailable'] %}
|
||||
{% elif not is_state('switch.downstairs_fridge_power_x41pp', 'on') %}
|
||||
{% set ns.items = ns.items + ['Shared power switched off'] %}
|
||||
{% elif is_state('binary_sensor.downstairs_fridge_power_draw_lost', 'on') %}
|
||||
{% set ns.items = ns.items + ['Shared power lost - no power draw for 4 hours'] %}
|
||||
{% endif %}
|
||||
@@ -755,7 +763,7 @@ template:
|
||||
{% set ns.items = ns.items + ['Door open too long'] %}
|
||||
{% elif not temperature_missing and is_state('binary_sensor.downstairs_freezer_temperature_recovery_grace', 'on') %}
|
||||
{% set ns.items = ns.items + ['Temperature alert delayed - door recently open'] %}
|
||||
{% elif not temperature_missing and (states('sensor.downstairs_freezer_temperature_x62ts_temperature') | float(0)) > threshold %}
|
||||
{% elif not temperature_missing and (states('sensor.downstairs_freezer_temperature_x70ts_temperature') | float(0)) > threshold %}
|
||||
{% if (states('sensor.downstairs_freezer_temperature_change_rate') | float(0)) >= 2 %}
|
||||
{% set ns.items = ns.items + ['Warming rapidly - possible open door'] %}
|
||||
{% else %}
|
||||
@@ -763,15 +771,15 @@ template:
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{{ ns.items }}
|
||||
temperature: "{{ states('sensor.downstairs_freezer_temperature_x62ts_temperature') }}"
|
||||
humidity: "{{ states('sensor.downstairs_freezer_temperature_x62ts_humidity') }}"
|
||||
temperature: "{{ states('sensor.downstairs_freezer_temperature_x70ts_temperature') }}"
|
||||
humidity: "{{ states('sensor.downstairs_freezer_temperature_x70ts_humidity') }}"
|
||||
average_7_days: "{{ states('sensor.downstairs_freezer_temperature_average_7_days') }}"
|
||||
alert_threshold: >-
|
||||
{% set percentile = states('sensor.downstairs_freezer_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{{ [-5, percentile + 0.5] | min if percentile is not none else -5 }}
|
||||
change_rate: "{{ states('sensor.downstairs_freezer_temperature_change_rate') }}"
|
||||
battery: "{{ states('sensor.downstairs_freezer_temperature_x62ts_battery') }}"
|
||||
power: "{{ states('sensor.downstairs_fridge_power_x41pp_power') }}"
|
||||
battery: "{{ states('sensor.downstairs_freezer_temperature_x70ts_battery') }}"
|
||||
power: "{{ states('sensor.downstairs_fridge_gpo_power_x68pm_power') }}"
|
||||
door_open: "{{ is_state('binary_sensor.downstairs_freezer_door_open', 'on') }}"
|
||||
illuminance: "{{ states('sensor.downstairs_freezer_light_sensor_x61ls_illuminance') }}"
|
||||
|
||||
@@ -787,7 +795,6 @@ template:
|
||||
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
|
||||
{{
|
||||
temperature_missing
|
||||
or battery_missing
|
||||
or (states('sensor.drinks_freezer_environment_lcd_btt02_battery') | float(-1)) <= 20
|
||||
or states('switch.drinks_fridge_power_x59pm') != 'on'
|
||||
or power_missing
|
||||
@@ -803,8 +810,8 @@ template:
|
||||
{% set power_missing = not has_value('sensor.drinks_fridge_power_x59pm_power') %}
|
||||
{% set percentile = states('sensor.drinks_freezer_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{% set threshold = [-5, percentile + 0.5] | min if percentile is not none else -5 %}
|
||||
{% if temperature_missing or battery_missing %}
|
||||
{% set ns.items = ns.items + ['Monitor offline'] %}
|
||||
{% if temperature_missing %}
|
||||
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
|
||||
{% endif %}
|
||||
{% if not battery_missing and (states('sensor.drinks_freezer_environment_lcd_btt02_battery') | float(-1)) <= 20 %}
|
||||
{% set ns.items = ns.items + ['Low monitor battery'] %}
|
||||
@@ -845,7 +852,6 @@ template:
|
||||
{% set threshold = [-10, percentile + 6] | min if percentile is not none else -10 %}
|
||||
{{
|
||||
temperature_missing
|
||||
or battery_missing
|
||||
or (states('sensor.lcd_temp_humidity_btt03_battery') | float(-1)) <= 20
|
||||
or states('switch.vertical_freezer_power_x60pm') != 'on'
|
||||
or power_missing
|
||||
@@ -861,8 +867,8 @@ template:
|
||||
{% set power_missing = not has_value('sensor.vertical_freezer_power_x60pm_power') %}
|
||||
{% set percentile = states('sensor.vertical_freezer_temperature_95th_percentile_7_days') | float(none) %}
|
||||
{% set threshold = [-10, percentile + 6] | min if percentile is not none else -10 %}
|
||||
{% if temperature_missing or battery_missing %}
|
||||
{% set ns.items = ns.items + ['Monitor offline'] %}
|
||||
{% if temperature_missing %}
|
||||
{% set ns.items = ns.items + ['Temperature monitor unavailable'] %}
|
||||
{% endif %}
|
||||
{% if not battery_missing and (states('sensor.lcd_temp_humidity_btt03_battery') | float(-1)) <= 20 %}
|
||||
{% set ns.items = ns.items + ['Low monitor battery'] %}
|
||||
|
||||
@@ -9,9 +9,12 @@
|
||||
# packages/garage_corner_light_cctv_motion.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.0 2026-06-29
|
||||
# V1.1 2026-08-31
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.1 2026-08-31
|
||||
# - Restrict CCTV motion activation to one hour before sunset through one hour after sunrise.
|
||||
#
|
||||
# V1.0 2026-06-29
|
||||
# - Initial package.
|
||||
# - Turns the garage external corner light on when CCTV motion MQTT payload "1" is received.
|
||||
@@ -20,7 +23,8 @@
|
||||
# - Adds a Home Assistant enable switch for CCTV movement triggers.
|
||||
#
|
||||
# PURPOSE:
|
||||
# Turns on the garage external corner light from selected CCTV motion MQTT triggers.
|
||||
# Turns on the garage external corner light from selected CCTV motion MQTT triggers
|
||||
# during the configured night window.
|
||||
#
|
||||
# NOTES:
|
||||
# - The light is:
|
||||
@@ -31,6 +35,7 @@
|
||||
#
|
||||
# - Turning OFF "Garage corner light movement triggers" prevents new CCTV triggers.
|
||||
# - If a timer is already running, it will still finish and turn the light off.
|
||||
# - CCTV triggers run from one hour before sunset until one hour after sunrise.
|
||||
#
|
||||
#:########################################################################################:#
|
||||
# User Configuration #
|
||||
@@ -91,6 +96,12 @@ automation:
|
||||
entity_id: input_boolean.garage_corner_light_movement_triggers
|
||||
state: "on"
|
||||
|
||||
- condition: sun
|
||||
after: sunset
|
||||
after_offset: "-01:00:00"
|
||||
before: sunrise
|
||||
before_offset: "01:00:00"
|
||||
|
||||
action:
|
||||
- service: switch.turn_on
|
||||
target:
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# jobs_tracker_appliance_completion_triggers.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.0 2026-08-15
|
||||
# V1.1 2026-09-03
|
||||
#
|
||||
# PURPOSE:
|
||||
# Provides time-qualified appliance door and lid triggers for Jobs Tracker completion.
|
||||
@@ -19,9 +19,13 @@
|
||||
#
|
||||
# OPERATION:
|
||||
# Each contact must remain open for five seconds before its corresponding Jobs Tracker
|
||||
# completion route is called. The job registry owns the completion entity mappings.
|
||||
# completion route is called. Starting the dryer or washer clears only a previous Due
|
||||
# unload job, so the next finished cycle creates its own new unload task.
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.1 2026-09-03
|
||||
# - Clear a pending dryer or washer unload job when its next cycle starts.
|
||||
#
|
||||
# V1.0 2026-08-15
|
||||
# - Added five-second door and lid open completion triggers for dryer and washer jobs.
|
||||
#
|
||||
@@ -63,3 +67,43 @@ automation:
|
||||
data:
|
||||
completion_entity: binary_sensor.washing_machine_lid_status_x39rs_contact
|
||||
completion_to_state: "on"
|
||||
|
||||
- id: jobs_tracker_clear_dryer_unload_on_start
|
||||
alias: "Jobs Tracker - Clear Dryer Unload on Start"
|
||||
description: "Clears an outstanding Empty the Dryer job when a new dryer cycle starts."
|
||||
mode: single
|
||||
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: sensor.appliance_monitor_dryer_monitor
|
||||
to: Operating
|
||||
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: sensor.jobs_tracker_empty_dryer
|
||||
state: Due
|
||||
|
||||
actions:
|
||||
- action: script.jobs_tracker_dispatch
|
||||
data:
|
||||
job_id: empty_dryer
|
||||
|
||||
- id: jobs_tracker_clear_washer_unload_on_start
|
||||
alias: "Jobs Tracker - Clear Washer Unload on Start"
|
||||
description: "Clears an outstanding Empty the Washer job when a new washer cycle starts."
|
||||
mode: single
|
||||
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: sensor.appliance_monitor_washing_machine_monitor
|
||||
to: Operating
|
||||
|
||||
conditions:
|
||||
- condition: state
|
||||
entity_id: sensor.jobs_tracker_empty_washing_machine
|
||||
state: Due
|
||||
|
||||
actions:
|
||||
- action: script.jobs_tracker_dispatch
|
||||
data:
|
||||
job_id: empty_washing_machine
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#:########################################################################################:#
|
||||
# Jobs Tracker Appliance Completion Triggers Package #
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# TITLE:
|
||||
# Jobs Tracker Appliance Completion Triggers
|
||||
#
|
||||
# FILE:
|
||||
# jobs_tracker_appliance_completion_triggers.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.0 2026-08-15
|
||||
#
|
||||
# PURPOSE:
|
||||
# Provides time-qualified appliance door and lid triggers for Jobs Tracker completion.
|
||||
#
|
||||
# DEPENDS ON:
|
||||
# packages/Job_Chore_Tracking/jobs_tracker_jobs.yaml V3.5 or newer.
|
||||
#
|
||||
# OPERATION:
|
||||
# Each contact must remain open for five seconds before its corresponding Jobs Tracker
|
||||
# completion route is called. The job registry owns the completion entity mappings.
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.0 2026-08-15
|
||||
# - Added five-second door and lid open completion triggers for dryer and washer jobs.
|
||||
#
|
||||
#:########################################################################################:#
|
||||
|
||||
automation:
|
||||
- id: jobs_tracker_empty_dryer_door_open
|
||||
alias: "Jobs Tracker - Empty Dryer on Door Open"
|
||||
description: "Marks Empty the Dryer complete after the dryer door is open for five seconds."
|
||||
mode: single
|
||||
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: binary_sensor.dryer_door_status_x34rs_contact
|
||||
to: "on"
|
||||
for:
|
||||
seconds: 5
|
||||
|
||||
actions:
|
||||
- action: script.jobs_tracker_route_completion
|
||||
data:
|
||||
completion_entity: binary_sensor.dryer_door_status_x34rs_contact
|
||||
completion_to_state: "on"
|
||||
|
||||
- id: jobs_tracker_empty_washing_machine_lid_open
|
||||
alias: "Jobs Tracker - Empty Washer on Lid Open"
|
||||
description: "Marks Empty the Washer complete after the washer lid is open for five seconds."
|
||||
mode: single
|
||||
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: binary_sensor.washing_machine_lid_status_x39rs_contact
|
||||
to: "on"
|
||||
for:
|
||||
seconds: 5
|
||||
|
||||
actions:
|
||||
- action: script.jobs_tracker_route_completion
|
||||
data:
|
||||
completion_entity: binary_sensor.washing_machine_lid_status_x39rs_contact
|
||||
completion_to_state: "on"
|
||||
@@ -635,8 +635,11 @@ script:
|
||||
entity_id: input_datetime.outdoor_lighting_number_16_last_schedule_event
|
||||
data:
|
||||
datetime: "{{ (selected_event_ts | int(0)) | timestamp_custom('%Y-%m-%d %H:%M:%S', true) }}"
|
||||
- action: script.outdoor_lighting_ramp_number_16
|
||||
- action: script.turn_on
|
||||
target:
|
||||
entity_id: script.outdoor_lighting_ramp_number_16
|
||||
data:
|
||||
variables:
|
||||
target_brightness: "{{ selected_target | int(0) }}"
|
||||
ramp_seconds: "{{ ramp_to_use | int(0) }}"
|
||||
|
||||
@@ -787,8 +790,11 @@ script:
|
||||
entity_id: input_datetime.outdoor_lighting_main_entrance_last_schedule_event
|
||||
data:
|
||||
datetime: "{{ (selected_event_ts | int(0)) | timestamp_custom('%Y-%m-%d %H:%M:%S', true) }}"
|
||||
- action: script.outdoor_lighting_ramp_main_entrance
|
||||
- action: script.turn_on
|
||||
target:
|
||||
entity_id: script.outdoor_lighting_ramp_main_entrance
|
||||
data:
|
||||
variables:
|
||||
target_brightness: "{{ selected_target | int(0) }}"
|
||||
ramp_seconds: "{{ ramp_to_use | int(0) }}"
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#:########################################################################################:#
|
||||
# Package: Pet Feeding and Jobs Timing
|
||||
# File: pet_feeding_and_jobs.yaml
|
||||
# Version: v1.4.0
|
||||
# Date: 2026-07-26
|
||||
# Version: v1.5.2
|
||||
# Date: 2026-09-09
|
||||
#
|
||||
# Purpose:
|
||||
# Provides legacy MQTT pet activity sensors and Jobs-derived timing sensors for
|
||||
@@ -17,6 +17,11 @@
|
||||
# instead of exposing a numeric sentinel value.
|
||||
#
|
||||
# Version History:
|
||||
# - v1.5.2 (2026-09-12): Ignore stale restored dog-button event states so
|
||||
# reconnects cannot create false timestamps or visual feedback.
|
||||
# - v1.5.1 (2026-09-09): Extended dog-button feedback intervals to 500 ms.
|
||||
# - v1.5.0 (2026-09-09): Added visual feedback flashes for physical dog
|
||||
# completion buttons, using the Lounge outside light relay.
|
||||
# - v1.4.0 (2026-07-26): Announce four physical job completions on the Sony
|
||||
# lounge TV and both Pushover devices.
|
||||
# - v1.3.0 (2026-07-26): Restore retained dog-fed and jobs-done activity
|
||||
@@ -122,7 +127,12 @@ automation:
|
||||
conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}
|
||||
{% set valid_state = trigger.to_state is not none
|
||||
and trigger.to_state.state not in ['unknown', 'unavailable'] %}
|
||||
{% set event_ts = as_timestamp(trigger.to_state.state, 0)
|
||||
if valid_state else 0 %}
|
||||
{% set event_age = as_timestamp(now()) - event_ts %}
|
||||
{{ valid_state and event_ts > 0 and event_age >= 0 and event_age <= 30 }}
|
||||
actions:
|
||||
- action: input_datetime.set_datetime
|
||||
target:
|
||||
@@ -145,7 +155,12 @@ automation:
|
||||
conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}
|
||||
{% set valid_state = trigger.to_state is not none
|
||||
and trigger.to_state.state not in ['unknown', 'unavailable'] %}
|
||||
{% set event_ts = as_timestamp(trigger.to_state.state, 0)
|
||||
if valid_state else 0 %}
|
||||
{% set event_age = as_timestamp(now()) - event_ts %}
|
||||
{{ valid_state and event_ts > 0 and event_age >= 0 and event_age <= 30 }}
|
||||
actions:
|
||||
- action: input_datetime.set_datetime
|
||||
target:
|
||||
@@ -227,3 +242,64 @@ automation:
|
||||
title: "Jobs Announcement"
|
||||
short_announcement: "{{ completion_message }}"
|
||||
long_announcement: "{{ completion_message }}"
|
||||
|
||||
#:######################################################################################:#
|
||||
# AUTOMATION: Physical Dog-Button Visual Feedback
|
||||
#:######################################################################################:#
|
||||
- id: dog_button_visual_feedback
|
||||
alias: "Jobs - Dog Button Visual Feedback"
|
||||
description: >-
|
||||
Flashes the Lounge outside light relay for one physical single-press,
|
||||
preserving its original state after dog feeding or depooping is recorded.
|
||||
mode: queued
|
||||
max: 10
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id:
|
||||
- event.jobs_dog_fed_button_x14bt_action
|
||||
- event.jobs_dog_depooped_button_x15bt_action
|
||||
conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{% set valid_state = trigger.to_state is not none
|
||||
and trigger.to_state.state not in ['unknown', 'unavailable'] %}
|
||||
{% set event_ts = as_timestamp(trigger.to_state.state, 0)
|
||||
if valid_state else 0 %}
|
||||
{% set event_age = as_timestamp(now()) - event_ts %}
|
||||
{{
|
||||
valid_state
|
||||
and event_ts > 0
|
||||
and event_age >= 0
|
||||
and event_age <= 30
|
||||
and trigger.to_state.attributes.event_type == 'single'
|
||||
}}
|
||||
actions:
|
||||
- variables:
|
||||
initial_state: "{{ states('switch.esp_loungesouthleftswitch_relay_2_outside_light_1') }}"
|
||||
flash_count: >-
|
||||
{{ 2 if trigger.entity_id == 'event.jobs_dog_fed_button_x14bt_action' else 3 }}
|
||||
- repeat:
|
||||
count: "{{ flash_count | int }}"
|
||||
sequence:
|
||||
- choose:
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ initial_state == 'off' }}"
|
||||
sequence:
|
||||
- action: switch.turn_on
|
||||
target:
|
||||
entity_id: switch.esp_loungesouthleftswitch_relay_2_outside_light_1
|
||||
- delay: "00:00:00.500"
|
||||
- action: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.esp_loungesouthleftswitch_relay_2_outside_light_1
|
||||
- delay: "00:00:00.500"
|
||||
default:
|
||||
- action: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.esp_loungesouthleftswitch_relay_2_outside_light_1
|
||||
- delay: "00:00:00.500"
|
||||
- action: switch.turn_on
|
||||
target:
|
||||
entity_id: switch.esp_loungesouthleftswitch_relay_2_outside_light_1
|
||||
- delay: "00:00:00.500"
|
||||
|
||||
@@ -9,42 +9,24 @@
|
||||
# quiet_time_on_off_actions.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.2 2026-06-20
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.2 2026-06-20
|
||||
# - Added Quiet Time OFF action to change OpenHASP panel openhasp_1
|
||||
# back to page 1.
|
||||
#
|
||||
# V1.1 2026-06-15
|
||||
# - Added separate Quiet Time ON and Quiet Time OFF action sections.
|
||||
# - Added support for non-binary Quiet Time OFF actions.
|
||||
# - Sets input_number.openhasp_1_backlight_level to 200 when Quiet Time ends.
|
||||
#
|
||||
# V1.0 2026-06-15
|
||||
# - Initial standalone package split out from the main Quiet Time package.
|
||||
# - Turns selected entities on/off when input_boolean.quiet_time changes.
|
||||
# V1.3 2026-09-04
|
||||
#
|
||||
# PURPOSE:
|
||||
# Runs local Home Assistant actions when Quiet Time is turned ON or OFF.
|
||||
#
|
||||
# The main Quiet Time package should continue to own:
|
||||
# - input_boolean.quiet_time
|
||||
# - daily reset behaviour
|
||||
# - MQTT quiet_time state publishing
|
||||
# The main Quiet Time package owns the helper, daily reset behaviour, and MQTT
|
||||
# publishing. This package owns extra local Quiet Time actions.
|
||||
#
|
||||
# This package only handles extra local actions that should happen when
|
||||
# Quiet Time starts or ends.
|
||||
# VERSION HISTORY:
|
||||
# V1.3 2026-09-04
|
||||
# - Disables Flounder Motion Wake during Quiet Time and requests a one-off
|
||||
# 10-second presence fade to Screen Off.
|
||||
# - Restores Flounder Motion Wake when Quiet Time ends.
|
||||
#
|
||||
# EDITING NOTES:
|
||||
# - Add normal on/off entities to the relevant entity lists.
|
||||
# - Empty lists are fine and will simply do nothing.
|
||||
# - Use the "Other Quiet Time OFF Actions" section for things that are not
|
||||
# simple on/off actions, such as setting input_numbers, selects, scenes,
|
||||
# scripts, MQTT commands, or custom service calls.
|
||||
# V1.2 2026-06-20
|
||||
# - Added Quiet Time OFF action to change OpenHASP panel openhasp_1 back to
|
||||
# page 1.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# AUTOMATIONS
|
||||
################################################################################
|
||||
@@ -56,56 +38,15 @@ automation:
|
||||
mode: single
|
||||
|
||||
variables:
|
||||
##########################################################################
|
||||
# QUIET TIME ON ACTION LISTS
|
||||
##########################################################################
|
||||
#
|
||||
# These actions run when input_boolean.quiet_time changes to "on".
|
||||
#
|
||||
|
||||
quiet_time_on_turn_off_entities:
|
||||
- light.led_matrix_display_led_matrix_display_display
|
||||
|
||||
quiet_time_on_turn_on_entities: []
|
||||
|
||||
##########################################################################
|
||||
# QUIET TIME OFF ACTION LISTS
|
||||
##########################################################################
|
||||
#
|
||||
# These actions run when input_boolean.quiet_time changes to "off".
|
||||
#
|
||||
|
||||
quiet_time_off_turn_off_entities: []
|
||||
|
||||
quiet_time_off_turn_on_entities:
|
||||
- light.led_matrix_display_led_matrix_display_display
|
||||
|
||||
##########################################################################
|
||||
# OTHER QUIET TIME OFF ACTION VALUES
|
||||
##########################################################################
|
||||
#
|
||||
# Use this list for input_number helpers that should be set when Quiet Time
|
||||
# ends.
|
||||
#
|
||||
# Format:
|
||||
# - entity_id: input_number.some_helper
|
||||
# value: 123
|
||||
#
|
||||
|
||||
quiet_time_off_input_number_values:
|
||||
- entity_id: input_number.openhasp_1_backlight_level
|
||||
value: 200
|
||||
|
||||
##########################################################################
|
||||
# OPENHASP QUIET TIME OFF PAGE ACTION
|
||||
##########################################################################
|
||||
#
|
||||
# Sends the OpenHASP panel back to the main page when Quiet Time ends.
|
||||
#
|
||||
# Current OpenHASP MQTT command topic:
|
||||
# hasp/openhasp_1/command/page
|
||||
#
|
||||
|
||||
quiet_time_off_openhasp_page_topic: "hasp/openhasp_1/command/page"
|
||||
quiet_time_off_openhasp_page: 1
|
||||
|
||||
@@ -121,13 +62,6 @@ automation:
|
||||
|
||||
actions:
|
||||
- choose:
|
||||
######################################################################
|
||||
# QUIET TIME ON ACTIONS
|
||||
######################################################################
|
||||
#
|
||||
# Runs when Quiet Time starts.
|
||||
#
|
||||
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.to_state.state == 'on' }}"
|
||||
@@ -138,47 +72,44 @@ automation:
|
||||
- action: homeassistant.turn_off
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_on_turn_on_entities }}"
|
||||
sequence:
|
||||
- action: homeassistant.turn_on
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
######################################################################
|
||||
# QUIET TIME OFF ACTIONS
|
||||
######################################################################
|
||||
#
|
||||
# Runs when Quiet Time ends.
|
||||
#
|
||||
|
||||
# Stop camera motion from extending presence, then fade the
|
||||
# current session to the existing Screen Off base state.
|
||||
- action: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.flounder_kiosk_motion_wake
|
||||
- wait_template: "{{ is_state('switch.flounder_kiosk_motion_wake', 'off') }}"
|
||||
timeout: "00:00:10"
|
||||
continue_on_timeout: true
|
||||
- action: mqtt.publish
|
||||
data:
|
||||
topic: "viewroad-commands/flounder/presence/end"
|
||||
payload: "10"
|
||||
retain: false
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.to_state.state == 'off' }}"
|
||||
sequence:
|
||||
##################################################################
|
||||
# Quiet Time OFF - binary/entity actions
|
||||
##################################################################
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_off_turn_off_entities }}"
|
||||
sequence:
|
||||
- action: homeassistant.turn_off
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_off_turn_on_entities }}"
|
||||
sequence:
|
||||
- action: homeassistant.turn_on
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
##################################################################
|
||||
# Quiet Time OFF - input_number set actions
|
||||
##################################################################
|
||||
|
||||
- action: switch.turn_on
|
||||
target:
|
||||
entity_id: switch.flounder_kiosk_motion_wake
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_off_input_number_values }}"
|
||||
sequence:
|
||||
@@ -187,34 +118,8 @@ automation:
|
||||
entity_id: "{{ repeat.item.entity_id }}"
|
||||
data:
|
||||
value: "{{ repeat.item.value | float }}"
|
||||
|
||||
##################################################################
|
||||
# Quiet Time OFF - OpenHASP page action
|
||||
##################################################################
|
||||
#
|
||||
# Change OpenHASP panel back to page 1 when Quiet Time ends.
|
||||
#
|
||||
|
||||
- action: mqtt.publish
|
||||
data:
|
||||
topic: "{{ quiet_time_off_openhasp_page_topic }}"
|
||||
payload: "{{ quiet_time_off_openhasp_page | int }}"
|
||||
retain: false
|
||||
|
||||
##################################################################
|
||||
# Quiet Time OFF - other custom actions
|
||||
##################################################################
|
||||
#
|
||||
# Add any extra non-binary service calls here later.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# - action: script.some_script
|
||||
#
|
||||
# - action: select.select_option
|
||||
# target:
|
||||
# entity_id: select.some_select
|
||||
# data:
|
||||
# option: "Some Option"
|
||||
#
|
||||
##################################################################
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
################################################################################
|
||||
# Quiet Time On / Off Actions Package
|
||||
################################################################################
|
||||
#
|
||||
# TITLE:
|
||||
# Quiet Time On / Off Actions
|
||||
#
|
||||
# FILE:
|
||||
# quiet_time_on_off_actions.yaml
|
||||
#
|
||||
# VERSION:
|
||||
# V1.3 2026-09-04
|
||||
# - Disables Flounder Motion Wake during Quiet Time and requests a one-off
|
||||
# 10-second presence fade to Screen Off.
|
||||
# - Restores Flounder Motion Wake when Quiet Time ends.
|
||||
#
|
||||
# V1.2 2026-06-20
|
||||
#
|
||||
# VERSION HISTORY:
|
||||
# V1.2 2026-06-20
|
||||
# - Added Quiet Time OFF action to change OpenHASP panel openhasp_1
|
||||
# back to page 1.
|
||||
#
|
||||
# V1.1 2026-06-15
|
||||
# - Added separate Quiet Time ON and Quiet Time OFF action sections.
|
||||
# - Added support for non-binary Quiet Time OFF actions.
|
||||
# - Sets input_number.openhasp_1_backlight_level to 200 when Quiet Time ends.
|
||||
#
|
||||
# V1.0 2026-06-15
|
||||
# - Initial standalone package split out from the main Quiet Time package.
|
||||
# - Turns selected entities on/off when input_boolean.quiet_time changes.
|
||||
#
|
||||
# PURPOSE:
|
||||
# Runs local Home Assistant actions when Quiet Time is turned ON or OFF.
|
||||
#
|
||||
# The main Quiet Time package should continue to own:
|
||||
# - input_boolean.quiet_time
|
||||
# - daily reset behaviour
|
||||
# - MQTT quiet_time state publishing
|
||||
#
|
||||
# This package only handles extra local actions that should happen when
|
||||
# Quiet Time starts or ends.
|
||||
#
|
||||
# EDITING NOTES:
|
||||
# - Add normal on/off entities to the relevant entity lists.
|
||||
# - Empty lists are fine and will simply do nothing.
|
||||
# - Use the "Other Quiet Time OFF Actions" section for things that are not
|
||||
# simple on/off actions, such as setting input_numbers, selects, scenes,
|
||||
# scripts, MQTT commands, or custom service calls.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# AUTOMATIONS
|
||||
################################################################################
|
||||
|
||||
automation:
|
||||
- id: quiet_time_state_change_actions
|
||||
alias: "Quiet Time - State Change Actions"
|
||||
description: "Runs configured Home Assistant actions when Quiet Time is turned on or off."
|
||||
mode: single
|
||||
|
||||
variables:
|
||||
##########################################################################
|
||||
# QUIET TIME ON ACTION LISTS
|
||||
##########################################################################
|
||||
#
|
||||
# These actions run when input_boolean.quiet_time changes to "on".
|
||||
#
|
||||
|
||||
quiet_time_on_turn_off_entities:
|
||||
- light.led_matrix_display_led_matrix_display_display
|
||||
|
||||
quiet_time_on_turn_on_entities: []
|
||||
|
||||
##########################################################################
|
||||
# QUIET TIME OFF ACTION LISTS
|
||||
##########################################################################
|
||||
#
|
||||
# These actions run when input_boolean.quiet_time changes to "off".
|
||||
#
|
||||
|
||||
quiet_time_off_turn_off_entities: []
|
||||
|
||||
quiet_time_off_turn_on_entities:
|
||||
- light.led_matrix_display_led_matrix_display_display
|
||||
|
||||
##########################################################################
|
||||
# OTHER QUIET TIME OFF ACTION VALUES
|
||||
##########################################################################
|
||||
#
|
||||
# Use this list for input_number helpers that should be set when Quiet Time
|
||||
# ends.
|
||||
#
|
||||
# Format:
|
||||
# - entity_id: input_number.some_helper
|
||||
# value: 123
|
||||
#
|
||||
|
||||
quiet_time_off_input_number_values:
|
||||
- entity_id: input_number.openhasp_1_backlight_level
|
||||
value: 200
|
||||
|
||||
##########################################################################
|
||||
# OPENHASP QUIET TIME OFF PAGE ACTION
|
||||
##########################################################################
|
||||
#
|
||||
# Sends the OpenHASP panel back to the main page when Quiet Time ends.
|
||||
#
|
||||
# Current OpenHASP MQTT command topic:
|
||||
# hasp/openhasp_1/command/page
|
||||
#
|
||||
|
||||
quiet_time_off_openhasp_page_topic: "hasp/openhasp_1/command/page"
|
||||
quiet_time_off_openhasp_page: 1
|
||||
|
||||
triggers:
|
||||
- trigger: state
|
||||
entity_id: input_boolean.quiet_time
|
||||
from:
|
||||
- "on"
|
||||
- "off"
|
||||
to:
|
||||
- "on"
|
||||
- "off"
|
||||
|
||||
actions:
|
||||
- choose:
|
||||
######################################################################
|
||||
# QUIET TIME ON ACTIONS
|
||||
######################################################################
|
||||
#
|
||||
# Runs when Quiet Time starts.
|
||||
#
|
||||
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.to_state.state == 'on' }}"
|
||||
sequence:
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_on_turn_off_entities }}"
|
||||
sequence:
|
||||
- action: homeassistant.turn_off
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_on_turn_on_entities }}"
|
||||
sequence:
|
||||
- action: homeassistant.turn_on
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
# Stop camera motion from extending presence, then fade the
|
||||
# current session to the existing Screen Off base state.
|
||||
- action: switch.turn_off
|
||||
target:
|
||||
entity_id: switch.flounder_kiosk_motion_wake
|
||||
|
||||
- wait_template: "{{ is_state('switch.flounder_kiosk_motion_wake', 'off') }}"
|
||||
timeout: "00:00:10"
|
||||
continue_on_timeout: true
|
||||
|
||||
- action: mqtt.publish
|
||||
data:
|
||||
topic: "viewroad-commands/flounder/presence/end"
|
||||
payload: "10"
|
||||
retain: false
|
||||
|
||||
######################################################################
|
||||
# QUIET TIME OFF ACTIONS
|
||||
######################################################################
|
||||
#
|
||||
# Runs when Quiet Time ends.
|
||||
#
|
||||
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.to_state.state == 'off' }}"
|
||||
sequence:
|
||||
##################################################################
|
||||
# Quiet Time OFF - binary/entity actions
|
||||
##################################################################
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_off_turn_off_entities }}"
|
||||
sequence:
|
||||
- action: homeassistant.turn_off
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_off_turn_on_entities }}"
|
||||
sequence:
|
||||
- action: homeassistant.turn_on
|
||||
target:
|
||||
entity_id: "{{ repeat.item }}"
|
||||
|
||||
- action: switch.turn_on
|
||||
target:
|
||||
entity_id: switch.flounder_kiosk_motion_wake
|
||||
|
||||
##################################################################
|
||||
# Quiet Time OFF - input_number set actions
|
||||
##################################################################
|
||||
|
||||
- repeat:
|
||||
for_each: "{{ quiet_time_off_input_number_values }}"
|
||||
sequence:
|
||||
- action: input_number.set_value
|
||||
target:
|
||||
entity_id: "{{ repeat.item.entity_id }}"
|
||||
data:
|
||||
value: "{{ repeat.item.value | float }}"
|
||||
|
||||
##################################################################
|
||||
# Quiet Time OFF - OpenHASP page action
|
||||
##################################################################
|
||||
#
|
||||
# Change OpenHASP panel back to page 1 when Quiet Time ends.
|
||||
#
|
||||
|
||||
- action: mqtt.publish
|
||||
data:
|
||||
topic: "{{ quiet_time_off_openhasp_page_topic }}"
|
||||
payload: "{{ quiet_time_off_openhasp_page | int }}"
|
||||
retain: false
|
||||
|
||||
##################################################################
|
||||
# Quiet Time OFF - other custom actions
|
||||
##################################################################
|
||||
#
|
||||
# Add any extra non-binary service calls here later.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# - action: script.some_script
|
||||
#
|
||||
# - action: select.select_option
|
||||
# target:
|
||||
# entity_id: select.some_select
|
||||
# data:
|
||||
# option: "Some Option"
|
||||
#
|
||||
##################################################################
|
||||
@@ -0,0 +1,164 @@
|
||||
#:########################################################################################:#
|
||||
# View Road Smoke Alarm RF Package - V1.2.0 #
|
||||
#:########################################################################################:#
|
||||
# Receives normalized AJ-765 RF state from the decoder running on beaver. #
|
||||
# #
|
||||
# V1.2 performs early RF fingerprint classification, normally shortly after RF activity. #
|
||||
# #
|
||||
# Current RF fingerprints: #
|
||||
# - detector_test : TEST button transmission from a detector #
|
||||
# - remote_test : TEST transmission matching the remote capture #
|
||||
# - remote_hush : HUSH/LOCATE button on the Goldair remote #
|
||||
# - smoke_alarm : Experimental only - not yet considered authoritative #
|
||||
# #
|
||||
# Individual detector identity has NOT been found in the RF protocol. #
|
||||
#:########################################################################################:#
|
||||
|
||||
|
||||
mqtt:
|
||||
|
||||
- binary_sensor:
|
||||
name: "RF Interconnect"
|
||||
unique_id: view_road_smoke_alarm_rf_interconnect
|
||||
default_entity_id: binary_sensor.smoke_alarm_rf_interconnect
|
||||
|
||||
state_topic: "viewroad-status/smokealarms/rf/interconnect"
|
||||
payload_on: "ON"
|
||||
payload_off: "OFF"
|
||||
|
||||
availability_topic: "viewroad-status/smokealarms/rf/availability"
|
||||
payload_available: "online"
|
||||
payload_not_available: "offline"
|
||||
|
||||
icon: mdi:radio-tower
|
||||
|
||||
device:
|
||||
identifiers:
|
||||
- view_road_smoke_alarm_rf
|
||||
name: "Smoke Alarm RF Monitor"
|
||||
manufacturer: "Zorruno"
|
||||
model: "AJ-765 RF Monitor"
|
||||
sw_version: "1.2.0"
|
||||
|
||||
|
||||
- event:
|
||||
name: "RF Event"
|
||||
unique_id: view_road_smoke_alarm_rf_event
|
||||
default_entity_id: event.smoke_alarm_rf_event
|
||||
|
||||
state_topic: "viewroad-status/smokealarms/rf/event"
|
||||
|
||||
event_types:
|
||||
- interconnect_start
|
||||
- detector_test
|
||||
- remote_test
|
||||
- remote_hush
|
||||
- smoke_alarm
|
||||
- unknown_aj765
|
||||
- interconnect_end
|
||||
|
||||
availability_topic: "viewroad-status/smokealarms/rf/availability"
|
||||
payload_available: "online"
|
||||
payload_not_available: "offline"
|
||||
|
||||
icon: mdi:radio-tower
|
||||
|
||||
device:
|
||||
identifiers:
|
||||
- view_road_smoke_alarm_rf
|
||||
|
||||
|
||||
- sensor:
|
||||
name: "RF Current Type"
|
||||
unique_id: view_road_smoke_alarm_rf_current_type
|
||||
default_entity_id: sensor.smoke_alarm_rf_current_type
|
||||
|
||||
state_topic: "viewroad-status/smokealarms/rf/current_type"
|
||||
|
||||
availability_topic: "viewroad-status/smokealarms/rf/availability"
|
||||
payload_available: "online"
|
||||
payload_not_available: "offline"
|
||||
|
||||
icon: mdi:waveform
|
||||
|
||||
device:
|
||||
identifiers:
|
||||
- view_road_smoke_alarm_rf
|
||||
|
||||
|
||||
- sensor:
|
||||
name: "RF Last Type"
|
||||
unique_id: view_road_smoke_alarm_rf_last_type
|
||||
default_entity_id: sensor.smoke_alarm_rf_last_type
|
||||
|
||||
state_topic: "viewroad-status/smokealarms/rf/last_type"
|
||||
entity_category: diagnostic
|
||||
|
||||
availability_topic: "viewroad-status/smokealarms/rf/availability"
|
||||
payload_available: "online"
|
||||
payload_not_available: "offline"
|
||||
|
||||
icon: mdi:waveform
|
||||
|
||||
device:
|
||||
identifiers:
|
||||
- view_road_smoke_alarm_rf
|
||||
|
||||
|
||||
- sensor:
|
||||
name: "RF Last Confidence"
|
||||
unique_id: view_road_smoke_alarm_rf_last_confidence
|
||||
default_entity_id: sensor.smoke_alarm_rf_last_confidence
|
||||
|
||||
state_topic: "viewroad-status/smokealarms/rf/last_confidence"
|
||||
unit_of_measurement: "%"
|
||||
state_class: measurement
|
||||
entity_category: diagnostic
|
||||
|
||||
availability_topic: "viewroad-status/smokealarms/rf/availability"
|
||||
payload_available: "online"
|
||||
payload_not_available: "offline"
|
||||
|
||||
icon: mdi:percent
|
||||
|
||||
device:
|
||||
identifiers:
|
||||
- view_road_smoke_alarm_rf
|
||||
|
||||
|
||||
- sensor:
|
||||
name: "RF Last Seen"
|
||||
unique_id: view_road_smoke_alarm_rf_last_seen
|
||||
default_entity_id: sensor.smoke_alarm_rf_last_seen
|
||||
|
||||
state_topic: "viewroad-status/smokealarms/rf/last_seen"
|
||||
device_class: timestamp
|
||||
entity_category: diagnostic
|
||||
|
||||
availability_topic: "viewroad-status/smokealarms/rf/availability"
|
||||
payload_available: "online"
|
||||
payload_not_available: "offline"
|
||||
|
||||
device:
|
||||
identifiers:
|
||||
- view_road_smoke_alarm_rf
|
||||
|
||||
|
||||
- sensor:
|
||||
name: "RF Last Duration"
|
||||
unique_id: view_road_smoke_alarm_rf_last_duration
|
||||
default_entity_id: sensor.smoke_alarm_rf_last_duration
|
||||
|
||||
state_topic: "viewroad-status/smokealarms/rf/last_duration"
|
||||
unit_of_measurement: "s"
|
||||
device_class: duration
|
||||
state_class: measurement
|
||||
entity_category: diagnostic
|
||||
|
||||
availability_topic: "viewroad-status/smokealarms/rf/availability"
|
||||
payload_available: "online"
|
||||
payload_not_available: "offline"
|
||||
|
||||
device:
|
||||
identifiers:
|
||||
- view_road_smoke_alarm_rf
|
||||