diff --git a/esphome/esp-officeduallights.yaml b/esphome/esp-officeduallights.yaml index ea456aa..a99e5de 100644 --- a/esphome/esp-officeduallights.yaml +++ b/esphome/esp-officeduallights.yaml @@ -6,6 +6,10 @@ # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeduallights.yaml #:########################################################################################:# # VERSIONS: +# V2.8 2026-07-25 Added 2-way MQTT sync with esp-officelights (office main lightswitch). +# on_connect republishes retained status on MQTT reconnect. on_message +# subscribes to main lightswitch command topics for offline HA-independent +# operation. # V2.7 2026-04-24 Updated MQTT local topics, retain false, and timed control using seconds # V2.6 2026-04-23 Added independent MQTT timed ON control for relay1 and relay2 # V2.5 2026-03-11 Updated yaml to zorruno layout V1.1 @@ -22,11 +26,11 @@ #:########################################################################################:# # OPERATION NOTES: # - Controls 2 office light circuits: -# - Overhead cool white lights -# - Right hand warm bunker light +# - Right hand warm bunker light (relay/light 1) +# - Overhead cool white lights (relay/light 2) # - Local button 1 toggles relay/light 1 and cancels any active timer for relay 1 # - Local button 2 toggles relay/light 2 and cancels any active timer for relay 2 -# - Relay state changes are sent out via MQTT status topics with retain false +# - Relay state changes are sent out via MQTT status topics with retain true # - MQTT can command each relay with: # - On = turn on with no timer and cancel any active timer # - Off = turn off immediately and cancel any active timer @@ -35,31 +39,42 @@ # - Invalid MQTT timer values are ignored # - Template binary lights drive the template relay switches # - Sonoff Dual R1 requires UART serial packets to operate the physical relays +# - 2-way sync with esp-officelights (office main lightswitch) for offline HA-independent +# operation. This device subscribes to command topics from the main lightswitch and +# publishes retained status for the main lightswitch to mirror. # # MQTT COMMANDS: -# - Command relay 1: -# - ${mqtt_local_command1_topic} On, Off, or 1 to 3600 seconds -# - Command relay 2: -# - ${mqtt_local_command2_topic} On, Off, or 1 to 3600 seconds -# - Relay 1 status publishes to: -# - ${mqtt_local_status1_topic} On or Off -# - Relay 2 status publishes to: -# - ${mqtt_local_status2_topic} On or Off +# Bunker Light (relay 1): +# - Command topics: +# - ${mqtt_local_command1_topic} On, Off, or 1 to 3600 seconds (from occupancy sensor) +# - ${mqtt_mainlight_command_bunker} On or Off (from esp-officelights button 1) +# - Status topic: +# - ${mqtt_local_status1_topic} On or Off (retained) +# +# Overhead Lights (relay 2): +# - Command topics: +# - ${mqtt_local_command2_topic} On, Off, or 1 to 3600 seconds (from occupancy sensor) +# - ${mqtt_mainlight_command_overhead} On or Off (from esp-officelights button 2) +# - Status topic: +# - ${mqtt_local_status2_topic} On or Off (retained) #:########################################################################################:# # OFFLINE NOTES: # a) Home Assistant offline (network and MQTT still online): -# - Device continues to operate from local buttons -# - Device can still be controlled directly by MQTT -# - Relay status still publishes by MQTT if broker is available +# - Device continues to operate from local buttons. +# - Device can still be controlled directly by MQTT. +# - 2-way sync with esp-officelights continues via MQTT. +# - Relay status still publishes by MQTT if broker is available. +# - HA entities are unavailable until HA returns. # # b) MQTT offline (or HA and MQTT both offline): -# - Device continues to operate from local buttons only -# - No direct inter-ESP MQTT control available -# - No MQTT state feedback available +# - Device continues to operate from local buttons only. +# - No direct inter-ESP MQTT control available. +# - No MQTT state feedback available to esp-officelights. +# - No MQTT state feedback available to esp-officelights. # # c) Entire WiFi / Network offline: -# - Device continues to operate from local buttons only -# - No HA control or MQTT control/status available +# - Device continues to operate from local buttons only. +# - No HA control or MQTT control/status available. # - Accurate time is not needed; SNTP is not required for operation #:########################################################################################:# @@ -76,7 +91,7 @@ substitutions: # Project Naming project_name: "Sonoff Technologies.Sonoff Dual R1" - project_version: "v2.7" + project_version: "v2.8" # Passwords and Secrets api_key: !secret esp-api_key @@ -100,10 +115,18 @@ substitutions: mqtt_local_command2_topic: "${mqtt_command_main_topic}/${mqtt_local_device2_name}" mqtt_local_status2_topic: "${mqtt_status_main_topic}/${mqtt_local_device2_name}" - # MQTT REMOTE Controls - # mqtt_remote_device1_name: "masterbath-towelrail" - # mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}/operation" - # mqtt_remote_device1_command1: "BOOST" + # MQTT REMOTE Controls - esp-officelights (office main lightswitch) + # Command topics: this device subscribes to these to receive button press commands + # from the main lightswitch for 2-way sync. + mqtt_mainlight_function_bunker: "office-main-lights-left" + mqtt_mainlight_command_bunker: "${mqtt_command_main_topic}/${mqtt_mainlight_function_bunker}" + + mqtt_mainlight_function_overhead: "office-main-lights-right" + mqtt_mainlight_command_overhead: "${mqtt_command_main_topic}/${mqtt_mainlight_function_overhead}" + + # MQTT Status/Command payloads + mqtt_command_on: "On" + mqtt_command_off: "Off" # Switch Naming switch_1_name: "Dual L1 Relay" @@ -195,6 +218,20 @@ uart: # https://esphome.io/components/mqtt.html #:########################################################################################:# mqtt: + # Republish current relay states whenever MQTT reconnects so retained status stays accurate + # for subscribers that reconnect later. + on_connect: + - mqtt.publish: + topic: "${mqtt_local_status1_topic}" + payload: !lambda |- + return id(relay_1).state ? "${mqtt_command_on}" : "${mqtt_command_off}"; + retain: true + - mqtt.publish: + topic: "${mqtt_local_status2_topic}" + payload: !lambda |- + return id(relay_2).state ? "${mqtt_command_on}" : "${mqtt_command_off}"; + retain: true + on_message: - topic: "${mqtt_local_command1_topic}" payload: "On" @@ -272,6 +309,51 @@ mqtt: id(relay_2_timer_script)->execute(timer_seconds * 1000); + # Mirror remote bunker command from esp-officelights onto light_1, but only if a real + # state change is needed. Do not republish the command from here. Relay status is + # published by the relay callback below. + - topic: "${mqtt_mainlight_command_bunker}" + payload: "${mqtt_command_on}" + then: + - script.stop: relay_1_timer_script + - if: + condition: + lambda: "return !id(relay_1).state;" + then: + - light.turn_on: light_1 + + - topic: "${mqtt_mainlight_command_bunker}" + payload: "${mqtt_command_off}" + then: + - script.stop: relay_1_timer_script + - if: + condition: + lambda: "return id(relay_1).state;" + then: + - light.turn_off: light_1 + + # Mirror remote overhead command from esp-officelights onto light_2, but only if a real + # state change is needed. + - topic: "${mqtt_mainlight_command_overhead}" + payload: "${mqtt_command_on}" + then: + - script.stop: relay_2_timer_script + - if: + condition: + lambda: "return !id(relay_2).state;" + then: + - light.turn_on: light_2 + + - topic: "${mqtt_mainlight_command_overhead}" + payload: "${mqtt_command_off}" + then: + - script.stop: relay_2_timer_script + - if: + condition: + lambda: "return id(relay_2).state;" + then: + - light.turn_off: light_2 + #:########################################################################################:# # SCRIPT COMPONENT: # Independent per-relay timer scripts @@ -351,7 +433,7 @@ switch: - mqtt.publish: topic: "${mqtt_local_status1_topic}" payload: "On" - retain: false + retain: true - if: condition: switch.is_off: relay_2 @@ -363,7 +445,7 @@ switch: - mqtt.publish: topic: "${mqtt_local_status1_topic}" payload: "Off" - retain: false + retain: true - if: condition: switch.is_off: relay_2 @@ -382,7 +464,7 @@ switch: - mqtt.publish: topic: "${mqtt_local_status2_topic}" payload: "On" - retain: false + retain: true - if: condition: switch.is_off: relay_1 @@ -394,7 +476,7 @@ switch: - mqtt.publish: topic: "${mqtt_local_status2_topic}" payload: "Off" - retain: false + retain: true - if: condition: switch.is_off: relay_1 @@ -445,4 +527,4 @@ light: - platform: binary name: "${light_2_name}" id: light_2 - output: light_output_2 \ No newline at end of file + output: light_output_2