From 9342616e33c1847309f863ef55700fa71920da2c Mon Sep 17 00:00:00 2001 From: ESPHome Device Builder Date: Sat, 27 Jun 2026 23:57:17 +1200 Subject: [PATCH] Edit esp-entrancebathrmlights.yaml --- esphome/esp-entrancebathrmlights.yaml | 128 +++++++++++++------------- 1 file changed, 66 insertions(+), 62 deletions(-) diff --git a/esphome/esp-entrancebathrmlights.yaml b/esphome/esp-entrancebathrmlights.yaml index 3e45c91..fb231e2 100644 --- a/esphome/esp-entrancebathrmlights.yaml +++ b/esphome/esp-entrancebathrmlights.yaml @@ -6,7 +6,8 @@ # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-entrancebathrmlights.yaml #:########################################################################################:# # VERSIONS: -# V4.0 2026-06-27 Added extract fan timer enable switch and minute countdown sensor +# V4.1 2026-06-27 Changed fan timer back to MM:SS with 1 second countdown and 00:00 when fan is off +# V4.0 2026-06-27 Added extract fan timer enable switch and countdown sensor # V3.9 2026-03-11 Updated yaml to zorruno layout V1.1 # V3.8 2026-02-25 Updated yaml to zorruno layout V1.1 # V3.7 2025-09-34 Upload to this bathroom (as noted in original header) @@ -30,8 +31,8 @@ # - Countdown starts when the light turns OFF while the fan is ON. # - Countdown also starts when the fan turns ON while the light is already OFF. # - Countdown is cancelled/reset if the light turns ON or the fan turns OFF manually. -# - The timer remaining sensor shows whole minutes remaining. -# - When idle, the timer remaining sensor sits at the configured timer duration. +# - The timer remaining sensor shows MM:SS while counting down. +# - When the fan is OFF, the timer remaining sensor shows 00:00. #:########################################################################################:# # OFFLINE NOTES: # a) Home Assistant OFFLINE, but Network and MQTT ONLINE @@ -61,7 +62,7 @@ substitutions: # Project Naming project_name: "Zemismart Technologies.KS-811 Double" - project_version: "v4.0" + project_version: "v4.1" # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names @@ -118,7 +119,7 @@ packages: #### DIAGNOSTICS Sensors #### diag_basic: !include common/include_basic_diag_sensors.yaml - #diag_more: !include common/include_more_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml #diag_debug: !include common/include_debug_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml @@ -173,7 +174,7 @@ globals: restore_value: false initial_value: "false" - - id: fan_timer_remaining_minutes + - id: fan_timer_remaining_seconds type: int restore_value: false initial_value: "0" @@ -238,24 +239,35 @@ switch: - script.execute: fan_timer_evaluate #:########################################################################################:# -# SENSORS -# https://esphome.io/components/sensor/ +# TEXT SENSORS +# https://esphome.io/components/text_sensor/ #:########################################################################################:# -sensor: +text_sensor: - platform: template - name: "Fan Timer Remaining Minutes" - id: fan_timer_remaining_minutes_sensor + name: "Fan Timer Remaining" + id: fan_timer_remaining_text icon: "mdi:timer-outline" - unit_of_measurement: "min" - accuracy_decimals: 0 - device_class: duration - update_interval: 60s + update_interval: 1s lambda: |- - if (id(fan_timer_counting_down)) { - return id(fan_timer_remaining_minutes); + int seconds = 0; + + if (id(Relay_2).state && id(fan_timer_counting_down)) { + seconds = id(fan_timer_remaining_seconds); + } else { + seconds = 0; } - return ${fan_timer_duration_minutes}; + if (seconds < 0) { + seconds = 0; + } + + int mins = seconds / 60; + int secs = seconds % 60; + + char buffer[8]; + snprintf(buffer, sizeof(buffer), "%02d:%02d", mins, secs); + + return std::string(buffer); #:########################################################################################:# # SCRIPTS @@ -265,11 +277,10 @@ script: - id: fan_timer_cancel mode: restart then: - - script.stop: fan_timer_countdown - lambda: |- id(fan_timer_counting_down) = false; - id(fan_timer_remaining_minutes) = 0; - - component.update: fan_timer_remaining_minutes_sensor + id(fan_timer_remaining_seconds) = 0; + - component.update: fan_timer_remaining_text - id: fan_timer_evaluate mode: restart @@ -279,52 +290,45 @@ script: lambda: |- return id(fan_timer_enabled).state && !id(Relay_1).state && id(Relay_2).state; then: - - script.execute: fan_timer_countdown + - lambda: |- + id(fan_timer_remaining_seconds) = ${fan_timer_duration_minutes} * 60; + id(fan_timer_counting_down) = true; + - component.update: fan_timer_remaining_text else: - script.execute: fan_timer_cancel - - id: fan_timer_countdown - mode: restart +#:########################################################################################:# +# INTERVALS +# https://esphome.io/components/interval.html +#:########################################################################################:# +interval: + - interval: 1s then: - - lambda: |- - id(fan_timer_counting_down) = true; - id(fan_timer_remaining_minutes) = ${fan_timer_duration_minutes}; - - component.update: fan_timer_remaining_minutes_sensor - - - while: - condition: - lambda: |- - return id(fan_timer_counting_down) - && id(fan_timer_enabled).state - && !id(Relay_1).state - && id(Relay_2).state - && id(fan_timer_remaining_minutes) > 0; - then: - - delay: 60s - - if: - condition: - lambda: |- - return id(fan_timer_counting_down) - && id(fan_timer_enabled).state - && !id(Relay_1).state - && id(Relay_2).state - && id(fan_timer_remaining_minutes) > 0; - then: - - lambda: |- - id(fan_timer_remaining_minutes) -= 1; - - component.update: fan_timer_remaining_minutes_sensor - - if: condition: lambda: |- - return id(fan_timer_counting_down) - && id(fan_timer_enabled).state - && !id(Relay_1).state - && id(Relay_2).state - && id(fan_timer_remaining_minutes) <= 0; + return id(fan_timer_counting_down); then: - - lambda: |- - id(fan_timer_counting_down) = false; - id(fan_timer_remaining_minutes) = 0; - - component.update: fan_timer_remaining_minutes_sensor - - switch.turn_off: Relay_2 \ No newline at end of file + - if: + condition: + lambda: |- + return id(fan_timer_enabled).state && !id(Relay_1).state && id(Relay_2).state; + then: + - lambda: |- + if (id(fan_timer_remaining_seconds) > 0) { + id(fan_timer_remaining_seconds) -= 1; + } + - component.update: fan_timer_remaining_text + + - if: + condition: + lambda: |- + return id(fan_timer_remaining_seconds) <= 0; + then: + - lambda: |- + id(fan_timer_counting_down) = false; + id(fan_timer_remaining_seconds) = 0; + - component.update: fan_timer_remaining_text + - switch.turn_off: Relay_2 + else: + - script.execute: fan_timer_cancel \ No newline at end of file