diff --git a/esphome/esp-officelights.yaml b/esphome/esp-officelights.yaml index e780b0c..aae26f0 100644 --- a/esphome/esp-officelights.yaml +++ b/esphome/esp-officelights.yaml @@ -222,6 +222,7 @@ mqtt: - topic: "${mqtt_this_device_command_topic_overhead}" payload: "${mqtt_command_on}" then: + - script.stop: overhead_timer_script - if: condition: lambda: "return !id(Relay_2).state;" @@ -231,12 +232,39 @@ mqtt: - topic: "${mqtt_this_device_command_topic_overhead}" payload: "${mqtt_command_off}" then: + - script.stop: overhead_timer_script - if: condition: lambda: "return id(Relay_2).state;" then: - switch.turn_off: Relay_2 + - topic: "${mqtt_this_device_command_topic_overhead}" + then: + - lambda: |- + if (x.empty()) { + return; + } + + bool numeric_payload = true; + for (char c : x) { + if (c < '0' || c > '9') { + numeric_payload = false; + break; + } + } + + if (!numeric_payload) { + return; + } + + const int timer_seconds = atoi(x.c_str()); + if (timer_seconds < 1 || timer_seconds > 3600) { + return; + } + + id(overhead_timer_script)->execute(timer_seconds * 1000); + # Mirror remote bunker command onto Relay_1, but only if a real state change is needed. # This handles commands from esp-officeduallights when its local button toggles the # physical bunker light and publishes status. @@ -258,6 +286,54 @@ mqtt: then: - switch.turn_off: Relay_1 + # Bunker command from occupancy sensor or other MQTT publishers. Handles On, Off, + # and numeric timer values (1 to 3600 seconds). + - topic: "${mqtt_this_device_command_topic_bunker}" + payload: "${mqtt_command_on}" + then: + - script.stop: bunker_timer_script + - if: + condition: + lambda: "return !id(Relay_1).state;" + then: + - switch.turn_on: Relay_1 + + - topic: "${mqtt_this_device_command_topic_bunker}" + payload: "${mqtt_command_off}" + then: + - script.stop: bunker_timer_script + - if: + condition: + lambda: "return id(Relay_1).state;" + then: + - switch.turn_off: Relay_1 + + - topic: "${mqtt_this_device_command_topic_bunker}" + then: + - lambda: |- + if (x.empty()) { + return; + } + + bool numeric_payload = true; + for (char c : x) { + if (c < '0' || c > '9') { + numeric_payload = false; + break; + } + } + + if (!numeric_payload) { + return; + } + + const int timer_seconds = atoi(x.c_str()); + if (timer_seconds < 1 || timer_seconds > 3600) { + return; + } + + id(bunker_timer_script)->execute(timer_seconds * 1000); + #:########################################################################################:# # SCRIPTS # https://esphome.io/components/script.html @@ -346,6 +422,27 @@ script: else: - script.execute: office_overhead_on + # Bunker timer script. Turns on immediately, waits for the duration, then turns off. + # mode: restart means a new valid timer value restarts the timer from zero. + - id: bunker_timer_script + mode: restart + parameters: + timer_duration_ms: int + then: + - switch.turn_on: Relay_1 + - delay: !lambda "return timer_duration_ms;" + - switch.turn_off: Relay_1 + + # Overhead timer script. Turns on immediately, waits for the duration, then turns off. + - id: overhead_timer_script + mode: restart + parameters: + timer_duration_ms: int + then: + - switch.turn_on: Relay_2 + - delay: !lambda "return timer_duration_ms;" + - switch.turn_off: Relay_2 + #:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/