diff --git a/esphome/esp-occupancystair.yaml b/esphome/esp-occupancystair.yaml index 722df22..6bb6e88 100644 --- a/esphome/esp-occupancystair.yaml +++ b/esphome/esp-occupancystair.yaml @@ -6,6 +6,7 @@ # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-occupancystair.yaml #:########################################################################################:# # VERSIONS: +# V2.4 2026-07-26 Added status-aware ownership for the footer-light auto timer # V2.3 2026-07-25 Standardized MQTT payloads: "ON"/"OFF" → "On"/"Off" # V2.2 2026-02-25 Updated yaml to zorruno layout V1.1 # V2.1 2025-08-25 Added some MQTT to send commands to turn on remote lights @@ -65,7 +66,7 @@ substitutions: # Project Naming project_name: "Generic.ESP32" - project_version: "v2.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_version: "v2.4" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) api_key: !secret esp-api_key @@ -85,6 +86,7 @@ substitutions: # MQTT REMOTE Controls mqtt_remote_device1_name: "stair-footerlights" mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}" + mqtt_remote_device1_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device1_name}" mqtt_remote_device_command_ON: "On" mqtt_remote_device_command_OFF: "Off" @@ -158,6 +160,26 @@ globals: restore_value: true initial_value: "20" + - id: stair_footer_state_known + type: bool + restore_value: false + initial_value: "false" + + - id: stair_footer_is_on + type: bool + restore_value: false + initial_value: "false" + + - id: stair_footer_auto_owns_light + type: bool + restore_value: false + initial_value: "false" + + - id: stair_footer_auto_on_pending + type: bool + restore_value: false + initial_value: "false" + #:########################################################################################:# # I2C BUS: # https://esphome.io/components/i2c.html @@ -176,6 +198,31 @@ logger: level: "${log_level}" baud_rate: 0 +#:########################################################################################:# +# MQTT STATUS: +# Tracks the authoritative footer-light state so auto control only turns off a +# light that it turned on itself. +#:########################################################################################:# +mqtt: + on_message: + - topic: "${mqtt_remote_device1_status_topic}" + payload: "${mqtt_remote_device_command_ON}" + then: + - lambda: |- + id(stair_footer_state_known) = true; + id(stair_footer_is_on) = true; + id(stair_footer_auto_on_pending) = false; + + - topic: "${mqtt_remote_device1_status_topic}" + payload: "${mqtt_remote_device_command_OFF}" + then: + - lambda: |- + id(stair_footer_state_known) = true; + id(stair_footer_is_on) = false; + if (!id(stair_footer_auto_on_pending)) { + id(stair_footer_auto_owns_light) = false; + } + #:########################################################################################:# # UART: # https://esphome.io/components/uart.html @@ -467,17 +514,38 @@ script: - id: stair_footer_auto_script mode: restart then: - # Turn lights on (command the Top switch's footer relay) - - mqtt.publish: - topic: "${mqtt_remote_device1_command_topic}" - payload: "${mqtt_remote_device_command_ON}" - retain: false + - if: + condition: + lambda: |- + return id(stair_footer_auto_owns_light) + || !id(stair_footer_state_known) + || !id(stair_footer_is_on); + then: + # Acquire ownership only when this automation needs to turn the light on. + - if: + condition: + lambda: "return !id(stair_footer_auto_owns_light);" + then: + - lambda: |- + id(stair_footer_auto_owns_light) = true; + id(stair_footer_auto_on_pending) = true; + - mqtt.publish: + topic: "${mqtt_remote_device1_command_topic}" + payload: "${mqtt_remote_device_command_ON}" + retain: false - # Wait for the HA-adjustable timeout - - delay: !lambda "return (uint32_t)(id(stair_footer_auto_time_s).state) * 1000;" + # Repeated occupancy restarts this delay while retaining ownership. + - delay: !lambda "return (uint32_t)(id(stair_footer_auto_time_s).state) * 1000;" - # Turn lights back off - - mqtt.publish: - topic: "${mqtt_remote_device1_command_topic}" - payload: "${mqtt_remote_device_command_OFF}" - retain: false + # An external OFF status releases ownership and suppresses this command. + - if: + condition: + lambda: "return id(stair_footer_auto_owns_light);" + then: + - lambda: |- + id(stair_footer_auto_owns_light) = false; + id(stair_footer_auto_on_pending) = false; + - mqtt.publish: + topic: "${mqtt_remote_device1_command_topic}" + payload: "${mqtt_remote_device_command_OFF}" + retain: false