From a8d2927274b380c2c5244186ae6db1d0a6499c83 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 25 Feb 2026 21:05:21 +1300 Subject: [PATCH] yaml layout updates to v1.x --- esphome/esp-3dprinterpow.yaml | 202 +++-- esphome/esp-arcademachine1.yaml | 131 +-- esphome/esp-bedrm1arlecbulb.yaml | 188 +++-- esphome/esp-bedrm2ceilingfan.yaml | 295 ++++--- esphome/esp-bedrm2fanswitch.yaml | 213 ++--- esphome/esp-bedrm2lights.yaml | 161 ++-- esphome/esp-bedrm3ceilingfan.yaml | 264 +++--- esphome/esp-bedrm3fanswitch.yaml | 222 ++--- esphome/esp-bedrm3lights.yaml | 216 +++-- esphome/esp-breakfastbarleds.yaml | 394 ++++----- esphome/esp-centralstairs-bottom.yaml | 170 ++-- esphome/esp-centralstairs-top.yaml | 175 ++-- esphome/esp-datacupboardfans.yaml | 194 +++-- esphome/esp-datacupboardpower-left.yaml | 102 ++- esphome/esp-datacupboardpower-right.yaml | 105 ++- esphome/esp-downstairsdishwasher.yaml | 179 ++-- esphome/esp-downstairskitchleds.yaml | 473 ++++++----- esphome/esp-downstbathswitch.yaml | 172 ++-- esphome/esp-downstbathtowelrail.yaml | 323 ++++---- esphome/esp-downstbedrm2lights.yaml | 193 ++--- esphome/esp-downstkitchlights.yaml | 156 ++-- esphome/esp-downstloungeentry.yaml | 210 +++-- esphome/esp-downstloungemain.yaml | 222 ++--- esphome/esp-downstloungeoutside.yaml | 195 ++--- esphome/esp-downstmasterbedrmlights.yaml | 188 +++-- esphome/esp-entbtproxy.yaml | 154 ++-- esphome/esp-entmulti.yaml | 607 ++++++++------ esphome/esp-entrancebathrmlights.yaml | 166 ++-- esphome/esp-entrancelightswitch.yaml | 200 +++-- esphome/esp-entranceoutsideledlights.yaml | 969 ++++++++++++++++++++++ esphome/esp-flysprayer1.yaml | 320 ++++--- esphome/esp-garagedbcontrols.yaml | 354 ++++---- esphome/esp-lounge6chdimmer.yaml | 285 ++++--- esphome/esp-mainbathfancombo.yaml | 45 +- esphome/esp-mainpowermonitor.yaml | 289 +++++-- esphome/esp-masterbathtowelrail.yaml | 136 +-- esphome/esp-occupancyoffice.yaml | 538 ++++++------ esphome/esp-occupancystair.yaml | 343 ++++---- esphome/esp-officelights.yaml | 187 +++-- esphome/esp-officeusbhubpower.yaml | 219 ++--- esphome/esp-poollightpower2.yaml | 216 ++--- esphome/esp-poolpumppower.yaml | 406 ++++----- esphome/esp-rocktumbler.yaml | 198 +++-- esphome/esp-underhouselights.yaml | 235 +++--- 44 files changed, 6521 insertions(+), 4689 deletions(-) create mode 100644 esphome/esp-entranceoutsideledlights.yaml diff --git a/esphome/esp-3dprinterpow.yaml b/esphome/esp-3dprinterpow.yaml index 7d93d52..3fddf88 100644 --- a/esphome/esp-3dprinterpow.yaml +++ b/esphome/esp-3dprinterpow.yaml @@ -1,35 +1,67 @@ -############################################# -############################################# -# 3D PRINTER POWER AND SWITCH +#:########################################################################################:# +# TITLE: 3D PRINTER POWER AND SWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-3dprinterpow.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.0 2025-06-29 Initial Version -############################################# -# Sonoff POW R1 +#:########################################################################################:# +# HARDWARE: +# Sonoff POW R1 (ESP8266) # https://devices.esphome.io/devices/Sonoff-POW-R1 +#:########################################################################################:# +# OPERATION NOTES: +# - Inline power monitor (HLW8012) plus relay control for the 3D printer power feed +# - Local MQTT control (ON/OFF) without needing Home Assistant +# - Publishes current relay state on boot (burst) and on relay changes +# - "Running" binary sensor is derived from measured power > 4 W (with delayed_off) +#:########################################################################################:# +# MQTT COMMANDS: +# - Command topic (local): +# ${mqtt_local_command_topic} +# Payload "ON" -> relay ON + status LED ON +# Payload "OFF" -> relay OFF + status LED OFF # -# NOTES -# - -# -############################################# -############################################# +# - Status topic (local): +# ${mqtt_local_status_topic} +# Payload "ON"/"OFF" published on relay state changes, plus a short burst on boot +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device remains controllable via MQTT local command topic +# - Status publishes to MQTT still occur (relay state burst + changes) +# - HA entities are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable from Home Assistant via API (if enabled) +# - Local MQTT commands will not work and status publishes will fail while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available +# - Local button still toggles the relay (and status LED follows) +# - Accurate time is NOT needed (SNTP not needed) +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-3dprinterpow" friendly_name: "3D Printer Power" - description_comment: "3D Printer inline monitor and switch override using a Sonoff Pow R1." - device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "3D Printer inline monitor and switch override using a Sonoff Pow R1. (Layout V1.1)" + device_area: "Underhouse" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Sonoff Technologies.POW R1" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - + project_name: "Sonoff Technologies.POW R1" # Project Details + project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + # Passwords & Secrets api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-3dprinterpow_ip # unfortunately you can't use substitutions inside secrets names mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic @@ -42,16 +74,16 @@ substitutions: mqtt_local_device_name: "3dprinter-power" mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_local_device_name}" # Topic we will use to command this locally without HA mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_local_device_name}" # Topic we will use to view status locally without HA - - # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - entity_prefix: "Load" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. -########################################################################################## + # Device Settings + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for for general sensors etc + entity_prefix: "Load" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -74,23 +106,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -104,80 +136,74 @@ esphome: then: - script.execute: publish_state_burst -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: Device-specific MQTT command triggers # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: # Switch control from MQTT - topic: "${mqtt_local_command_topic}" payload: "ON" then: - - switch.turn_on: relay - - light.turn_on: led + - switch.turn_on: relay + - light.turn_on: led - topic: "${mqtt_local_command_topic}" payload: "OFF" then: - - switch.turn_off: relay - - light.turn_off: led + - switch.turn_off: relay + - light.turn_off: led -############################################# -# STATUS LED -# https://esphome.io/components/status_led.html -############################################# -#status_led: -# pin: -# number: GPIO2 -# inverted: yes - -############################################# -# SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# binary_sensor: - platform: gpio pin: - number: GPIO00 + number: GPIO0 mode: INPUT_PULLUP - inverted: True - name: Button + inverted: true + name: "Button" on_press: - switch.toggle: virtual_button + - platform: template - name: ${entity_prefix} Running + name: "${entity_prefix} Running" filters: - delayed_off: 15s lambda: |- if (isnan(id(power).state)) { return {}; } else if (id(power).state > 4) { - // Running return true; } else { - // Not running return false; } +#:########################################################################################:# +# SENSORS COMPONENT: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: hlw8012 sel_pin: 5 @@ -185,20 +211,17 @@ sensor: cf1_pin: 13 update_interval: 2s current: - name: ${entity_prefix} Current + name: "${entity_prefix} Current" voltage: - name: ${entity_prefix} Voltage + name: "${entity_prefix} Voltage" power: - name: ${entity_prefix} Power + name: "${entity_prefix} Power" id: power - #on_value_range: - # - above: 4.0 - # then: - # - light.turn_on: led - # - below: 3.0 - # then: - # - light.turn_off: led +#:########################################################################################:# +# SWITCH COMPONENT: +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: - platform: template name: "Relay" @@ -215,7 +238,6 @@ switch: id: relay pin: GPIO12 restore_mode: RESTORE_DEFAULT_ON - # restore_mode: ALWAYS_ON # Or RESTORE_DEFAULT_ON/RESTORE_DEFAULT_OFF on_turn_on: - mqtt.publish: topic: "${mqtt_local_status_topic}" @@ -227,19 +249,31 @@ switch: payload: "OFF" retain: false +#:########################################################################################:# +# OUTPUT COMPONENT: +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: pow_blue_led pin: number: GPIO15 - inverted: True + inverted: true +#:########################################################################################:# +# LIGHT COMPONENT: +# https://esphome.io/components/light/ +#:########################################################################################:# light: - platform: monochromatic - name: Status LED + name: "Status LED" output: pow_blue_led id: led +#:########################################################################################:# +# SCRIPT COMPONENT: +# https://esphome.io/components/script.html +#:########################################################################################:# script: - id: publish_state_burst mode: restart diff --git a/esphome/esp-arcademachine1.yaml b/esphome/esp-arcademachine1.yaml index 5a2ceeb..8dbc450 100644 --- a/esphome/esp-arcademachine1.yaml +++ b/esphome/esp-arcademachine1.yaml @@ -1,23 +1,40 @@ -########################################################################################## -########################################################################################## +#:########################################################################################:# +# TITLE: ARCADE CABINET 1 POWER (ATHOM SMART PLUG V1) +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: +# V1.0 Unknown date - Initial Version (date not present in source header) +#:########################################################################################:# +# HARDWARE: +# - Athom Smart Plug Power V1 (ESP8285 / ESP8266 family) +# - Load: MAME Arcade Cabinet 1 (Defender) +#:########################################################################################:# +# OPERATION NOTES: +# - Controls arcade cabinet mains power via Athom Smart Plug relay +# - Provides power monitoring via included Athom PowerMon V1 common package +# - Local power button toggles relay state +#:########################################################################################:# +# MQTT COMMANDS: # -########################################################################################## -########################################################################################## +#:########################################################################################:# +# OFFLINE NOTES: +# +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-arcademachine1" friendly_name: "Arcade Cabinet 1" - description_comment: "MAME Arcade 1 (Defender) machine power :: Athom Smart Plug Power V1" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - + description_comment: "MAME Arcade 1 (Defender) machine power :: Athom Smart Plug Power V1 (Layout V1.0)" + device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + # Project Naming - project_name: "Athom Technology.Smart Plug V1" # Project Details + project_name: "Athom Technology.Smart Plug V1" # Project Details project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords @@ -34,13 +51,14 @@ substitutions: update_interval: "10s" # update time for for general sensors etc # Device Settings - relay_icon: "mdi:power-socket-au" - current_limit : "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. - -########################################################################################## + relay_icon: "mdi:power-socket-au" + current_limit: "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. + + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: ################################################## # MANDATORY packages (won't compile without them!) @@ -57,7 +75,7 @@ packages: ################################################## # OPTIONAL packages (comment if you don't want them) - ################################################## + ################################################## #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -65,7 +83,7 @@ packages: #file: common/api_common_noencryption.yaml vars: local_api_key: "${api_key}" - + #### WEB PORTAL #### common_webportal: !include file: common/webportal_common.yaml @@ -75,7 +93,7 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### SNTP (Only use if you want/need accurate timeclocks) #### common_sntp: !include file: common/sntp_common.yaml @@ -100,56 +118,69 @@ packages: local_friendly_name: "${friendly_name}" local_current_limit: "${current_limit}" -########################################################################################## -# ESPHome + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" #Appears on the esphome page in HA - area: "${device_area}" - name_add_mac_suffix: False + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" + name_add_mac_suffix: false min_version: 2024.6.0 project: name: "${project_name}" version: "${project_version}" -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +#:########################################################################################:# esp8266: board: esp8285 restore_from_flash: true # mainly for calculating cumulative energy, but not that important here #framework: # version: 2.7.4 + +#:########################################################################################:# +# PREFERENCES: +# https://esphome.io/components/preferences.html +#:########################################################################################:# preferences: flash_write_interval: 10min -mdns: - disabled: False # binary size saving -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# MDNS: +# https://esphome.io/components/mdns.html +#:########################################################################################:# +mdns: + disabled: false # binary size saving + + +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# BINARY SENSORS + +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: gpio pin: - number: GPIO03 + number: GPIO3 mode: INPUT_PULLUP inverted: true name: "Power Button" @@ -162,28 +193,28 @@ binary_sensor: then: - lambda: |- if (id(relay).state) { - // Relay is ON: turn it OFF and set mode to 2 (TIMER) + // Relay is ON: turn it OFF id(relay).turn_off(); } else { - // Relay is OFF: turn it ON and set mode to 3 (BOOST) + // Relay is OFF: turn it ON id(relay).turn_on(); } - + - platform: template name: "Relay Status" lambda: |- return id(relay).state; -################################################################################################# -# SWITCH COMPONENT + +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -################################################################################################# +#:########################################################################################:# switch: - platform: gpio name: "Power Output" pin: GPIO14 id: relay - restore_mode: RESTORE_DEFAULT_OFF # Ensures the relay is restored (or off) at boot - #internal: true # Hides the switch from Home Assistant - icon: "${relay_icon}" - + restore_mode: RESTORE_DEFAULT_OFF # Ensures the relay is restored (or off) at boot + #internal: true # Hides the switch from Home Assistant + icon: "${relay_icon}" \ No newline at end of file diff --git a/esphome/esp-bedrm1arlecbulb.yaml b/esphome/esp-bedrm1arlecbulb.yaml index a063664..f68107c 100644 --- a/esphome/esp-bedrm1arlecbulb.yaml +++ b/esphome/esp-bedrm1arlecbulb.yaml @@ -1,39 +1,62 @@ -########################################################################################## -########################################################################################## -# MASTER BEDROOM BEDSIDE LAMP BULB -# File: esp-bedrm1arlecbulb.yaml -# -# v1.1 - 2026-02-21 Add "Jump Fade Up/Down" switch + configurable Jump Fade (%) -# v1.0 - 2026-02-21 Initial version (ported from Athom bulb YAML to Arlec GLD120HA) -# -# Hardware: Arlec Grid Connect Smart LED Globe RGB (GLD120HA) - B22 -# RGB + Warm White + Cold White (RGBWW, 5x PWM channels) -# -# NOTES -# - This keeps the "preferred control" ramping / min-max / watchdog / restore logic. +#:########################################################################################:# +# TITLE: MASTER BEDROOM BEDSIDE LAMP BULB +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm1arlecbulb.yaml +#:########################################################################################:# +# VERSIONS: +# v1.2 2026-02-25 Updated yaml to zorruno layout V1.1 +# v1.1 2026-02-21 Add "Jump Fade Up/Down" switch + configurable Jump Fade (%) +# v1.0 2026-02-21 Initial version (ported from Athom bulb YAML to Arlec GLD120HA) +#:########################################################################################:# +# HARDWARE: +# - Arlec Grid Connect Smart LED Globe RGB (GLD120HA) - B22 +# - ESP8266 (PWM, 5x channels) RGB + Warm White + Cold White (RGBWW) +# - PWM channels: +# - Red GPIO4 +# - Green GPIO12 +# - Blue GPIO14 +# - Warm White GPIO13 +# - Cold White GPIO5 +#:########################################################################################:# +# OPERATION NOTES: +# - Keeps the "preferred control" ramping / min-max / watchdog / restore logic. # - All ramping and "Output Set (0-100)" controls FORCE the bulb into Warm White endpoint -# (so everyday dimming uses the Warm White channel only, not mixed CT). -# - You can still control full RGB and CT from HA using the normal light entity. +# (everyday dimming uses Warm White channel only, not mixed CT). +# - Full RGB and CT control is still available from HA using the normal light entity. # - Max On watchdog turns the whole bulb OFF at the time limit (all channels). # - Jump Fade switch behavior: # - ON: jump to (jump% of max cap), then fade up to full (normal fade-up). # - OFF: jump down to (current - current*jump%), then fade down to OFF (normal fade-down). -########################################################################################## -########################################################################################## +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Bulb continues local operation and restores per configured restart action. +# - MQTT state publishing may not be visible in HA until HA returns. +# b) MQTT OFFLINE (or broker unreachable) +# - Bulb still operates via HA API (if available) and local logic. +# - MQTT local command topics will not work while MQTT is down. +# c) Entire WiFi/Network OFFLINE +# - Bulb still operates locally (last state/restore behavior as configured). +# - Accurate time is NOT needed (SNTP not needed). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS -########################################################################################## + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions +# If NOT using a secrets file, just replace these with the passwords etc (in quotes) +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-bedrm1arlecbulb" # yaml file should be device_name.yaml friendly_name: "Master Bedroom Bedside Lamp Arlec Bulb" - description_comment: "Bedside lightbulb using gridconnect Arlec RGB bulb" + description_comment: "Bedside lightbulb using gridconnect Arlec RGB bulb (Layout V1.1)" device_area: "Master Bedroom" # Project Naming project_name: "Grid Connect GLD120HA RGBWW.Arlec" - project_version: "v1.1" + project_version: "v1.2" # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) # Re-using your existing bulb flasher secrets (adjust if you prefer per-device secrets) @@ -55,28 +78,29 @@ substitutions: mqtt_local_device_command_OFF: "OFF" # Device Specific Settings - log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE - update_interval: "20s" - led_gamma: "2.8" - minimum_led_output: "1" # % If at this value or below, we'll switch it completely off - maximum_led_output: "80" # % Hard cap - max_on_default_hours: "24" # 0 = no automatic turn-off - pwm_frequency: "1000" # Hz + log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE + update_interval: "20s" + led_gamma: "2.8" + minimum_led_output: "1" # % If at this value or below, we'll switch it completely off + maximum_led_output: "80" # % Hard cap + max_on_default_hours: "24" # 0 = no automatic turn-off + pwm_frequency: "1000" # Hz # Warm/cold endpoints (reported range around 3000K-5700K) - bulb_warm_kelvin: "3000 K" - bulb_cold_kelvin: "5700 K" + bulb_warm_kelvin: "3000 K" + bulb_cold_kelvin: "5700 K" # Arlec GLD120HA GPIO mapping (PWM) - bulb_red_pin: GPIO4 - bulb_green_pin: GPIO12 - bulb_blue_pin: GPIO14 - bulb_warm_white_pin: GPIO13 - bulb_cold_white_pin: GPIO5 + bulb_red_pin: GPIO4 + bulb_green_pin: GPIO12 + bulb_blue_pin: GPIO14 + bulb_warm_white_pin: GPIO13 + bulb_cold_white_pin: GPIO5 -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages -########################################################################################## +# https://esphome.io/components/packages.html +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -100,13 +124,14 @@ packages: local_device_name: "${device_name}" #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - #diag_debug: !include common/include_debug_diag_sensors.yaml + diag_basic: !include common/include_basic_diag_sensors.yaml + diag_more: !include common/include_more_diag_sensors.yaml + #diag_debug: !include common/include_debug_diag_sensors.yaml -########################################################################################## -# ESPHome CORE CONFIGURATION -########################################################################################## +#:########################################################################################:# +# ESPHOME CORE CONFIGURATION +# https://esphome.io/components/esphome.html +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -158,9 +183,10 @@ esphome: # Boot complete: allow OFF handlers again - lambda: 'id(booting) = false;' -########################################################################################## +#:########################################################################################:# # ESP PLATFORM AND FRAMEWORK -########################################################################################## +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m restore_from_flash: true @@ -171,9 +197,10 @@ mdns: preferences: flash_write_interval: 1min -########################################################################################## +#:########################################################################################:# # GLOBAL VARIABLES -########################################################################################## +# https://esphome.io/components/globals.html +#:########################################################################################:# globals: - id: min_brightness_pct type: int @@ -255,22 +282,23 @@ globals: restore_value: false initial_value: "false" - # Jump Fade percentage (default 25%) + # Jump Fade percentage - id: jump_fade_pct type: int restore_value: true initial_value: "15" -########################################################################################## -# LOGGER -########################################################################################## +#:########################################################################################:# +# LOGGING +# https://esphome.io/components/logger.html +#:########################################################################################:# logger: level: "${log_level}" baud_rate: 0 -########################################################################################## +#:########################################################################################:# # MQTT COMMANDS (adds device-specific triggers to common MQTT) -########################################################################################## +#:########################################################################################:# mqtt: on_message: - topic: "${mqtt_local_command_topic}/light/set" @@ -283,9 +311,10 @@ mqtt: then: - switch.turn_off: bulb_ramp_switch -########################################################################################## +#:########################################################################################:# # SWITCH -########################################################################################## +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: - platform: template id: bulb_ramp_switch @@ -319,9 +348,10 @@ switch: id(ramp_switch_target_on) = false; - script.execute: jump_ramp_off_script -########################################################################################## +#:########################################################################################:# # BUTTON -########################################################################################## +# https://esphome.io/components/button/index.html +#:########################################################################################:# button: - platform: template id: fade_up_button @@ -370,9 +400,10 @@ button: id(last_brightness_pct) = pct; } -########################################################################################## +#:########################################################################################:# # SELECT -########################################################################################## +# https://esphome.io/components/select/index.html +#:########################################################################################:# select: - platform: template id: restart_action @@ -394,9 +425,10 @@ select: id(restart_mode) = 2; } -########################################################################################## +#:########################################################################################:# # SENSORS -########################################################################################## +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: template id: bulb_output_pct @@ -445,9 +477,10 @@ sensor: if (pwm > 1.0f) pwm = 1.0f; return pwm * 100.0f; -########################################################################################## +#:########################################################################################:# # OUTPUTS: 5 x PWM channels for the Arlec GLD120HA RGBWW bulb -########################################################################################## +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: output_red @@ -474,9 +507,10 @@ output: pin: ${bulb_cold_white_pin} frequency: ${pwm_frequency} -########################################################################################## +#:########################################################################################:# # LIGHT: RGBWW (correct for this bulb) -########################################################################################## +# https://esphome.io/components/light/ +#:########################################################################################:# light: - platform: rgbww id: bulb_light @@ -492,10 +526,9 @@ light: warm_white_color_temperature: ${bulb_warm_kelvin} cold_white_color_temperature: ${bulb_cold_kelvin} - # Safety: do not allow RGB and whites simultaneously color_interlock: true - # Important: keep OFF at boot to avoid instant restore flashes; boot script handles behavior. + # Keep OFF at boot to avoid instant restore flashes; boot script handles behavior. restore_mode: ALWAYS_OFF default_transition_length: 2s @@ -533,7 +566,6 @@ light: id(last_set_pos) = 0; id(led_output_set_pct).publish_state(0); - # Cap brightness to max_brightness_pct without a visible step on_state: - lambda: |- const float cap = id(max_brightness_pct) / 100.0f; @@ -548,9 +580,10 @@ light: call.set_transition_length(0); call.perform(); -########################################################################################## +#:########################################################################################:# # NUMBER -########################################################################################## +# https://esphome.io/components/number/ +#:########################################################################################:# number: - platform: template id: cfg_ramp_up_s @@ -612,7 +645,6 @@ number: id(jump_fade_pct) = v; id(cfg_jump_fade_pct).publish_state((float) v); - # This is the preferred everyday dimmer slider (FORCES Warm endpoint) - platform: template id: led_output_set_pct name: "${friendly_name} Output Set (0-100)" @@ -713,9 +745,10 @@ number: then: - script.execute: max_on_watchdog -########################################################################################## +#:########################################################################################:# # SCRIPTS -########################################################################################## +# https://esphome.io/components/script.html +#:########################################################################################:# script: - id: ramp_on_script mode: restart @@ -930,7 +963,6 @@ script: then: - script.stop: ramp_off_script - # Jump UP to (jump_pct% of max cap), only if we are below it. - if: condition: lambda: |- @@ -971,7 +1003,6 @@ script: return target_pct / 100.0f; transition_length: 0s - # Then fade up to full using your normal fade logic - script.execute: ramp_on_script # Jump Fade: OFF = jump down to (current - current*jump%) then normal fade down to OFF @@ -980,12 +1011,10 @@ script: then: - script.stop: ramp_on_script - # If the light is off already, do nothing fancy (avoids a flash from ramp_off_script). - if: condition: lambda: 'return id(bulb_light).current_values.is_on();' then: - # Jump DOWN to (100 - jump)% of current brightness (25 -> 75%), clamp to min. - light.turn_on: id: bulb_light color_temperature: "${bulb_warm_kelvin}" @@ -997,7 +1026,7 @@ script: if (jp < 0.0f) jp = 0.0f; if (jp > 100.0f) jp = 100.0f; - float factor = (100.0f - jp) / 100.0f; // 25 -> 0.75 + float factor = (100.0f - jp) / 100.0f; float target_pct = curr_pct * factor; float minp = (float) id(min_brightness_pct); @@ -1010,7 +1039,6 @@ script: return target_pct / 100.0f; transition_length: 0s - # Then fade down to off using your normal fade logic - script.execute: ramp_off_script else: - light.turn_off: diff --git a/esphome/esp-bedrm2ceilingfan.yaml b/esphome/esp-bedrm2ceilingfan.yaml index 9124a8f..43433d1 100644 --- a/esphome/esp-bedrm2ceilingfan.yaml +++ b/esphome/esp-bedrm2ceilingfan.yaml @@ -1,70 +1,88 @@ -########################################################################################## -########################################################################################## -# CEILING FAN - BEDROOM 2 -# - 3 speed fan using Sonoff IFan02 -# - Also, single Light Output +#:########################################################################################:# +# TITLE: CEILING FAN - BEDROOM 2 +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: +# V1.0 2025-07-21 First Setup (and replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# Controlled by a Sonoff iFan02 (3-speed fan + 1x light relay) +#:########################################################################################:# +# OPERATION NOTES: +# - Fan and light can be controlled via MQTT (local topics below) and via Home Assistant API +# - Fan speed state is tracked in a restored global (speed_value) +# - UART0 is used to sniff fan MCU frames (useful for RF remote debug) +#:########################################################################################:# +# MQTT COMMANDS: +# Fan speed command: +# ${mqtt_local_command_topic}/speed/set -> 0,1,2,3,+,- +# Fan light command: +# ${mqtt_local_command_topic}/light/set -> ON,OFF # -# Controlled by a Sonoff IFan 02 -# -# V1.0 - 2025-07-21 First Setup (and replacement of Tasmota) -# -# NOTES: -# Command the fan with MQTT -# ${mqtt_local_command_full_topic}/speed/set 1,2,3,0,+,- -# ${mqtt_local_command_full_topic}/light/set ON,OFF -# Status of the fan is in MQTT -# ${mqtt_local_command_full_topic}/speed/state 1,2,3,0 -# ${mqtt_local_command_full_topic}/light/state ON,OFF -# -########################################################################################## -########################################################################################## +# Fan speed status: +# ${mqtt_local_status_topic}/speed/state -> 0,1,2,3 +# Fan light status: +# ${mqtt_local_status_topic}/light/state -> ON,OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device remains controllable via MQTT local command topics +# - Status publishes to MQTT still occur (speed and light state) +# - HA entities (fan/light/select) will be unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable from Home Assistant via API (fan/light/select) +# - MQTT local commands will not work and status publishes will fail while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available +# - If power remains on, the relays keep their last driven state (fan speed relays and light relay) +# - If the device reboots while offline, fan/light restore_mode defaults apply (RESTORE_DEFAULT_OFF) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-bedrm2ceilingfan" friendly_name: "Bedroom 2 Ceiling Fan" - description_comment: "3 Speed Overhead Ceiling Fan Bedroom 2 :: Sonoff ifan02" - device_area: "Bedroom 2" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "3 Speed Overhead Ceiling Fan Bedroom 2 :: Sonoff iFan02 (Layout V1.0)" + device_area: "Bedroom 2" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Sonoff Technologies.Sonoff ifan02" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - # Passwords & Secrets + project_name: "Sonoff Technologies.Sonoff iFan02" # Project Details + project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + # Passwords and Secrets api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-bedrm2ceilingfan_ip # unfortunately you can't use substitutions inside secrets names mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic - + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + update_interval: "60s" # update time for general sensors etc # MQTT LOCAL Controls mqtt_device_name: "bedroom2-ceilingfan" - mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic used to command this locally without HA + mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic used to view status locally without HA - # MQTT REMOTE Controls + # Switch/Relay Naming and Icons + light_1_name: "Fan Light" + switch_2_name: "Fan 2 Relay" + switch_3_name: "Fan 3 Relay" + switch_4_name: "Fan 4 Relay" - # Button Naming & Icons - - # Switch/Relay Naming & Icons - #relay_icon: "mdi:lightbulb-group" - light_1_name: "Fan Light" - switch_2_name: "Fan 2 Relay" - switch_3_name: "Fan 3 Relay" - switch_4_name: "Fan 4 Relay" - -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -73,6 +91,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -86,102 +105,99 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" # Appears on the esphome page in HA area: "${device_area}" - on_boot: # This weird toggle thing makes sure the states get restored on reboot - priority : -100 + on_boot: # Publish restored speed on boot so other systems can sync + priority: -100 then: - delay: 200ms - #- fan.toggle: ifan02_fan - #- fan.toggle: ifan02_fan - #- delay: 200ms - #- light.toggle: ifan02_light - #- delay: 1ms - #- light.toggle: ifan02_light - #- delay: 1s - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" - payload: !lambda 'return to_string(id(speed_value));' + payload: !lambda "return to_string(id(speed_value));" # platformio_options: # build_flags: -# - "-Os" # optimize for size -# - "-Wl,--gc-sections" # drop unused code/data -# - "-fno-exceptions" # strip C++ exceptaions -# - "-fno-rtti" # strip C++ RTTI +# - "-Os" # optimize for size +# - "-Wl,--gc-sections" # drop unused code/data +# - "-fno-exceptions" # strip C++ exceptions +# - "-fno-rtti" # strip C++ RTTI -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: True # restore some values on reboot + board: esp01_1m # Sonoff iFan02 + restore_from_flash: true # restore some values on reboot preferences: flash_write_interval: 5min mdns: - disabled: True # Disabling will make the build file smaller (and it is still available via static IP) + disabled: true # Disabling will make the build file smaller (and it is still available via static IP) -########################################################################################## -# GLOBAL VARIABLES -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/guides/automations.html#global-variables +#:########################################################################################:# globals: - id: speed_value type: int - restore_value: yes - initial_value: '0' + restore_value: true + initial_value: "0" -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" # INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" # INFO suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART (UART0 used for fan MCU sniffing) -########################################################################################## -# UART: Fan MCU / RF Remote Sniff (iFan02 -> ESP over UART0) +#:########################################################################################:# +# UART: +# Fan MCU / RF Remote Sniff (iFan02 -> ESP over UART0) # - Uses GPIO3 (RX0) to listen to the fan microcontroller frames (433 MHz remote is decoded there) # - 9600 8N1 is typical; if no frames appear, try 19200 (uncomment below) # - If still nothing, some revisions route MCU TX to another pin; try rx_pin: GPIO13 -########################################################################################## +#:########################################################################################:# uart: id: ifan_uart - tx_pin: GPIO1 # ESP TX0 -> Fan MCU RX (not required for sniffing, but harmless) - rx_pin: GPIO3 # ESP RX0 <- Fan MCU TX (primary source for RF button frames) + tx_pin: GPIO1 # ESP TX0 -> Fan MCU RX (not required for sniffing, but harmless) + rx_pin: GPIO3 # ESP RX0 <- Fan MCU TX (primary source for RF button frames) baud_rate: 9600 - #baud_rate: 19200 # <-- try this if you see no frames in logs + #baud_rate: 19200 # try this if you see no frames in logs rx_buffer_size: 256 # NOTE: If no frames appear at either 9600 or 19200, try moving rx_pin to GPIO13 and reflash: # rx_pin: GPIO13 -########################################################################################## -# INTERVAL: Accumulate UART bytes and publish last frame to text sensor +#:########################################################################################:# +# INTERVAL COMPONENT: +# https://esphome.io/components/interval.html +# +# Accumulate UART bytes and publish last frame to text sensor # - Publishes after ~60ms of silence to group a single button press into one frame -########################################################################################## +#:########################################################################################:# interval: - interval: 50ms then: @@ -206,20 +222,20 @@ interval: frame.clear(); } -########################################################################################## -# TEXT SENSORS: RF/MCU debug output (last frame seen) -# - Shows the last raw hex bytes received from the fan MCU when you press the RF remote -########################################################################################## +#:########################################################################################:# +# TEXT SENSORS COMPONENT: +# https://esphome.io/components/text_sensor/index.html +#:########################################################################################:# text_sensor: - platform: template id: ifan_last_rf name: "iFan02 Remote Last Frame" update_interval: never -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: # Light control @@ -227,12 +243,13 @@ mqtt: payload: "ON" then: - light.turn_on: ifan02_light + - topic: "${mqtt_local_command_topic}/light/set" payload: "OFF" then: - light.turn_off: ifan02_light - # Fan speed control (0–3) + ramp up/down (+ / -) + # Fan speed control (0-3) plus ramp up/down (+ / -) - topic: "${mqtt_local_command_topic}/speed/set" then: # 1) Compute new speed_value based on payload @@ -257,21 +274,21 @@ mqtt: # 2) Drive the fan based on the new value - if: condition: - lambda: 'return id(speed_value) == 0;' + lambda: "return id(speed_value) == 0;" then: - fan.turn_off: ifan02_fan else: - fan.turn_on: id: ifan02_fan - speed: !lambda 'return id(speed_value);' + speed: !lambda "return id(speed_value);" -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## -# Sonoff ifan02 has relays, but they don't need to be shown in HA because -# the speed of the fan is the important part (and combinations of the relays give that) -########################################################################################## +# +# Sonoff iFan02 has relays, but they do not need to be shown in HA because +# the speed of the fan is the important part (and combinations of the relays give that) +#:########################################################################################:# switch: - platform: gpio name: "${switch_3_name}" @@ -279,12 +296,14 @@ switch: id: fan3sw restore_mode: RESTORE_DEFAULT_OFF internal: true + - platform: gpio name: "${switch_2_name}" pin: GPIO5 id: fan2sw restore_mode: RESTORE_DEFAULT_OFF internal: true + - platform: gpio name: "${switch_4_name}" pin: GPIO15 @@ -292,10 +311,10 @@ switch: restore_mode: RESTORE_DEFAULT_OFF internal: true -########################################################################################## -# SELECT COMPONENT +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -########################################################################################## +#:########################################################################################:# select: - platform: template name: "Bedroom 2 Fan Speed" @@ -322,6 +341,7 @@ select: - lambda: |- id(speed_value) = 0; - fan.turn_off: ifan02_fan + # LOW (1) - if: condition: @@ -332,6 +352,7 @@ select: - fan.turn_on: id: ifan02_fan speed: 1 + # MEDIUM (2) - if: condition: @@ -342,6 +363,7 @@ select: - fan.turn_on: id: ifan02_fan speed: 2 + # HIGH (3) - if: condition: @@ -353,13 +375,17 @@ select: id: ifan02_fan speed: 3 -################################################################################ -# TEMPLATE OUTPUTS: drive the real relays when the states change -################################################################################ +#:########################################################################################:# +# OUTPUT COMPONENT: +# https://esphome.io/components/output/ +# +# Template output drives the real relays when the fan output state changes +#:########################################################################################:# output: - platform: gpio pin: GPIO12 id: lightrelay + - platform: template type: float id: fan_decode @@ -386,17 +412,17 @@ output: id(fan4sw).turn_on(); } -########################################################################################## -# LIGHT COMPONENT +#:########################################################################################:# +# LIGHT COMPONENT: # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: binary name: "${light_1_name}" output: lightrelay restore_mode: RESTORE_DEFAULT_OFF id: ifan02_light - # publish status updates when the light turns on/off: + # Publish status updates when the light turns on/off on_turn_on: - mqtt.publish: topic: "${mqtt_local_status_topic}/light/state" @@ -406,10 +432,10 @@ light: topic: "${mqtt_local_status_topic}/light/state" payload: "OFF" -########################################################################################## -# FAN COMPONENT +#:########################################################################################:# +# FAN COMPONENT: # https://esphome.io/components/fan/index.html -########################################################################################## +#:########################################################################################:# fan: - platform: speed output: fan_decode @@ -417,28 +443,31 @@ fan: id: ifan02_fan speed_count: 3 restore_mode: RESTORE_DEFAULT_OFF - # whenever you explicitly set a speed (1–3): + + # Whenever you explicitly set a speed (1-3) on_speed_set: - lambda: |- id(speed_value) = x; - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" - payload: !lambda 'return to_string(id(speed_value));' - # whenever the fan goes fully off: + payload: !lambda "return to_string(id(speed_value));" + + # Whenever the fan goes fully off on_turn_off: - lambda: |- id(speed_value) = 0; - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" payload: "0" - # whenever the fan goes off→on (e.g. via HA’s Fan switch): + + # Whenever the fan goes off->on (eg via HA fan switch) on_turn_on: - lambda: |- - // bump 0->1 if we were off + // Bump 0->1 if we were off if (id(speed_value) == 0) id(speed_value) = 1; - fan.turn_on: id: ifan02_fan - speed: !lambda 'return id(speed_value);' + speed: !lambda "return id(speed_value);" - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" - payload: !lambda 'return to_string(id(speed_value));' + payload: !lambda "return to_string(id(speed_value));" \ No newline at end of file diff --git a/esphome/esp-bedrm2fanswitch.yaml b/esphome/esp-bedrm2fanswitch.yaml index ee14762..69610e1 100644 --- a/esphome/esp-bedrm2fanswitch.yaml +++ b/esphome/esp-bedrm2fanswitch.yaml @@ -1,36 +1,61 @@ -########################################################################################## -########################################################################################## -# BEDROOM 2 FAN SWITCH +#:########################################################################################:# +# TITLE: BEDROOM 2 FAN SWITCH (WALL SWITCH) +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: +# V1.0 2025-07-23 First Setup (and replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# Controlled by a Zemismart KS-811 Triple push button (KS-811-3) +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Wall switch for Bedroom 2 ceiling fan +# - 3 physical buttons: Speed Up (Button 1), Speed Down (Button 2), Fan Off (Button 3) +# - Buttons publish MQTT commands to the fan speed topic (remote control) +# - Device also subscribes to the fan speed state topic and drives the local KS-811 relays +# as a visual indicator of current speed (0-3) +#:########################################################################################:# +# MQTT COMMANDS: +# Remote fan speed command topic: +# ${mqtt_remote_device_command_topic} +# Payloads sent by buttons: +# Button 1 (Speed Up) -> "+" +# Button 2 (Speed Down) -> "-" +# Button 3 (Fan Off) -> "0" # -# Controlled by a Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# V1.0 - 2025-07-23 First Setup (and replacement of Tasmota) -# -# NOTES -# - Switch for Ceiling Fan -# - 3 Switches, Up, Down and Off -# - Remote commands to the fan ${mqtt_remote_command_full_topic}/speed/set 1,2,3,0,+,- -# -########################################################################################## -########################################################################################## +# Subscribed speed state topic (drives relay indicators): +# ${mqtt_local_status_topic} -> 0,1,2,3 +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Buttons still publish MQTT commands directly to the fan +# - Relay indicator sync still works (subscribed MQTT state updates) +# - HA entities for this switch device are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Buttons cannot command the fan (no MQTT broker available) +# - Relay indicator sync will not update from fan speed state +# - HA can still see/control only this device entities, but the fan control path is MQTT +# c) Entire WiFi/Network OFFLINE +# - No MQTT publish/subscribe and no HA API connectivity +# - Buttons will do nothing to the fan (no transport) +# - Relay indicators will remain in their last state until connectivity returns (or reboot) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-bedrm2fanswitch" friendly_name: "Bedroom 2 Fan Wall Switch (3)" - description_comment: "Switch for Bedroom 2 Ceiling Fan using Zemismart KS-811 Triple Push Button. Speed Up (1), Speed Down (2), Fan Off (3)" - device_area: "Bedroom 2" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - + description_comment: "Switch for Bedroom 2 Ceiling Fan using Zemismart KS-811 Triple Push Button. Speed Up (1), Speed Down (2), Fan Off (3) (Layout V1.0)" + device_area: "Bedroom 2" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + # Project Naming - project_name: "Zemismart Technologies.KS-811-3 (Triple)" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - entity_prefix: "Main Bathroom" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + project_name: "Zemismart Technologies.KS-811-3 (Triple)" # Project Details + project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names @@ -38,37 +63,34 @@ substitutions: static_ip_address: !secret esp-bedrm2fanswitch_ip mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic - - # Device Settings - #relay_icon: "mdi:heating-coil" - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - # MQTT LOCAL Controls - #mqtt_device_name: "bedroom2-ceilingfan-switch" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # Device Settings + log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc + # MQTT REMOTE Controls mqtt_remote_device_name: "bedroom2-ceilingfan" mqtt_remote_device_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}/speed/set" mqtt_remote_device_command1: "+" mqtt_remote_device_command2: "-" mqtt_remote_device_command3: "0" - mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}/speed/state" # Topic we will use to view status locally without HA - - # Button Naming & Icons + + # Fan speed status topic (used to sync relay indicators) + mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}/speed/state" # Switch/Relay Naming & Icons - #relay_icon: "mdi:heating-coil" - switch_1_name: "Fan Speed Up" # This is virtual only, no power connected to 1st relay - switch_2_name: "Fan Speed Down" # This is virtual only, no power connected to 2nd relay - switch_3_name: "Fan Off" # This is virtual only, no power connected to 3rd relay + switch_1_name: "Fan Speed Up" # Virtual intent only, no load connected to relay 1 + switch_2_name: "Fan Speed Down" # Virtual intent only, no load connected to relay 2 + switch_3_name: "Fan Off" # Virtual intent only, no load connected to relay 3 -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -77,6 +99,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -90,85 +113,80 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} #Appears on the esphome page in HA - area: ${device_area} + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" project: name: "${project_name}" version: "${project_version}" # platformio_options: # build_flags: -# - "-Os" # optimize for size -# - "-Wl,--gc-sections" # drop unused code/data -# - "-fno-exceptions" # strip C++ exceptions -# - "-fno-rtti" # strip C++ RTTI -# on_boot: -# priority: 200 -# then: -# - switch.turn_on: Relay_3 +# - "-Os" # optimize for size +# - "-Wl,--gc-sections" # drop unused code/data +# - "-fno-exceptions" # strip C++ exceptions +# - "-fno-rtti" # strip C++ RTTI -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO suggested, or DEBUG for testing + #baud_rate: 0 # set to 0 for no logging via UART, needed if using UART for other serial devices #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -########################################################################################## -# Status LED for KS-811 is GPIO02 -########################################################################################## +# Status LED for KS-811 is GPIO2 +#:########################################################################################:# status_led: pin: number: GPIO02 - inverted: yes + inverted: true -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## -# Buttons for KS-811-3 are GPIO16, GPIO05, GPIO04 -########################################################################################## +# Buttons for KS-811-3 are GPIO16, GPIO5, GPIO4 +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # This pin does not support interrupts so use polling (suppresses warning). name: "Button 1: ${switch_1_name}" on_press: - mqtt.publish: @@ -179,7 +197,7 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - mqtt.publish: @@ -190,33 +208,38 @@ binary_sensor: pin: number: GPIO4 mode: INPUT - inverted: True + inverted: true name: "Button 3: ${switch_3_name}" on_press: - mqtt.publish: topic: "${mqtt_remote_device_command_topic}" payload: "${mqtt_remote_device_command3}" -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## # Relays for KS-811-3 are GPIO13, GPIO12, GPIO14 -########################################################################################## +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 id: Relay_1 + - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 id: Relay_2 + - platform: gpio name: "Relay 3: ${switch_3_name}" pin: GPIO14 id: Relay_3 +#:########################################################################################:# +# MQTT: +# Subscribe to fan speed state and mirror it to relay indicator pattern +#:########################################################################################:# mqtt: on_message: - topic: "${mqtt_local_status_topic}" diff --git a/esphome/esp-bedrm2lights.yaml b/esphome/esp-bedrm2lights.yaml index ff83e31..975fe72 100644 --- a/esphome/esp-bedrm2lights.yaml +++ b/esphome/esp-bedrm2lights.yaml @@ -1,60 +1,73 @@ -########################################################################################## -########################################################################################## -# BEDROOM 2 LIGHTSWITCH +#:########################################################################################:# +# TITLE: BEDROOM 2 LIGHTSWITCH +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: # V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# Zemismart KS-811 Double push button (KS-811-2) +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - 2 button wall switch controlling 2 relays +# - Button 1 toggles Relay 1 (Main Lights) +# - Button 2 toggles Relay 2 (Desk Lights) +# - Status LED on GPIO2 +#:########################################################################################:# +# MQTT COMMANDS: +# - None (local relay control only; MQTT package is included for diagnostics/standardization) +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network ONLINE +# - Physical buttons still toggle the relays locally +# - If MQTT is online, any standard MQTT diagnostics from your common package continue to publish +# - HA entities will be unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Physical buttons still toggle the relays locally +# - HA control via API remains available (switch entities still work) +# - MQTT diagnostics/publishes from common_mqtt will fail while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - Physical buttons still toggle the relays locally (standalone operation) +# - No HA API access and no MQTT connectivity until network returns +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-bedrm2lights" friendly_name: "Bedroom 2 Lightswitch (2)" - description_comment: "Bedroom 2 Main Lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Desk Lights (2)" - device_area: "Bedroom 2" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Bedroom 2 Main Lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Desk Lights (2) (Layout V1.0)" + device_area: "Bedroom 2" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - # Passwords & Secrets + # Passwords and Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-bedrm2lights_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings - #relay_icon: "mdi:lightbulb-group" log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - - # MQTT LOCAL Controls - #mqtt_device_name: "bedroom2-lights" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + update_interval: "60s" # update time for general sensors etc # Switch Naming switch_1_name: "Main Lights" switch_2_name: "Desk Lights" - #switch_3_name: "Nil" -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -63,6 +76,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -76,23 +90,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -101,50 +115,52 @@ esphome: project: name: "${project_name}" version: "${project_version}" - #on_boot: + #on_boot: # priority: 200 # then: # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO suggested, or DEBUG for testing + #baud_rate: 0 # set to 0 for no logging via UART, needed if using UART for other serial devices #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +# Buttons for KS-811-2 are GPIO16, GPIO5 +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # GPIO16 does not support interrupts so use polling (suppresses warning). name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 @@ -153,7 +169,7 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - switch.toggle: Relay_2 @@ -163,15 +179,16 @@ binary_sensor: # pin: # number: GPIO4 # mode: INPUT -# inverted: True +# inverted: true # name: "Button 3: ${switch_3_name}" # on_press: # - switch.toggle: Relay_3 -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +# Relays for KS-811-2 are GPIO13, GPIO12 +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -187,6 +204,4 @@ switch: # - platform: gpio # name: "Relay 3: ${switch_3_name}" # pin: GPIO14 -# id: Relay_3 - - +# id: Relay_3 \ No newline at end of file diff --git a/esphome/esp-bedrm3ceilingfan.yaml b/esphome/esp-bedrm3ceilingfan.yaml index 9837542..8e7ede5 100644 --- a/esphome/esp-bedrm3ceilingfan.yaml +++ b/esphome/esp-bedrm3ceilingfan.yaml @@ -1,72 +1,88 @@ -########################################################################################## -########################################################################################## -# CEILING FAN - BEDROOM 3 -# - 3 speed fan using Sonoff IFan02 -# - Also, single Light Output +#:########################################################################################:# +# TITLE: CEILING FAN - BEDROOM 3 +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: +# V1.0 2025-07-21 First Setup (and replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# Controlled by a Sonoff iFan02 (3-speed fan + 1x light relay) +#:########################################################################################:# +# OPERATION NOTES: +# - Fan and light can be controlled via MQTT (local topics below) and via Home Assistant API +# - Fan speed state is tracked in a restored global (speed_value) +# - On boot, the device publishes the restored speed_value to the MQTT speed/state topic for syncing +#:########################################################################################:# +# MQTT COMMANDS: +# Fan speed command: +# ${mqtt_local_command_topic}/speed/set -> 0,1,2,3,+,- +# Fan light command: +# ${mqtt_local_command_topic}/light/set -> ON,OFF # -# Controlled by a Sonoff IFan 02 -# -# V1.0 - 2025-07-21 First Setup (and replacement of Tasmota) -# -# NOTES: -# Command the fan with MQTT -# ${mqtt_local_command_full_topic}/speed/set 1,2,3,0,+,- -# ${mqtt_local_command_full_topic}/light/set ON,OFF -# Status of the fan is in MQTT -# ${mqtt_local_command_full_topic}/speed/state 1,2,3,0 -# ${mqtt_local_command_full_topic}/light/state ON,OFF -# -########################################################################################## -########################################################################################## +# Fan speed status: +# ${mqtt_local_status_topic}/speed/state -> 0,1,2,3 +# Fan light status: +# ${mqtt_local_status_topic}/light/state -> ON,OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Fan and light remain controllable via MQTT local command topics +# - Status publishes to MQTT still occur (speed and light state) +# - HA entities are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Fan and light remain controllable from Home Assistant via API (fan/light/select) +# - MQTT local commands will not work and status publishes will fail while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available +# - If power remains on, relays keep their last driven state +# - If the device reboots while offline, fan/light restore_mode defaults apply (RESTORE_DEFAULT_OFF) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-bedrm3ceilingfan" friendly_name: "Bedroom 3 Ceiling Fan" - description_comment: "3 Speed Overhead Ceiling Fan Bedroom 3 :: Sonoff ifan02" - device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "3 Speed Overhead Ceiling Fan Bedroom 3 :: Sonoff iFan02 (Layout V1.0)" + device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Sonoff Technologies.Sonoff ifan02" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - # Passwords & Secrets + project_name: "Sonoff Technologies.Sonoff iFan02" # Project Details + project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + # Passwords and Secrets api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-bedrm3ceilingfan_ip # unfortunately you can't use substitutions inside secrets names mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic - + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + update_interval: "60s" # update time for general sensors etc # MQTT LOCAL Controls mqtt_device_name: "bedroom3-ceilingfan" - mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - - # MQTT REMOTE Controls - - # Button Naming & Icons + mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic used to command this locally without HA + mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic used to view status locally without HA # Switch/Relay Naming & Icons - #relay_icon: "mdi:lightbulb-group" - light_1_name: "Fan Light" - switch_2_name: "Fan 2 Relay" - switch_3_name: "Fan 3 Relay" - switch_4_name: "Fan 4 Relay" + light_1_name: "Fan Light" + switch_2_name: "Fan 2 Relay" + switch_3_name: "Fan 3 Relay" + switch_4_name: "Fan 4 Relay" -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -75,6 +91,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -88,80 +105,76 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" # Appears on the esphome page in HA area: "${device_area}" - on_boot: # This weird toggle thing makes sure the states get restored on reboot - priority : -100 + project: + name: "${project_name}" + version: "${project_version}" + on_boot: # Publish restored speed on boot so other systems can sync + priority: -100 then: - delay: 200ms - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" - payload: !lambda 'return to_string(id(speed_value));' - -# platformio_options: -# build_flags: -# - "-Os" # optimize for size -# - "-Wl,--gc-sections" # drop unused code/data -# - "-fno-exceptions" # strip C++ exceptaions -# - "-fno-rtti" # strip C++ RTTI + payload: !lambda "return to_string(id(speed_value));" -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: True # restore some values on reboot + board: esp01_1m # Sonoff iFan02 + restore_from_flash: true # restore some values on reboot preferences: flash_write_interval: 5min mdns: - disabled: True # Disabling will make the build file smaller (and it is still available via static IP) + disabled: true # Disabling will make the build file smaller (and it is still available via static IP) -########################################################################################## -# GLOBAL VARIABLES -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/guides/automations.html#global-variables +#:########################################################################################:# globals: - id: speed_value type: int - restore_value: yes - initial_value: '0' + restore_value: true + initial_value: "0" -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" # INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" # INFO suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: # Light control @@ -169,12 +182,13 @@ mqtt: payload: "ON" then: - light.turn_on: ifan02_light + - topic: "${mqtt_local_command_topic}/light/set" payload: "OFF" then: - light.turn_off: ifan02_light - # Fan speed control (0–3) + ramp up/down (+ / -) + # Fan speed control (0-3) plus ramp up/down (+ / -) - topic: "${mqtt_local_command_topic}/speed/set" then: # 1) Compute new speed_value based on payload @@ -199,21 +213,21 @@ mqtt: # 2) Drive the fan based on the new value - if: condition: - lambda: 'return id(speed_value) == 0;' + lambda: "return id(speed_value) == 0;" then: - fan.turn_off: ifan02_fan else: - fan.turn_on: id: ifan02_fan - speed: !lambda 'return id(speed_value);' + speed: !lambda "return id(speed_value);" -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## -# Sonoff ifan02 has relays, but they don't need to be shown in HA because -# the speed of the fan is the important part (and combinations of the relays give that) -########################################################################################## +# +# Sonoff iFan02 has relays, but they do not need to be shown in HA because +# the speed of the fan is the important part (and combinations of the relays give that) +#:########################################################################################:# switch: - platform: gpio name: "${switch_3_name}" @@ -221,12 +235,14 @@ switch: id: fan3sw restore_mode: RESTORE_DEFAULT_OFF internal: true + - platform: gpio name: "${switch_2_name}" pin: GPIO5 id: fan2sw restore_mode: RESTORE_DEFAULT_OFF internal: true + - platform: gpio name: "${switch_4_name}" pin: GPIO15 @@ -234,14 +250,14 @@ switch: restore_mode: RESTORE_DEFAULT_OFF internal: true -########################################################################################## -# SELECT COMPONENT +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -########################################################################################## +#:########################################################################################:# select: - platform: template - name: "Bedroom 2 Fan Speed" - id: bedroom2_fan_speed_select + name: "Bedroom 3 Fan Speed" + id: bedroom3_fan_speed_select options: - "Off" - "Low" @@ -264,6 +280,7 @@ select: - lambda: |- id(speed_value) = 0; - fan.turn_off: ifan02_fan + # LOW (1) - if: condition: @@ -274,6 +291,7 @@ select: - fan.turn_on: id: ifan02_fan speed: 1 + # MEDIUM (2) - if: condition: @@ -284,6 +302,7 @@ select: - fan.turn_on: id: ifan02_fan speed: 2 + # HIGH (3) - if: condition: @@ -295,13 +314,17 @@ select: id: ifan02_fan speed: 3 -################################################################################ -# TEMPLATE OUTPUTS: drive the real relays when the states change -################################################################################ +#:########################################################################################:# +# OUTPUT COMPONENT: +# https://esphome.io/components/output/ +# +# Template output drives the real relays when the fan output state changes +#:########################################################################################:# output: - platform: gpio pin: GPIO12 id: lightrelay + - platform: template type: float id: fan_decode @@ -328,17 +351,17 @@ output: id(fan4sw).turn_on(); } -########################################################################################## -# LIGHT COMPONENT +#:########################################################################################:# +# LIGHT COMPONENT: # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: binary name: "${light_1_name}" output: lightrelay restore_mode: RESTORE_DEFAULT_OFF id: ifan02_light - # publish status updates when the light turns on/off: + # Publish status updates when the light turns on/off on_turn_on: - mqtt.publish: topic: "${mqtt_local_status_topic}/light/state" @@ -348,10 +371,10 @@ light: topic: "${mqtt_local_status_topic}/light/state" payload: "OFF" -########################################################################################## -# FAN COMPONENT +#:########################################################################################:# +# FAN COMPONENT: # https://esphome.io/components/fan/index.html -########################################################################################## +#:########################################################################################:# fan: - platform: speed output: fan_decode @@ -359,28 +382,31 @@ fan: id: ifan02_fan speed_count: 3 restore_mode: RESTORE_DEFAULT_OFF - # whenever you explicitly set a speed (1–3): + + # Whenever you explicitly set a speed (1-3) on_speed_set: - lambda: |- id(speed_value) = x; - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" - payload: !lambda 'return to_string(id(speed_value));' - # whenever the fan goes fully off: + payload: !lambda "return to_string(id(speed_value));" + + # Whenever the fan goes fully off on_turn_off: - lambda: |- id(speed_value) = 0; - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" payload: "0" - # whenever the fan goes off→on (e.g. via HA’s Fan switch): + + # Whenever the fan goes off->on (eg via HA fan switch) on_turn_on: - lambda: |- - // bump 0→1 if we were off + // bump 0->1 if we were off if (id(speed_value) == 0) id(speed_value) = 1; - fan.turn_on: id: ifan02_fan - speed: !lambda 'return id(speed_value);' + speed: !lambda "return id(speed_value);" - mqtt.publish: topic: "${mqtt_local_status_topic}/speed/state" - payload: !lambda 'return to_string(id(speed_value));' \ No newline at end of file + payload: !lambda "return to_string(id(speed_value));" \ No newline at end of file diff --git a/esphome/esp-bedrm3fanswitch.yaml b/esphome/esp-bedrm3fanswitch.yaml index 8873a17..b35a2f5 100644 --- a/esphome/esp-bedrm3fanswitch.yaml +++ b/esphome/esp-bedrm3fanswitch.yaml @@ -1,76 +1,103 @@ -########################################################################################## -########################################################################################## -# BEDROOM 3 FAN SWITCH +#:########################################################################################:# +# TITLE: BEDROOM 3 FAN SWITCH (WALL SWITCH) +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: +# V1.0 2025-07-23 First Setup (and replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# Zemismart KS-811 Triple push button (KS-811-3) +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Wall switch for Bedroom 3 ceiling fan +# - 3 physical buttons: Speed Up (Button 1), Speed Down (Button 2), Fan Off (Button 3) +# - Buttons publish MQTT commands to the fan speed topic (remote control) +# - Device also subscribes to the fan speed state topic and drives the local KS-811 relays +# as a visual indicator of current speed (0-3) +#:########################################################################################:# +# MQTT COMMANDS: +# Remote fan speed command topic: +# ${mqtt_remote_device_command_topic} +# Payloads sent by buttons: +# Button 1 (Speed Up) -> "+" +# Button 2 (Speed Down) -> "-" +# Button 3 (Fan Off) -> "0" # -# Controlled by a Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# V1.0 - 2025-07-23 First Setup (and replacement of Tasmota) -# -# NOTES -# - Switch for Ceiling Fan -# - 3 Switches, Up, Down and Off -# - Remote commands to the fan ${mqtt_remote_command_full_topic}/speed/set 1,2,3,0,+,- -# -########################################################################################## -########################################################################################## +# Subscribed speed state topic (drives relay indicators): +# ${mqtt_local_status_topic} -> 0,1,2,3 +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Buttons still publish MQTT commands directly to the fan +# - Relay indicator sync still works (subscribed MQTT state updates) +# - HA entities for this switch device are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Buttons cannot command the fan (no MQTT broker available) +# - Relay indicator sync will not update from fan speed state +# - HA can still see/control only this device entities, but the fan control path is MQTT +# c) Entire WiFi/Network OFFLINE +# - No MQTT publish/subscribe and no HA API connectivity +# - Buttons will do nothing to the fan (no transport) +# - Relay indicators will remain in their last state until connectivity returns (or reboot) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-bedrm3fanswitch" friendly_name: "Bedroom 3 Fan Wall Switch (3)" - description_comment: "Switch for Bedroom 3 Ceiling Fan using Zemismart KS-811 Triple Push Button. Speed Up (1), Speed Down (2), Fan Off (3)" - device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - - # Project Naming - project_name: "Zemismart Technologies.KS-811-3 (Triple)" # Project Details - project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - #entity_prefix: "Main Bathroom" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + description_comment: "Switch for Bedroom 3 Ceiling Fan using Zemismart KS-811 Triple Push Button. Speed Up (1), Speed Down (2), Fan Off (3) (Layout V1.0)" + device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - # Passwords + # Project Naming + project_name: "Zemismart Technologies.KS-811-3 (Triple)" # Project Details + project_version: "v1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + #entity_prefix: "Main Bathroom" # Simple device name where we want to prefix a sensor or switch, eg "Load" Current. + + # Passwords and Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-bedrm3fanswitch_ip mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic - + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - #relay_icon: "mdi:heating-coil" log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + update_interval: "60s" # update time for general sensors etc # MQTT LOCAL Controls - #mqtt_device_name: "bedroom2-ceilingfan-switch" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - + #mqtt_device_name: "bedroom3-ceilingfan-switch" + #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic used to command this locally without HA + #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic used to view status locally without HA + # MQTT REMOTE Controls mqtt_remote_device_name: "bedroom3-ceilingfan" mqtt_remote_device_command_topic: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/speed/set" mqtt_remote_device_command1: "+" mqtt_remote_device_command2: "-" mqtt_remote_device_command3: "0" - mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_remote_device_name}/speed/state" # Topic we will use to view status locally without HA - - # Button Naming & Icons - # Switch/Relay Naming & Icons - #relay_icon: "mdi:heating-coil" - switch_1_name: "Fan Speed Up" # This is virtual only, no power connected to 1st relay - switch_2_name: "Fan Speed Down" # This is virtual only, no power connected to 2nd relay - switch_3_name: "Fan Off" # This is virtual only, no power connected to 3rd relay + # Fan speed status topic (used to sync relay indicators) + mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_remote_device_name}/speed/state" -########################################################################################## + # Switch/Relay Naming and Icons + switch_1_name: "Fan Speed Up" # Virtual intent only, no load connected to relay 1 + switch_2_name: "Fan Speed Down" # Virtual intent only, no load connected to relay 2 + switch_3_name: "Fan Off" # Virtual intent only, no load connected to relay 3 + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -79,6 +106,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -92,85 +120,84 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} #Appears on the esphome page in HA - area: ${device_area} + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # Appears on the ESPHome page in HA + area: "${device_area}" project: name: "${project_name}" version: "${project_version}" platformio_options: build_flags: - - "-Os" # optimize for size - - "-Wl,--gc-sections" # drop unused code/data - #- "-fno-exceptions" # strip C++ exceptions - #- "-fno-rtti" # strip C++ RTTI -# on_boot: + - "-Os" # optimize for size + - "-Wl,--gc-sections" # drop unused code/data + #- "-fno-exceptions" # strip C++ exceptions + #- "-fno-rtti" # strip C++ RTTI +# on_boot: # priority: 200 # then: # - switch.turn_on: Relay_3 -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO suggested, or DEBUG for testing + #baud_rate: 0 # set to 0 for no logging via UART, needed if using UART for other serial devices #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -########################################################################################## -# Status LED for KS-811 is GPIO02 -########################################################################################## +# Status LED for KS-811 is GPIO2 +#:########################################################################################:# status_led: pin: - number: GPIO02 - inverted: yes + number: GPIO2 + inverted: true -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## -# Buttons for KS-811-3 are GPIO16, GPIO05, GPIO04 -########################################################################################## +# Buttons for KS-811-3 are GPIO16, GPIO5, GPIO4 +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # GPO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # GPIO16 does not support interrupts so use polling (suppresses warning). name: "Button 1: ${switch_1_name}" on_press: - mqtt.publish: @@ -181,7 +208,7 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - mqtt.publish: @@ -192,33 +219,38 @@ binary_sensor: pin: number: GPIO4 mode: INPUT - inverted: True + inverted: true name: "Button 3: ${switch_3_name}" on_press: - mqtt.publish: topic: "${mqtt_remote_device_command_topic}" payload: "${mqtt_remote_device_command3}" -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## # Relays for KS-811-3 are GPIO13, GPIO12, GPIO14 -########################################################################################## +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 id: Relay_1 + - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 id: Relay_2 + - platform: gpio name: "Relay 3: ${switch_3_name}" pin: GPIO14 id: Relay_3 +#:########################################################################################:# +# MQTT: +# Subscribe to fan speed state and mirror it to relay indicator pattern +#:########################################################################################:# mqtt: on_message: - topic: "${mqtt_local_status_topic}" diff --git a/esphome/esp-bedrm3lights.yaml b/esphome/esp-bedrm3lights.yaml index a66a06b..1d8eaf7 100644 --- a/esphome/esp-bedrm3lights.yaml +++ b/esphome/esp-bedrm3lights.yaml @@ -1,73 +1,99 @@ -########################################################################################## -########################################################################################## -# BEDROOM 3 LIGHTSWITCH +#:########################################################################################:# +# TITLE: BEDROOM 3 LIGHTSWITCH +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: # V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# HARDWARE: +# Zemismart KS-811 Double push button (KS-811-2) +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Virtual 2-button wall switch used to control Bedroom 3 ceiling fan light and to force "all off" +# - Button 1 toggles the iFan02 light (sends MQTT ON/OFF), using Relay 1 as the local state mirror +# - Button 2 forces "All Lights Off" (turns iFan02 light OFF and sets fan speed to 0), and turns Relay 2 OFF +# - Relay 1 and Relay 2 are used as local state indicators (no load connected) +# - A short cooldown is used on Button 1 to prevent repeated MQTT publishes +#:########################################################################################:# +# MQTT COMMANDS: +# Remote fan light command: +# ${mqtt_remote_device_command_topic1} -> ON,OFF +# Remote fan speed command (used by All Off): +# ${mqtt_remote_device_command_topic2} -> 0 # -# NOTES -# - -# -########################################################################################## -########################################################################################## +# Remote fan light status (subscribed to keep Relay 1 in sync): +# ${mqtt_remote_status_topic1} -> ON,OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Buttons still publish MQTT commands directly to the remote iFan02 (light and all-off actions) +# - Relay 1 state mirror still updates from subscribed remote light status topic +# - HA entities for this switch device are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Buttons cannot control the remote iFan02 (control path is MQTT) +# - Relay 1 will not mirror the remote light status while MQTT is down +# - HA can still see/control the local indicator relays, but those do not affect the fan without MQTT +# c) Entire WiFi/Network OFFLINE +# - No MQTT publish/subscribe and no HA API connectivity +# - Buttons will not control the remote iFan02 +# - Local indicator relays remain in their last state until connectivity returns (or reboot) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-bedrm3lights" friendly_name: "Bedroom 3 Lightswitch (2)" - description_comment: "Bedroom 3 Main Lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1-Virtual), All Lights Off (2-Virtual)" - device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Bedroom 3 Main Lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1-Virtual), All Lights Off (2-Virtual) (Layout V1.0)" + device_area: "Bedroom 3" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - # Passwords & Secrets + # Passwords and Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-bedrm3lights_ip mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - #relay_icon: "mdi:lightbulb-group" log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + update_interval: "60s" # update time for general sensors etc - # MQTT LOCAL Controls + # MQTT LOCAL Controls mqtt_device_name: "bedroom3-lightswitch" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - # MQTT REMOTE Controls + # MQTT REMOTE Controls (Bedroom 3 iFan02) mqtt_remote_device_name: "bedroom3-ceilingfan" + + # Remote Light mqtt_remote_device_command_topic1: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/light/set" - mqtt_remote_status_topic1: "${mqtt_local_status_main_topic}/${mqtt_remote_device_name}/light/state" # Topic we will use to view status of remote without HA + mqtt_remote_status_topic1: "${mqtt_local_status_main_topic}/${mqtt_remote_device_name}/light/state" mqtt_remote_device_command_ON: "ON" mqtt_remote_device_command_OFF: "OFF" - mqtt_remote_device_command_topic2: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/speed/set" - #mqtt_remote_device_command1: "+" - #mqtt_remote_device_command2: "-" - mqtt_remote_device_command_0: "0" - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_remote_device_name}/speed/state" # Topic we will use to view status locally without HA - # Button Naming & Icons + # Remote Fan Speed (used for All Off) + mqtt_remote_device_command_topic2: "${mqtt_local_command_main_topic}/${mqtt_remote_device_name}/speed/set" + mqtt_remote_device_command_0: "0" # Switch Naming - switch_1_name: "Main Lights" # Nothing physically connected to this output. Lights are physically on IFan02 light output + switch_1_name: "Main Lights" # Nothing physically connected to this output (ifan02 light is the real load) switch_2_name: "All Lights Off" # Nothing physically connected to this output -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -76,6 +102,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -89,76 +116,80 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" # Appears on the ESPHome page in HA area: "${device_area}" project: name: "${project_name}" version: "${project_version}" - #on_boot: + #on_boot: # priority: 200 # then: # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO suggested, or DEBUG for testing + #baud_rate: 0 # set to 0 for no logging via UART, needed if using UART for other serial devices #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -#GLobals - +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/guides/automations.html#global-variables +#:########################################################################################:# globals: - id: btn1_last_ms type: uint32_t - restore_value: no - initial_value: '0' + restore_value: false + initial_value: "0" -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +# Buttons for KS-811-2 are GPIO16, GPIO5 +#:########################################################################################:# binary_sensor: - platform: gpio id: button_1 @@ -166,15 +197,15 @@ binary_sensor: number: GPIO16 mode: input: true - pullup: false # set to true if you need an internal pull-up + pullup: false # set to true if you need an internal pull-up inverted: true - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + use_interrupt: false # GPIO16 does not support interrupts so use polling (suppresses warning). name: "Button 1: ${switch_1_name}" filters: - delayed_on: 30ms - delayed_off: 30ms on_press: - # cooldown: 250 ms between publishes + # Cooldown: 250ms between publishes - if: condition: lambda: |- @@ -202,25 +233,26 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - switch.turn_off: Relay_2 - mqtt.publish: - topic: "${mqtt_remote_device_command_topic1}" - payload: "${mqtt_remote_device_command_OFF}" - qos: 0 - retain: false + topic: "${mqtt_remote_device_command_topic1}" + payload: "${mqtt_remote_device_command_OFF}" + qos: 0 + retain: false - mqtt.publish: - topic: "${mqtt_remote_device_command_topic2}" - payload: "${mqtt_remote_device_command_0}" - qos: 0 - retain: false + topic: "${mqtt_remote_device_command_topic2}" + payload: "${mqtt_remote_device_command_0}" + qos: 0 + retain: false -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +# Relays for KS-811-2 are GPIO13, GPIO12 (no load connected; used as indicators) +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -232,19 +264,19 @@ switch: pin: GPIO12 id: Relay_2 - -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: - # Switch control. Turn on/off relay if remote device switched on/off + # Mirror remote light state onto Relay 1 indicator - topic: "${mqtt_remote_status_topic1}" payload: "${mqtt_remote_device_command_ON}" then: - switch.turn_on: Relay_1 + - topic: "${mqtt_remote_status_topic1}" payload: "${mqtt_remote_device_command_OFF}" then: - - switch.turn_off: Relay_1 + - switch.turn_off: Relay_1 \ No newline at end of file diff --git a/esphome/esp-breakfastbarleds.yaml b/esphome/esp-breakfastbarleds.yaml index becbb0d..da74da5 100644 --- a/esphome/esp-breakfastbarleds.yaml +++ b/esphome/esp-breakfastbarleds.yaml @@ -1,19 +1,28 @@ -########################################################################################## -########################################################################################## -# Title: BREAKFAST BAR LEDS (Lounge) -# Repo: https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungebookshelfleds.yaml -# -# v2.0 - 2025-09-15 A bunch of fixes and made it more standard across my devices -# v1.0 - 2025-08-17 First setup (and replacement of Tasmota) +#:########################################################################################:# +# TITLE: BREAKFAST BAR LEDS (LOUNGE) +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-breakfastbarleds.yaml +#:########################################################################################:# +# VERSIONS: +# V2.0 2025-09-15 A bunch of fixes and made it more standard across my devices +# V1.0 2025-08-17 First setup (and replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# Magishome LED controller single channel (ESP8266, NOT the later ones with BL602) +# https://devices.esphome.io/devices/MagicHome-ZJ-WFMN-C-Single-Color # -# ------------------------------------------ -# OPERATION (as of v2.0) -# ------------------------------------------ -# 1. General-purpose LED controller. +# DEVICE GPIO (Magichome ESP8266) +# - GPIO02 Blue LED (used for ESPHome status) - I think... can't see the board +# - GPIO12 MOSFET output (0 V when switched) +#:########################################################################################:# +# OPERATION NOTES: +# 1. General-purpose LED controller. # 2. Designed for the Sinilink XY-WFMS board with a MOSFET output (claimed 5A, 5-36 V DC), but will suit similar mosfet boards. -# 3. (In SUBSTITUTIONS) setting for MAX % output to extend LED life (ie can ensure it is only ever 95%) -# 4. (In SUBSTITUTIONS) Minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. -# 5. (In SUBSTITUTIONS) PWM frequency is set to 1kHz by default. You can increase it, but higher values caused +# 3. (SUBSTITUTIONS) setting for MAX % output to extend LED life (e.g. ensure it is only ever 95%) +# 4. (SUBSTITUTIONS) Minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. +# 5. (SUBSTITUTIONS) PWM frequency is set to 1kHz by default. You can increase it, but higher values caused # resets on Sinilink device. On ESP32 you can run much higher (~40 kHz). # 6. Min/Max output settings are not exposed in Home Assistant/MQTT by default, but could be. # With a 1 MB flash, space is tight and only minimal optimisation has been done so far. @@ -32,42 +41,57 @@ # - Normal On/Off switch (quick ramp up/down, up to the level of previous brightness) # - Fade up/down times (0-60s) # - Output % (pre-gamma) and PWM % (post-gamma) -# - Output Set (1-100, respects min/max). This also changes with other output so reflects value. +# - Output Set (1-100, respects min/max). This also changes with other output so reflects value. # - Many device diagnostics (from the included 'diagnostics' package) # - Maximum 'on' time before automatic fade-down (1-48 h, 0 = no limit) -########################################################################################## -########################################################################################## -# Hardware: Magishome LED controller single channel (ESP8266, NOT the later ones with BL602) -# https://devices.esphome.io/devices/MagicHome-ZJ-WFMN-C-Single-Color -# ------------------------------------------ -# DEVICE GPIO (Magichome ESP8266) -# ------------------------------------------ -# GPIO02 Blue LED (used for ESPHome status) - I think... can't see the board -# GPIO12 MOSFET output (0 V when switched) -########################################################################################## -########################################################################################## +#:########################################################################################:# +# MQTT COMMANDS: +# Local MQTT light control: +# - ${mqtt_local_command_topic}/light/set -> ON,OFF +# +# Local MQTT light status: +# - ${mqtt_local_status_topic}/light/state -> ON,OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device remains controllable via MQTT local command topics +# - Status publishes to MQTT still occur (light state) +# - HA entities are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable from Home Assistant via API (light/switch/buttons/select/numbers) +# - MQTT local commands will not work and status publishes will fail while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available +# - SNTP not needed (no timeclocks; loss of network does not affect timing) +# - If power remains on, the controller continues running at the last state (including any running scripts) +# - If the device reboots while offline, restart behavior depends on the stored restart_mode and restore globals +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-breakfastbarleds" # yaml file should be device_name.yaml friendly_name: "Breakfast Bar LEDs" - description_comment: "LED Strip under the breakfast bar, upstairs lounge :: Magichome ESP8266" + description_comment: "LED Strip under the breakfast bar, upstairs lounge :: Magichome ESP8266 (Layout V1.1)" device_area: "Lounge" # Allows the ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Project details. Manufacturer before the dot, device after the dot. - project_version: "v2.0" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version + project_name: "Magichome Single Colour V1.1 LED Controller.Generic ESP8266" # Manufacturer before the dot, device after the dot. + project_version: "v2.0" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass - static_ip_address: !secret esp-breakfastbarleds_ip # CHANGE THIS - - # MQTT LOCAL Controls (This is just my local method of controlling via MQTT, I also use the built in method) + ota_pass: !secret esp-ota_pass + static_ip_address: !secret esp-breakfastbarleds_ip + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # MQTT LOCAL Controls (This is just my local method of controlling via MQTT, I also use the built in method) mqtt_local_device_name: "lounge-breakfastbarleds" mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic @@ -77,24 +101,24 @@ substitutions: mqtt_local_device_command_OFF: "OFF" # Device Specific Settings - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE - update_interval: "20s" # Update time for general sensors, etc. - led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM - minimum_led_output: "1" # % If at this value or below, we'll switch it completely off - maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics - max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off - pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts + log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE + update_interval: "20s" # Update time for general sensors, etc. + led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM + minimum_led_output: "1" # % If at this value or below, we'll switch it completely off + maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics + max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off + pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts # Device Specific GPIO (so we can easily update for other devices) - device_status_led: GPIO02 + device_status_led: GPIO02 device_mosfet_out: GPIO12 - device_usr_button: GPIO04 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml - device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml + device_usr_button: GPIO04 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml + device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -103,6 +127,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -116,22 +141,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome CORE CONFIGURATION +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -179,25 +205,11 @@ esphome: # Boot complete: allow OFF handlers again - lambda: 'id(booting) = false;' - # NEW: force indicator OFF after boot logic - # (Removed: output.turn_off: green_led_out) - -# Only if you want to play with build flags... -# platformio_options: -# build_unflags: -# - -flto -# build_flags: -# - -fno-lto -# - -Wl,--gc-sections -# - -ffunction-sections -# - -fdata-sections -# - -DNDEBUG - -########################################################################################## -# ESP PLATFORM AND FRAMEWORK +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp8266.html # https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp8266: board: esp01_1m restore_from_flash: true # restore some values on reboot @@ -208,118 +220,128 @@ mdns: preferences: flash_write_interval: 2min # enough time to update values for reboots, but not enough to wear flash -########################################################################################## -# GLOBAL VARIABLES +#:########################################################################################:# +# GLOBAL VARIABLES: # https://esphome.io/components/globals.html -########################################################################################## +#:########################################################################################:# globals: # Minimum Brightness % for LEDs (will switch off if <=) - id: min_brightness_pct type: int restore_value: true - initial_value: "${minimum_led_output}" # start/finish at X% + initial_value: "${minimum_led_output}" + # Maximum Brightness % for LEDs (should never go beyond this) - id: max_brightness_pct type: int restore_value: false - initial_value: "${maximum_led_output}" # hard cap; never exceed this - # The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever + initial_value: "${maximum_led_output}" + + # The maximum time the lights will stay on, in hours. 0 = forever - id: max_on_hours type: int restore_value: true initial_value: "${max_on_default_hours}" + # Compile time Gamma - id: led_gamma_f type: float restore_value: false - initial_value: ${led_gamma} # <-- numeric at compile time + initial_value: ${led_gamma} # numeric at compile time # Default Fading Up Time (Selectable and will be retained) - - id: ramp_up_ms # fade-in when turned ON + - id: ramp_up_ms type: int restore_value: true - initial_value: '5000' # 5 s + initial_value: "5000" # 5 s + # Default Fading Down Time (Selectable and will be retained) - - id: ramp_down_ms # fade-out when turned OFF + - id: ramp_down_ms type: int restore_value: true - initial_value: '10000' # 10 s + initial_value: "10000" # 10 s + # Action on Restart. (0=Fade full, 1=Restore brightness, 2=Remain off) - - id: restart_mode + - id: restart_mode type: int restore_value: true - initial_value: '0' # default = Fade Up to Full (so can be deployed with no other setup) + initial_value: "0" # default = Fade Up to Full # Determine last fade direction. - # true when you asked the light to end up ON (Ramp Up) - # false when you asked the light to end up OFF (Ramp Down) - id: ramp_switch_target_on type: bool restore_value: true - initial_value: 'false' + initial_value: "false" + # Prevent jitter when adjusting the slider - id: suppress_slider_sync type: bool restore_value: false - initial_value: 'false' - # actual 0..100 seen last time, for restart - - id: last_brightness_pct + initial_value: "false" + + # Actual 0..100 seen last time, for restart + - id: last_brightness_pct type: float restore_value: true - initial_value: '0.0' - # last published "Output Set (0-100)" integer + initial_value: "0.0" + + # Last published "Output Set (0-100)" integer - id: last_set_pos type: int restore_value: false - initial_value: '-1' - # helper to keep blink time == transition time + initial_value: "-1" + + # Helper to keep blink time == transition time - id: last_ramp_ms type: int restore_value: false - initial_value: '0' - # target for "Restore Brightness" scripted ramp + initial_value: "0" + + # Target for "Restore Brightness" scripted ramp - id: restore_target_pct type: float restore_value: false - initial_value: '0.0' - # true while a scripted ramp is in progress (to limit flash writes) + initial_value: "0.0" + + # True while a scripted ramp is in progress (to limit flash writes) - id: is_ramping type: bool restore_value: false - initial_value: 'false' - # guards OFF persistence during startup caused by restore_mode: ALWAYS_OFF + initial_value: "false" + + # Guards OFF persistence during startup caused by restore_mode: RESTORE_DEFAULT_OFF - id: booting type: bool restore_value: false - initial_value: 'true' - # true only while we are performing a ramp-down that briefly turns the light ON to hit the floor + initial_value: "true" + + # True only while we are performing a ramp-down that briefly turns the light ON to hit the floor - id: ramping_for_off type: bool restore_value: false - initial_value: 'false' + initial_value: "false" -########################################################################################## -# LOGGER COMPONENT +#:########################################################################################:# +# LOGGER COMPONENT: # https://esphome.io/components/logger.html -# Logs all log messages through the serial port and through MQTT topics. -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" # INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) + level: "${log_level}" + baud_rate: 0 # set to 0 for no logging via UART -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: ${device_status_led} inverted: true -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: # Light control to ramp up @@ -327,16 +349,17 @@ mqtt: payload: "${mqtt_local_device_command_ON}" then: - switch.turn_on: mosfet_ramp_switch + # Light control to ramp down - topic: "${mqtt_local_command_topic}/light/set" payload: "${mqtt_local_device_command_OFF}" then: - switch.turn_off: mosfet_ramp_switch -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: # Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce) - platform: template @@ -356,10 +379,10 @@ switch: - script.stop: ramp_on_script - script.execute: ramp_off_script -################################################################################################# -# BUTTON COMPONENT +#:########################################################################################:# +# BUTTON COMPONENT: # https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# button: # Start ramping UP (from current level) - platform: template @@ -369,7 +392,7 @@ button: on_press: - lambda: |- id(ramp_switch_target_on) = true; - id(mosfet_ramp_switch).publish_state(true); // reflect in HA immediately + id(mosfet_ramp_switch).publish_state(true); // reflect in HA immediately - script.stop: ramp_off_script - script.execute: ramp_on_script @@ -381,7 +404,7 @@ button: on_press: - lambda: |- id(ramp_switch_target_on) = false; - id(mosfet_ramp_switch).publish_state(false); // reflect in HA immediately + id(mosfet_ramp_switch).publish_state(false); // reflect in HA immediately - script.stop: ramp_on_script - script.execute: ramp_off_script @@ -391,7 +414,6 @@ button: name: "${friendly_name} Fade Stop" icon: mdi:pause on_press: - # Stop any pending scripts (and their delayed actions) - script.stop: ramp_on_script - script.stop: ramp_off_script - lambda: |- @@ -399,7 +421,7 @@ button: id(ramping_for_off) = false; id(is_ramping) = false; - // Freeze the light at its *current* level by overwriting the transition + // Freeze the light at its current level by overwriting the transition const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { auto call = id(mosfet_leds).make_call(); @@ -415,12 +437,10 @@ button: id(last_brightness_pct) = pct; } - - -######################################################################################### -# SELECT COMPONENT +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -######################################################################################### +#:########################################################################################:# select: - platform: template id: restart_action @@ -442,10 +462,10 @@ select: id(restart_mode) = 2; } -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio id: btn_gpio12 @@ -467,21 +487,21 @@ binary_sensor: # Target is currently ON -> press should go OFF (start ramp-down) - lambda: |- id(ramp_switch_target_on) = false; - id(mosfet_ramp_switch).publish_state(false); // reflect in HA immediately + id(mosfet_ramp_switch).publish_state(false); // reflect in HA immediately - script.stop: ramp_on_script - script.execute: ramp_off_script else: # Target is currently OFF -> press should go ON (start ramp-up) - lambda: |- id(ramp_switch_target_on) = true; - id(mosfet_ramp_switch).publish_state(true); // reflect in HA immediately + id(mosfet_ramp_switch).publish_state(true); // reflect in HA immediately - script.stop: ramp_off_script - script.execute: ramp_on_script -########################################################################################## -# SENSOR COMPONENT +#:########################################################################################:# +# SENSOR COMPONENT: # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: - platform: template id: mosfet_output_pct @@ -489,7 +509,7 @@ sensor: unit_of_measurement: "%" icon: mdi:percent accuracy_decimals: 0 - update_interval: 2s # consider 200ms if you want fewer updates + update_interval: 2s lambda: |- const auto &cv = id(mosfet_leds).current_values; return cv.is_on() ? (float) (int)(cv.get_brightness() * 100.0f + 0.5f) : 0.0f; @@ -530,28 +550,26 @@ sensor: if (pwm > 1.0f) pwm = 1.0f; return pwm * 100.0f; -########################################################################################## -# OUTPUT COMPONENT -# https://esphome.io/components/light/index.html -########################################################################################## -# An OUTPUT can be binary (0,1) or float, which is any value between 0 and 1. -# PWM Outputs such as "ledc" are float. https://esphome.io/components/output/ledc.html -########################################################################################## +#:########################################################################################:# +# OUTPUT COMPONENT: +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: mosfet_pwm pin: ${device_mosfet_out} frequency: ${pwm_frequency} + - platform: gpio - id: green_led_out # Green LED + id: green_led_out # Green LED pin: number: ${device_fading_led} inverted: false -########################################################################################## -# LIGHT COMPONENT +#:########################################################################################:# +# LIGHT COMPONENT: # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: monochromatic id: mosfet_leds @@ -582,7 +600,7 @@ light: - script.execute: max_on_watchdog # OFF: publish state, track intent, clear watchdog, and persist OFF so Mode 1 will not restore - # Guarded by booting flag so the automatic OFF at boot from ALWAYS_OFF does not zero persistence. + # Guarded by booting flag so the automatic OFF at boot from RESTORE_DEFAULT_OFF does not zero persistence. on_turn_off: - output.turn_off: green_led_out - if: @@ -607,18 +625,17 @@ light: const auto &cv = id(mosfet_leds).current_values; if (!cv.is_on()) return; const float b = cv.get_brightness(); - if (b <= cap + 0.001f) return; // no call if already at/under cap + if (b <= cap + 0.001f) return; auto call = id(mosfet_leds).make_call(); call.set_state(true); call.set_brightness(cap); call.set_transition_length(0); call.perform(); - -########################################################################################## -# NUMBER COMPONENT +#:########################################################################################:# +# NUMBER COMPONENT: # https://esphome.io/components/number/ -########################################################################################## +#:########################################################################################:# number: - platform: template id: cfg_ramp_up_s @@ -668,24 +685,22 @@ number: min_value: 0 max_value: 100 step: 1 - # Show current position mapped into 0..100 across [min..max] lambda: |- const auto &cv = id(mosfet_leds).current_values; - float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; // 0..100 actual + float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); - if (maxp <= minp) maxp = minp + 1.0f; // avoid div/0 - if (actual <= 0.0f) return 0.0f; // when OFF, show 0 + if (maxp <= minp) maxp = minp + 1.0f; + if (actual <= 0.0f) return 0.0f; float pos = (actual - minp) * 100.0f / (maxp - minp); if (pos < 0.0f) pos = 0.0f; if (pos > 100.0f) pos = 100.0f; - return floorf(pos + 0.5f); // integer + return floorf(pos + 0.5f); set_action: - if: condition: lambda: 'return x <= 0.0f;' then: - # 0 means OFF - lambda: 'id(suppress_slider_sync) = true;' - script.stop: ramp_on_script - script.stop: ramp_off_script @@ -695,16 +710,15 @@ number: - lambda: |- id(ramp_switch_target_on) = false; id(led_output_set_pct).publish_state(0); - id(last_brightness_pct) = 0.0f; // persist OFF immediately + id(last_brightness_pct) = 0.0f; id(last_set_pos) = 0; - delay: 400ms - lambda: 'id(suppress_slider_sync) = false;' else: - # Map 1..100 - [min..max] and set ON - lambda: |- id(suppress_slider_sync) = true; - float pos = x; // 0..100 - if (pos < 1.0f) pos = 1.0f; // 0 is OFF + float pos = x; + if (pos < 1.0f) pos = 1.0f; if (pos > 100.0f) pos = 100.0f; id(led_output_set_pct).publish_state((int) floorf(pos + 0.5f)); - script.stop: ramp_off_script @@ -712,7 +726,7 @@ number: - light.turn_on: id: mosfet_leds brightness: !lambda |- - float pos = id(led_output_set_pct).state; // 1..100 + float pos = id(led_output_set_pct).state; float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); if (maxp <= minp) maxp = minp + 1.0f; @@ -722,13 +736,13 @@ number: transition_length: 250ms - lambda: |- id(ramp_switch_target_on) = true; - float pos = id(led_output_set_pct).state; // 1..100 + float pos = id(led_output_set_pct).state; float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); if (maxp <= minp) maxp = minp + 1.0f; float out_pct = minp + (pos * (maxp - minp) / 100.0f); if (out_pct > maxp) out_pct = maxp; - id(last_brightness_pct) = out_pct; // persist exact target now + id(last_brightness_pct) = out_pct; - delay: 400ms - lambda: 'id(suppress_slider_sync) = false;' @@ -762,19 +776,18 @@ number: then: - script.execute: max_on_watchdog -########################################################################################## -# SCRIPT COMPONENT +#:########################################################################################:# +# SCRIPT COMPONENT: # https://esphome.io/components/script.html -# Scripts can be executed nearly anywhere in your device configuration with a single call. -########################################################################################## +#:########################################################################################:# script: - - # Script: ramp up from current level. Obey global max. (LED ON while ramping) + # Script: ramp up from current level. Obey global max. - id: ramp_on_script mode: restart then: - lambda: 'id(is_ramping) = true;' - script.stop: ramp_off_script + # Ensure we start at at least the floor without a visible "pop". - if: condition: @@ -787,6 +800,7 @@ script: id: mosfet_leds brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' transition_length: 80ms + # Ramp from current (>= floor) to cap over a fraction of ramp_up_ms. - light.turn_on: id: mosfet_leds @@ -810,21 +824,23 @@ script: if (frac > 1.0f) frac = 1.0f; id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); return (uint32_t) id(last_ramp_ms); + - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - lambda: |- id(is_ramping) = false; const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { float pct = cv.get_brightness() * 100.0f; - id(last_brightness_pct) = pct; // persist final level + id(last_brightness_pct) = pct; } - # Script: ramp to a specific target (Restore Brightness path). (LED ON while ramping) + # Script: ramp to a specific target (Restore Brightness path). - id: ramp_to_target_script mode: restart then: - lambda: 'id(is_ramping) = true;' - script.stop: ramp_off_script + # Ensure we start at the floor cleanly. - if: condition: @@ -837,6 +853,7 @@ script: id: mosfet_leds brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' transition_length: 80ms + # Ramp from current (>= floor) to restore_target_pct over a fraction of ramp_up_ms. - light.turn_on: id: mosfet_leds @@ -866,17 +883,17 @@ script: if (frac > 1.0f) frac = 1.0f; id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac); return (uint32_t) id(last_ramp_ms); + - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - lambda: |- id(is_ramping) = false; const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { float pct = cv.get_brightness() * 100.0f; - id(last_brightness_pct) = pct; // persist final level + id(last_brightness_pct) = pct; } - - # Script: ramp down from current level to floor, then cleanly cut to OFF. (LED ON while ramping) + # Script: ramp down from current level to floor, then cleanly cut to OFF. - id: ramp_off_script mode: restart then: @@ -884,6 +901,7 @@ script: id(is_ramping) = true; id(ramping_for_off) = true; - script.stop: ramp_on_script + - light.turn_on: id: mosfet_leds brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' @@ -899,6 +917,7 @@ script: if (frac > 1.0f) frac = 1.0f; id(last_ramp_ms) = (int) (id(ramp_down_ms) * frac); return (uint32_t) id(last_ramp_ms); + - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - light.turn_off: id: mosfet_leds @@ -907,7 +926,7 @@ script: - lambda: |- id(is_ramping) = false; id(ramping_for_off) = false; - id(last_brightness_pct) = 0.0f; // persist OFF for restore path + id(last_brightness_pct) = 0.0f; id(last_set_pos) = 0; id(led_output_set_pct).publish_state(0); @@ -933,7 +952,7 @@ script: - id: deferred_restore_brightness mode: restart then: - - delay: 5s # let preferences/globals load and light settle + - delay: 5s # let preferences/globals load and light settle - lambda: |- // Use ONLY the exact last saved brightness. float target = id(last_brightness_pct); @@ -951,7 +970,7 @@ script: lambda: 'return id(restore_target_pct) > 0.5f;' then: - lambda: |- - id(ramp_switch_target_on) = true; // reflect our intent + id(ramp_switch_target_on) = true; id(suppress_slider_sync) = true; - script.stop: ramp_off_script - script.execute: ramp_to_target_script @@ -962,5 +981,4 @@ script: - lambda: 'id(ramp_switch_target_on) = false;' - light.turn_off: id: mosfet_leds - transition_length: 0s - # (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp \ No newline at end of file + transition_length: 0s \ No newline at end of file diff --git a/esphome/esp-centralstairs-bottom.yaml b/esphome/esp-centralstairs-bottom.yaml index 3676577..3b8d493 100644 --- a/esphome/esp-centralstairs-bottom.yaml +++ b/esphome/esp-centralstairs-bottom.yaml @@ -1,67 +1,98 @@ -########################################################################################## -########################################################################################## -# CENTRAL STAIRS - BOTTOM LIGHTSWITCH -# V3.7 2025-09-24 upload to this device +#:########################################################################################:# +# TITLE: CENTRAL STAIRS - BOTTOM LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-centralstairs-bottom.yaml +#:########################################################################################:# +# VERSIONS: +# V3.7 2025-09-24 Upload to this device # V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# HARDWARE: +# Zemismart KS-811 Double push button (KS-811-2) +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Light switch at bottom of the central stairs +# - Button 1 toggles Relay 1 (Main Stair Lights - Lower) - physically connected +# - Button 2 controls Stair Footer Lights via MQTT (remote device), using Relay 2 as a local mirror state +# - On MQTT connect, publishes current Relay 1 state to mqtt_status_topic_1 to keep remote status aligned +#:########################################################################################:# +# MQTT COMMANDS: +# Remote device 1 (Main Stair Lights): +# - Command topic: ${mqtt_command_topic_1} -> ON,OFF +# - Status topic: ${mqtt_status_topic_1} -> ON,OFF # -# NOTES -# - Light switch at top of the stairs, only the footer lights physically connected. -# -########################################################################################## -########################################################################################## +# Remote device 2 (Stair Footer Lights): +# - Command topic: ${mqtt_command_topic_2} -> ON,OFF +# - Status topic: ${mqtt_status_topic_2} -> ON,OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Physical buttons still operate (Relay 1 local toggle; Button 2 publishes MQTT for footer lights) +# - Relay 1 state continues to be published to MQTT status topic +# - HA entities are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Relay 1 still toggles locally and remains controllable from HA via API +# - Button 2 cannot control footer lights (MQTT publish fails) +# - Any MQTT state sync to remote devices will not occur while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - Physical button 1 continues to toggle Relay 1 locally (standalone) +# - Physical button 2 cannot control footer lights (no network transport) +# - Timeclocks will drift without network (SNTP). Time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Custom Naming device_name: "esp-centralstairs-bottom" friendly_name: "Central Stair Lightswitch - Bottom (2)" - description_comment: "Central Stair Lightswitch - Bottom, using Zemismart KS-811 Double Push Button. Main Stair Lights (1), Stair Footer Lights (2)" + description_comment: "Central Stair Lightswitch - Bottom, using Zemismart KS-811 Double Push Button. Main Stair Lights (1), Stair Footer Lights (2) (Layout V1.1)" device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + + # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-centralstairs-bottom_ip + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # MQTT Device Names mqtt_device_name_1: "stair-mainlights" mqtt_device_name_2: "stair-footerlights" # I/O Naming switch_1_name: "Main Stair Lights (Lower)" # Physical, but just the lower lights below the media cabinet switch_2_name: "Stair Footer Lights" # virtual only, nothing connected to this output - #relay_1_name: "Garage Lights" - #button_1_name: "Power Button" - #relay_icon: "mdi:lightbulb-group" # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # MQTT Controls mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic - mqtt_command_topic_1: "${mqtt_command_main_topic}/${mqtt_device_name_1}" + mqtt_command_topic_1: "${mqtt_command_main_topic}/${mqtt_device_name_1}" mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}" - mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}" + mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}" mqtt_status_topic_2: "${mqtt_status_main_topic}/${mqtt_device_name_2}" mqtt_command_ON: "ON" mqtt_command_OFF: "OFF" - # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) - api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass - # General Settings log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + update_interval: "60s" # update time for general sensors etc -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -70,6 +101,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -83,23 +115,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -108,39 +140,39 @@ esphome: project: name: "${project_name}" version: "${project_version}" - #on_boot: + #on_boot: # priority: 200 # then: # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -######################################################################################### +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_connect: then: - if: - # Status of relay 1, which has an actual light connected condition: lambda: 'return id(Relay_1).state;' then: @@ -199,26 +231,26 @@ mqtt: then: - switch.turn_off: Relay_2 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # GPIO16 does not support interrupts so use polling (suppresses warning). filters: - delayed_on: 30ms - delayed_off: 30ms @@ -230,7 +262,7 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true filters: - delayed_on: 30ms - delayed_off: 30ms @@ -251,10 +283,10 @@ binary_sensor: payload: "${mqtt_command_ON}" retain: false -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -275,4 +307,4 @@ switch: name: "Relay 2: ${switch_2_name}" pin: GPIO12 id: Relay_2 - # No mqtt.publish here (this is a mirror only) + # No mqtt.publish here (this is a mirror only) \ No newline at end of file diff --git a/esphome/esp-centralstairs-top.yaml b/esphome/esp-centralstairs-top.yaml index f5b1179..981175d 100644 --- a/esphome/esp-centralstairs-top.yaml +++ b/esphome/esp-centralstairs-top.yaml @@ -1,67 +1,99 @@ -########################################################################################## -########################################################################################## -# CENTRAL STAIRS - TOP LIGHTSWITCH -# V3.7 2025-09-24 upload to this device +#:########################################################################################:# +# TITLE: CENTRAL STAIRS - TOP LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-centralstairs-top.yaml +#:########################################################################################:# +# VERSIONS: +# V3.7 2025-09-24 Upload to this device # V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# HARDWARE: +# Zemismart KS-811 Double push button (KS-811-2) +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Light switch at top of the central stairs +# - Button 1 controls Main Stair Lights via MQTT (remote device), using Relay 1 as a local mirror state +# - Button 2 toggles Relay 2 (Stair Footer Lights) - physically connected +# - On MQTT connect, publishes current Relay 2 state to mqtt_status_topic_2 to keep remote status aligned +#:########################################################################################:# +# MQTT COMMANDS: +# Remote device 1 (Main Stair Lights): +# - Command topic: ${mqtt_command_topic_1} -> ON,OFF +# - Status topic: ${mqtt_status_topic_1} -> ON,OFF # -# NOTES -# - Light switch at top of the stairs -# -########################################################################################## -########################################################################################## +# Remote device 2 (Stair Footer Lights): +# - Command topic: ${mqtt_command_topic_2} -> ON,OFF +# - Status topic: ${mqtt_status_topic_2} -> ON,OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Button 1 continues to publish MQTT commands for main stair lights +# - Button 2 continues to toggle Relay 2 locally +# - Relay 2 state continues to be published to mqtt_status_topic_2 +# - HA entities are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Button 2 still toggles Relay 2 locally and is controllable via HA API +# - Button 1 cannot control main stair lights (MQTT publish fails) +# - Any MQTT state sync to remote devices will not occur while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - Button 2 continues to toggle Relay 2 locally (standalone) +# - Button 1 cannot control main stair lights (no network transport) +# - Timeclocks will drift without network (SNTP). Time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Custom Naming device_name: "esp-centralstairs-top" friendly_name: "Central Stair Lightswitch - Top (2)" - description_comment: "Central Stair Lightswitch - Top, using Zemismart KS-811 Double Push Button. Main Stair Lights (1), Stair Footer Lights (2)" + description_comment: "Central Stair Lightswitch - Top, using Zemismart KS-811 Double Push Button. Main Stair Lights (1), Stair Footer Lights (2) (Layout V1.1)" device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + + # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-centralstairs-top_ip + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # MQTT Device Names mqtt_device_name_1: "stair-mainlights" mqtt_device_name_2: "stair-footerlights" # I/O Naming switch_1_name: "Main Stair Lights" # virtual only, nothing connected to this output switch_2_name: "Stair Footer Lights" # Footer lights connected to this relay - #relay_1_name: "Garage Lights" - #button_1_name: "Power Button" - #relay_icon: "mdi:lightbulb-group" # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # MQTT Controls mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic - mqtt_command_topic_1: "${mqtt_command_main_topic}/${mqtt_device_name_1}" + mqtt_command_topic_1: "${mqtt_command_main_topic}/${mqtt_device_name_1}" mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}" - mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}" + mqtt_command_topic_2: "${mqtt_command_main_topic}/${mqtt_device_name_2}" mqtt_status_topic_2: "${mqtt_status_main_topic}/${mqtt_device_name_2}" mqtt_command_ON: "ON" mqtt_command_OFF: "OFF" - # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) - api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass - # General Settings log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + update_interval: "60s" # update time for general sensors etc -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -70,6 +102,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -83,23 +116,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -108,39 +141,39 @@ esphome: project: name: "${project_name}" version: "${project_version}" - #on_boot: + #on_boot: # priority: 200 # then: # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_connect: then: - if: - # Status of relay 1, which has an actual light connected condition: lambda: 'return id(Relay_2).state;' then: @@ -199,32 +232,32 @@ mqtt: then: - switch.turn_off: Relay_2 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # GPIO16 does not support interrupts so use polling (suppresses warning). filters: - delayed_on: 30ms - delayed_off: 30ms name: "Button 1: ${switch_1_name}" on_press: - # Toggle the remote Main Stair Lights (lower) via COMMAND topic, based on our mirrored state + # Toggle the remote Main Stair Lights via COMMAND topic, based on our mirrored state - if: condition: lambda: 'return id(Relay_1).state;' @@ -243,7 +276,7 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true filters: - delayed_on: 30ms - delayed_off: 30ms @@ -251,10 +284,10 @@ binary_sensor: on_press: - switch.toggle: Relay_2 -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -275,6 +308,4 @@ switch: - mqtt.publish: topic: "${mqtt_status_topic_2}" payload: "${mqtt_command_OFF}" - retain: false - - + retain: false \ No newline at end of file diff --git a/esphome/esp-datacupboardfans.yaml b/esphome/esp-datacupboardfans.yaml index 52a5322..6ba4757 100644 --- a/esphome/esp-datacupboardfans.yaml +++ b/esphome/esp-datacupboardfans.yaml @@ -1,43 +1,69 @@ -########################################################################################## -########################################################################################## -# DATA CUPBOARD FAN CONTROL -# Fan control for Data Cupboard -# -# Hardware: Yunshan 7-30V 10A Relay Board (HW-622) with ESP8266MOD -# +#:########################################################################################:# +# TITLE: DATA CUPBOARD FAN CONTROL +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-datacupboardfans.yaml +#:########################################################################################:# +# VERSIONS: # V1.3 2026-02-20 Remove invalid allow_other_uses on pulse_counter pins (ESPHome 2026.2.x) # V1.2 2026-02-20 Use common SNTP package, and publish fan fault/status via interval script # V1.1 2026-02-20 Fix template binary_sensor update method for ESPHome 2026.2.x # V1.0 2026-02-20 Initial Version -# -# NOTES +#:########################################################################################:# +# HARDWARE: +# Yunshan 7-30V 10A Relay Board (HW-622) with ESP8266MOD +#:########################################################################################:# +# OPERATION NOTES: # - Fan tach inputs are on GPIO1/GPIO3 (UART pins). Logger UART is disabled (baud_rate: 0). # - DHT22 data is on GPIO0 (boot-strap pin). Usually OK, but if you ever get boot issues, # move the DHT22 to a different GPIO if your board allows. # - Using common/sntp_common.yaml for time and diagnostic time text sensors. -########################################################################################## -########################################################################################## +# - Thermostat logic uses hysteresis thresholds (On temp / Off temp) plus a manual override. +# - Fan fault is evaluated periodically, with grace windows after boot and relay changes. +#:########################################################################################:# +# MQTT COMMANDS: +# Base topic: ${mqtt_main_topic} +# - ${mqtt_main_topic}/relay/set : ON,OFF +# - ${mqtt_main_topic}/override/set : ON,OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Fan control logic still runs on-device (thermostat + override) +# - MQTT commands still work and fan status/fault still publishes via MQTT (common_mqtt) +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Fan control logic still runs on-device (thermostat + override) +# - HA can still control entities via API, but MQTT command topics will not work +# c) Entire WiFi/Network OFFLINE +# - Fan control logic still runs on-device (thermostat + override) +# - Timeclocks will drift without network (SNTP). Time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS -########################################################################################## +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions +# If NOT using a secrets file, just replace these with the passwords etc (in quotes) +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-datacupboardfans" friendly_name: "Data Cupboard Fans" - description_comment: "Fan control for Data Cupboard" + description_comment: "Fan control for Data Cupboard (Layout V1.1)" device_area: "Data Cupboard" # Project Naming project_name: "Yunshan.HW-622 ESP8266MOD Relay Board" project_version: "v1.3" - # Passwords + # Passwords and Secrets (Unfortunately, you cannot use substitutions inside secret names) api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-datacupboardfans_ip mqtt_command_main_topic: !secret mqtt_command_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # MQTT Controls mqtt_device_name: "data-cupboard-fans" mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" @@ -67,9 +93,10 @@ substitutions: default_temp_on: "35" default_temp_off: "28" -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages -########################################################################################## +# https://esphome.io/components/packages.html +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -78,6 +105,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API #### common_api: !include @@ -99,9 +127,10 @@ packages: diag_basic: !include common/include_basic_diag_sensors.yaml diag_more: !include common/include_more_diag_sensors.yaml -########################################################################################## -# ESPHome -########################################################################################## +#:########################################################################################:# +# ESPHOME: +# https://esphome.io/components/esphome.html +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -120,9 +149,11 @@ esphome: - script.execute: apply_fan_control - script.execute: evaluate_fan_fault -########################################################################################## -# ESP Platform and Framework -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp12e restore_from_flash: true @@ -133,75 +164,87 @@ preferences: mdns: disabled: false -########################################################################################## -# LOGGING -########################################################################################## +#:########################################################################################:# +# LOGGING: +# https://esphome.io/components/logger.html +#:########################################################################################:# logger: level: "${log_level}" baud_rate: 0 -########################################################################################## -# GLOBALS -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/components/globals.html +#:########################################################################################:# globals: # Max temperature tracking - id: g_max_temp_today type: float - restore_value: yes + restore_value: true initial_value: "-1000.0" + - id: g_max_temp_yesterday type: float - restore_value: yes + restore_value: true initial_value: "-1000.0" + - id: g_max_temp_month type: float - restore_value: yes + restore_value: true initial_value: "-1000.0" + - id: g_max_temp_last_month type: float - restore_value: yes + restore_value: true initial_value: "-1000.0" + - id: g_max_temp_year type: float - restore_value: yes + restore_value: true initial_value: "-1000.0" # Last seen date parts (for rollover) - id: g_last_day type: int - restore_value: yes + restore_value: true initial_value: "0" + - id: g_last_month type: int - restore_value: yes + restore_value: true initial_value: "0" + - id: g_last_year type: int - restore_value: yes + restore_value: true initial_value: "0" # Fault evaluation grace timing - id: boot_ms type: uint32_t - restore_value: no - initial_value: "0" - - id: relay_last_change_ms - type: uint32_t - restore_value: no + restore_value: false initial_value: "0" -########################################################################################## -# INTERVAL (periodic evaluations) + - id: relay_last_change_ms + type: uint32_t + restore_value: false + initial_value: "0" + +#:########################################################################################:# +# INTERVAL: +# https://esphome.io/components/interval.html +#:########################################################################################:# +# Periodic evaluations # NOTE: common_sntp also defines its own interval (60s) for its fallback clock. -########################################################################################## interval: - interval: 5s then: - script.execute: evaluate_fan_fault -########################################################################################## -# SWITCHES (Relay + Override) -########################################################################################## +#:########################################################################################:# +# SWITCHES: +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: # Relay output (GPIO4) - powers both fans - platform: gpio @@ -239,9 +282,11 @@ switch: - script.execute: apply_fan_control - script.execute: evaluate_fan_fault -########################################################################################## -# NUMBERS (On/Off thresholds with hysteresis) -########################################################################################## +#:########################################################################################:# +# NUMBERS: +# https://esphome.io/components/number/ +#:########################################################################################:# +# On/Off thresholds with hysteresis number: - platform: template name: "Fans On Temperature" @@ -275,9 +320,10 @@ number: set_action: - script.execute: apply_fan_control -########################################################################################## -# BINARY SENSORS (Door + Fault) -########################################################################################## +#:########################################################################################:# +# BINARY SENSORS: +# https://esphome.io/components/binary_sensor/ +#:########################################################################################:# binary_sensor: # Door status on GPIO5 - platform: gpio @@ -298,17 +344,19 @@ binary_sensor: id: fan_fault device_class: problem -########################################################################################## -# STATUS LED (GPIO2) -########################################################################################## +#:########################################################################################:# +# STATUS LED: +# https://esphome.io/components/status_led.html +#:########################################################################################:# status_led: pin: number: GPIO2 inverted: true -########################################################################################## -# SENSORS (Temp/Humidity + Fan RPM + Max temp templates) -########################################################################################## +#:########################################################################################:# +# SENSORS: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: # DHT22 on GPIO0 - platform: dht @@ -419,19 +467,22 @@ sensor: lambda: |- return id(g_max_temp_year); -########################################################################################## -# TEXT SENSOR (Normal/Fault status) - published by script +#:########################################################################################:# +# TEXT SENSORS: +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# +# Normal/Fault status - published by script # NOTE: common_sntp also defines its own text_sensors (time status etc). -########################################################################################## text_sensor: - platform: template name: "${fan_status_name}" id: fan_status icon: "mdi:fan-alert" -########################################################################################## -# SCRIPTS -########################################################################################## +#:########################################################################################:# +# SCRIPTS: +# https://esphome.io/components/script.html +#:########################################################################################:# script: # Apply fan control logic (override + hysteresis thresholds) - id: apply_fan_control @@ -498,9 +549,6 @@ script: const float req = id(fan_relay).state ? ${rpm_min_when_relay_on} : ${rpm_min_when_relay_off}; - // Requirement as requested: - // - Relay OFF => both fans must be > 1800 RPM - // - Relay ON => both fans must be > 3000 RPM const bool fault = (r1 < req) || (r2 < req); id(fan_fault).publish_state(fault); @@ -569,9 +617,9 @@ script: id(max_temp_last_month).publish_state(id(g_max_temp_last_month)); id(max_temp_year).publish_state(id(g_max_temp_year)); -########################################################################################## -# MQTT COMMANDS (device-specific) -########################################################################################## +#:########################################################################################:# +# MQTT (DEVICE-SPECIFIC COMMAND SUBSCRIPTIONS): +#:########################################################################################:# mqtt: on_message: # Relay control diff --git a/esphome/esp-datacupboardpower-left.yaml b/esphome/esp-datacupboardpower-left.yaml index 593bdc8..929eccc 100644 --- a/esphome/esp-datacupboardpower-left.yaml +++ b/esphome/esp-datacupboardpower-left.yaml @@ -1,24 +1,43 @@ -########################################################################################## -########################################################################################## -# DATA CUPBOARD POWER MONITOR - LEFT -# -# Controlled by a Athom Smart Plug V2 No Relay -# https://github.com/athom-tech/athom-configs/blob/main/athom-without-relay-plug.yaml -# +#:########################################################################################:# +# TITLE: DATA CUPBOARD POWER MONITOR - LEFT +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-datacupboardpower-left.yaml +#:########################################################################################:# +# VERSIONS: # V1.0 2025-08-28 First Setup -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# Athom Smart Plug V2 (No Relay) - Power Monitor +# https://github.com/athom-tech/athom-configs/blob/main/athom-without-relay-plug.yaml +#:########################################################################################:# +# OPERATION NOTES: +# - Power monitoring only (no relay) +# - Uses Athom common package: common/athompowermonv2norelay_common.yaml +# - Energy sensor can be hidden via hide_energy_sensor substitution +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device continues metering and publishing via MQTT (common_mqtt) +# - HA entities are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device continues metering and HA can read values via API +# - MQTT publish/subscribe will not function while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - Device continues metering locally but cannot report data to HA/MQTT +# - Timeclocks will drift without network (SNTP). Time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-datacupboardpower-left" friendly_name: "Data Cupboard Power Monitor - Left" - description_comment: "Data Cupboard Left :: Athom Smart Plug Power V2 (No relay)" + description_comment: "Data Cupboard Left :: Athom Smart Plug Power V2 (No relay) (Layout V1.1)" device_area: "Data Cupboard" # Project Naming @@ -30,20 +49,22 @@ substitutions: ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-datacupboardpower-left_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device General Settings - log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for general sensors etc + log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # Device Specific Settings (Athom Power Monitor Plug V2) sensor_update_interval: "10s" - hide_energy_sensor: "true" # boolean (used by "internal:") + hide_energy_sensor: "true" # boolean (used by "internal:") -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -52,6 +73,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -65,21 +87,20 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 - # Device Specific included packages - # Athom Power Monitor Plug V2 (No Relay) + #### DEVICE SPECIFIC: Athom Power Monitor Plug V2 (No Relay) #### common_athompowermonV2: !include file: common/athompowermonv2norelay_common.yaml vars: @@ -87,10 +108,10 @@ packages: sensor_update_interval: "${sensor_update_interval}" hide_energy_sensor: "${hide_energy_sensor}" -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -102,10 +123,10 @@ esphome: name: "${project_name}" version: "${project_version}" -########################################################################################## -# ESP Platform and Framework +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp8266.html -########################################################################################## +#:########################################################################################:# esp8266: board: esp8285 restore_from_flash: true @@ -117,11 +138,10 @@ preferences: mdns: disabled: false -########################################################################################## -# ESPHome LOGGING +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: level: "${log_level}" - baud_rate: 0 # free UART for CSE7766 - + baud_rate: 0 # free UART for CSE7766 \ No newline at end of file diff --git a/esphome/esp-datacupboardpower-right.yaml b/esphome/esp-datacupboardpower-right.yaml index b1576f2..43909d0 100644 --- a/esphome/esp-datacupboardpower-right.yaml +++ b/esphome/esp-datacupboardpower-right.yaml @@ -1,50 +1,71 @@ - -########################################################################################## -########################################################################################## -# DATA CUPBOARD POWER MONITOR - RIGHT -# -# Controlled by a Athom Smart Plug V2 No Relay -# https://github.com/athom-tech/athom-configs/blob/main/athom-without-relay-plug.yaml -# +#:########################################################################################:# +# TITLE: DATA CUPBOARD POWER MONITOR - RIGHT +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-datacupboardpower-right.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.0 2025-08-28 First Setup -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# Athom Smart Plug V2 (No Relay) - Power Monitor +# https://github.com/athom-tech/athom-configs/blob/main/athom-without-relay-plug.yaml +#:########################################################################################:# +# OPERATION NOTES: +# - Power monitoring only (no relay) +# - Uses Athom common package: common/athompowermonv2norelay_common.yaml +# - Energy sensor can be hidden via hide_energy_sensor substitution +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device continues metering and publishing via MQTT (common_mqtt) +# - HA entities are unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device continues metering and HA can read values via API +# - MQTT publish/subscribe will not function while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - Device continues metering locally but cannot report data to HA/MQTT +# - SNTP not needed (no timeclocks; loss of network does not affect timing) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-datacupboardpower-right" friendly_name: "Data Cupboard Power Monitor - Right" - description_comment: "Data Cupboard Right :: Athom Smart Plug Power V2 (No relay)" + description_comment: "Data Cupboard Right :: Athom Smart Plug Power V2 (No relay) (Layout V1.1)" device_area: "Data Cupboard" # Project Naming project_name: "Athom Technology.Smart Plug V2 NR" - project_version: "v1.0" + project_version: "v1.1" # Passwords (unfortunately you cannot use substitutions inside secrets names) api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-datacupboardpower-right_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device General Settings - log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for general sensors etc + log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # Device Specific Settings (Athom Power Monitor Plug V2) sensor_update_interval: "10s" - hide_energy_sensor: "true" # boolean (used by "internal:") + hide_energy_sensor: "true" # boolean (used by "internal:") -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -53,6 +74,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -66,21 +88,20 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 - # Device Specific included packages - # Athom Power Monitor Plug V2 (No Relay) + #### DEVICE SPECIFIC: Athom Power Monitor Plug V2 (No Relay) #### common_athompowermonV2: !include file: common/athompowermonv2norelay_common.yaml vars: @@ -88,10 +109,10 @@ packages: sensor_update_interval: "${sensor_update_interval}" hide_energy_sensor: "${hide_energy_sensor}" -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -103,10 +124,10 @@ esphome: name: "${project_name}" version: "${project_version}" -########################################################################################## -# ESP Platform and Framework +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp8266.html -########################################################################################## +#:########################################################################################:# esp8266: board: esp8285 restore_from_flash: true @@ -118,10 +139,10 @@ preferences: mdns: disabled: false -########################################################################################## -# ESPHome LOGGING +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: level: "${log_level}" - baud_rate: 0 # free UART for CSE7766 \ No newline at end of file + baud_rate: 0 # free UART for CSE7766 \ No newline at end of file diff --git a/esphome/esp-downstairsdishwasher.yaml b/esphome/esp-downstairsdishwasher.yaml index cd8cb73..7ef924f 100644 --- a/esphome/esp-downstairsdishwasher.yaml +++ b/esphome/esp-downstairsdishwasher.yaml @@ -1,55 +1,83 @@ -########################################################################################## -########################################################################################## -# DOWNSTAIRS DISHWASHER POWER MONITOR -# -# Controlled by a Athom Smart Plug V1 -# package_import_url: github://athom-tech/athom-configs/athom-smart-plug.yaml -# +#:########################################################################################:# +# TITLE: DOWNSTAIRS DISHWASHER POWER MONITOR +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstdishwasher.yaml +#:########################################################################################:# +# VERSIONS: +# V1.4 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.3 2025-08-27 Changed to Athom V2 # V1.2 2025-06-15 Changed to Athom V1 # V1.1 2025-06-12 Tidyups and packages added -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# Athom Smart Plug V2 (ESP8285) with power monitoring +# - Power monitoring handled by: common/athompowermonv2_common.yaml +#:########################################################################################:# +# OPERATION NOTES: +# - Power monitoring smart plug for the downstairs dishwasher. +# - Uses common WiFi, API, MQTT, SNTP, and diagnostics packages. +# - "Power On State" select controls restore behavior using the restore_mode global: +# - Always Off +# - Always On +# - Restore Previous State +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device continues measuring power locally. +# - MQTT topics (if used elsewhere) and network remain available; HA entities will be unavailable until HA returns. +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable/visible from Home Assistant via API. +# - MQTT functionality from common_mqtt (publishes/subscribes) will not work while MQTT is down. +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available. +# - Device continues operating locally using last stored settings. +# - Accurate time is NOT needed (SNTP not needed) for core plug operation. +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-downstdishwasher" friendly_name: "Downstairs Dishwasher Power" - description_comment: "Downstairs Dishwasher Power :: Athom Smart Plug Power V2" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - + description_comment: "Downstairs Dishwasher Power :: Athom Smart Plug Power V2 (Layout V1.1)" + device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + # Project Naming - project_name: "Athom Technology.Smart Plug V2" # Project Details - project_version: "v1.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Athom Technology.Smart Plug V2" + project_version: "v1.4" # Passwords (unfortunately you can't use substitutions inside secrets names) api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-downstdishwasher_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device General Settings - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # Device Specific Settings # Athom Power Monitor Plug V2 - relay_icon: "mdi:power-socket-au" - current_limit: "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. + relay_icon: "mdi:power-socket-au" + current_limit: "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. sensor_update_interval: "10s" relay_restore_mode: RESTORE_DEFAULT_ON hide_energy_sensor: "true" -########################################################################################## + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -58,6 +86,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -71,18 +100,18 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 # Device Specific included packages # Athom Power Monitor Plug @@ -96,15 +125,16 @@ packages: power_plug_type: "${relay_icon}" hide_energy_sensor: "${hide_energy_sensor}" -########################################################################################## -# ESPHome + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" #Appears on the esphome page in HA - area: "${device_area}" + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" name_add_mac_suffix: false min_version: 2024.6.0 project: @@ -116,27 +146,27 @@ esphome: - select.set_index: id: power_mode index: !lambda |- - return id(restore_mode)-1; + return id(restore_mode) - 1; - lambda: |- - switch(id(restore_mode)) - { - case 1:{ - id(relay).turn_off(); - break; - } - case 2:{ - id(relay).turn_on(); - break; - } - default:{ - break; - } + switch (id(restore_mode)) { + case 1: { + id(relay).turn_off(); + break; } + case 2: { + id(relay).turn_on(); + break; + } + default: { + break; + } + } -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp8285 restore_from_flash: true # mainly for calculating cumulative energy, but not that important here @@ -148,18 +178,20 @@ preferences: mdns: disabled: false -########################################################################################## -# ESPHome LOGGING -# https://esphome.io/components/logger.html -########################################################################################## -logger: - level: "${log_level}" - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) -########################################################################################## -# GLOBAL VARIABLES -# https://esphome.io/guides/automations.html?highlight=globals#global-variables -########################################################################################## +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable +# https://esphome.io/components/logger.html +#:########################################################################################:# +logger: + level: "${log_level}" + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg power monitor UART) + + +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/guides/automations.html#global-variables +#:########################################################################################:# globals: # 0 = Always_Off. 1 = Restore_Power_Off. 2 = Always_On. - id: restore_mode @@ -167,14 +199,15 @@ globals: restore_value: yes initial_value: "2" -########################################################################################## -# SELECT COMPONENT + +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -########################################################################################## +#:########################################################################################:# select: - platform: template name: "Power On State" - id: "power_mode" + id: power_mode optimistic: true icon: mdi:electric-switch options: @@ -184,4 +217,4 @@ select: on_value: then: - lambda: |- - id(restore_mode)=i+1; \ No newline at end of file + id(restore_mode) = i + 1; \ No newline at end of file diff --git a/esphome/esp-downstairskitchleds.yaml b/esphome/esp-downstairskitchleds.yaml index 1d51fe4..78e096b 100644 --- a/esphome/esp-downstairskitchleds.yaml +++ b/esphome/esp-downstairskitchleds.yaml @@ -1,83 +1,111 @@ -########################################################################################## -########################################################################################## -# Title: DOWNSTAIRS KITCHEN - OVER PANTRY LEDS -# Repo: https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstairskitchleds.yaml +#:########################################################################################:# +# TITLE: DOWNSTAIRS KITCHEN - OVER PANTRY LEDS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstairskitchleds.yaml +#:########################################################################################:# +# VERSIONS: +# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 +# v2.0 2025-09-15 A bunch of fixes. +# v1.5 2025-09-04 Adopt ramped "Restore Brightness" (0->last non-zero), avoid boot blip (ALWAYS_OFF + high-priority on_boot), +# add flash-write coalescing (persist once at end of ramps), guards for edge cases, and flash_write_interval=5min +# v1.4 2025-08-22 Improved power loss/on actions +# v1.3 2025-08-22 Added a "max on time" setting (1-48 h, 0 = no limit) +# v1.2 2025-08-21 Added defaults to "Device Specific Settings" in substitutions & a PWM % view +# v1.1 2025-08-18 Full tidy-up as general-purpose LED strip controller +# v1.0 2025-08-17 First setup (and replacement of Tasmota) +#:########################################################################################:# +# HARDWARE: +# - Sinilink MOSFET Board XY-WFMS (ESP8266) - sometimes listed as "XY-VFMS" +# https://devices.esphome.io/devices/Sinilink-XY-WFMS # -# v2.0 - 2025-09-15 A bunch of fixes. -# v1.5 - 2025-09-04 Adopt ramped "Restore Brightness" (0→last non-zero), avoid boot blip (ALWAYS_OFF + high-priority on_boot), -# add flash-write coalescing (persist once at end of ramps), guards for edge cases, and flash_write_interval=5min -# v1.4 - 2025-08-22 Improved power loss/on actions -# v1.3 - 2025-08-22 Added a "max on time” setting (1-48 h, 0 = no limit) -# v1.2 - 2025-08-21 Added defaults to “Device Specific Settings” in substitutions & a PWM % view -# v1.1 - 2025-08-18 Full tidy-up as general-purpose LED strip controller -# v1.0 - 2025-08-17 First setup (and replacement of Tasmota) +# - 3D-printed case for Sinilink XY-WFMS +# https://cults3d.com/en/3d-model/tool/snapfit-enclosure-for-esp8266-sinilink-xy-wfms-5v-36v-mosfet-switch-module # -# ------------------------------------------ -# OPERATION (as of v2.0) -# ------------------------------------------ -# 1. General-purpose LED controller. -# 2. Designed for the Sinilink XY-WFMS board with a MOSFET output (claimed 5A, 5-36 V DC), but will suit similar mosfet boards. -# 3. (In SUBSTITUTIONS) setting for MAX % output to extend LED life (ie can ensure it is only ever 95%) -# 4. (In SUBSTITUTIONS) Minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. -# 5. (In SUBSTITUTIONS) PWM frequency is set to 1kHz by default. You can increase it, but higher values caused -# resets on Sinilink device. On ESP32 you can run much higher (~40 kHz). -# 6. Min/Max output settings are not exposed in Home Assistant/MQTT by default, but could be. -# With a 1 MB flash, space is tight and only minimal optimisation has been done so far. -# 7. (PACKAGES) include common items: network settings, diagnostic entities, MQTT, and SNTP (optional). -# 8. Default behaviours, for recovery from lost power or reset: -# - "Fade up to full": fade from floor to max on boot. -# - "Restore Brightness": fade from floor to the last non-zero brightness on boot (should be no on/off blip/flash). -# - "Remain Off": stays off on boot. -# 9. Green LED rule: ON while any ramp script is executing, otherwise OFF. The red LED follows the -# output (it shares the MOSFET GPIO). (Obviously this depends on hardware) -# 10. Fade timing scales with the configured values (proportionally when starting mid-brightness). -# 11. Exposed in Home Assistant/MQTT: -# - Startup action (On,Off,Restore) -# - Fade Up / Fade Down / Fade Stop buttons -# - Fade Up/Down toggle switch -# - Normal On/Off switch (quick ramp up/down) -# - Fade up/down times (0-60s) -# - Output % (pre-gamma) and PWM % (post-gamma) -# - Output Set (1-100, respects min/max). This also changes with other output so reflects value. -# - Many device diagnostics (from the included 'diagnostics' package) -# - Maximum 'on' time before automatic fade-down (1-48 h, 0 = no limit) -########################################################################################### -# Hardware: Sinilink MOSFET Board XY-WFMS (ESP8266) - sometimes listed as "XY-VFMS" -# https://devices.esphome.io/devices/Sinilink-XY-WFMS -# ------------------------------------------ # DEVICE GPIO (Sinilink XY-WFMS) -# ------------------------------------------ -# GPIO02 Blue LED, active-low (used for ESPHome status) -# GPIO04 MOSFET output (0V when switched) and Red LED -# GPIO12 Toggle button -# GPIO13 Green LED (used to display fading status) +# - GPIO02 Blue LED, active-low (used for ESPHome status) +# - GPIO04 MOSFET output (0V when switched) and Red LED +# - GPIO12 Toggle button +# - GPIO13 Green LED (used to display fading status) +#:########################################################################################:# +# OPERATION NOTES: +# - OPERATION (as of v2.0) +# 1. General-purpose LED controller. +# 2. Designed for the Sinilink XY-WFMS board with a MOSFET output (claimed 5A, 5-36 V DC), but will suit similar mosfet boards. +# 3. (In SUBSTITUTIONS) setting for MAX % output to extend LED life (ie can ensure it is only ever 95%) +# 4. (In SUBSTITUTIONS) Minimum output setting; switches fully OFF at/below the minimum to avoid low-PWM flicker. +# 5. (In SUBSTITUTIONS) PWM frequency is set to 1kHz by default. You can increase it, but higher values caused +# resets on Sinilink device. On ESP32 you can run much higher (~40 kHz). +# 6. Min/Max output settings are not exposed in Home Assistant/MQTT by default, but could be. +# With a 1 MB flash, space is tight and only minimal optimisation has been done so far. +# 7. (PACKAGES) include common items: network settings, diagnostic entities, MQTT, and SNTP (optional). +# 8. Default behaviours, for recovery from lost power or reset: +# - "Fade up to full": fade from floor to max on boot. +# - "Restore Brightness": fade from floor to the last non-zero brightness on boot (should be no on/off blip/flash). +# - "Remain Off": stays off on boot. +# 9. Green LED rule: ON while any ramp script is executing, otherwise OFF. The red LED follows the +# output (it shares the MOSFET GPIO). (Obviously this depends on hardware) +# 10. Fade timing scales with the configured values (proportionally when starting mid-brightness). +# 11. Exposed in Home Assistant/MQTT: +# - Startup action (On,Off,Restore) +# - Fade Up / Fade Down / Fade Stop buttons +# - Fade Up/Down toggle switch +# - Normal On/Off switch (quick ramp up/down) +# - Fade up/down times (0-60s) +# - Output % (pre-gamma) and PWM % (post-gamma) +# - Output Set (1-100, respects min/max). This also changes with other output so reflects value. +# - Many device diagnostics (from the included 'diagnostics' package) +# - Maximum 'on' time before automatic fade-down (1-48 h, 0 = no limit) +#:########################################################################################:# +# MQTT COMMANDS: +# - Command topic: +# ${mqtt_local_command_topic}/light/set +# Payload "${mqtt_local_device_command_ON}" -> fade up (switch ON) +# Payload "${mqtt_local_device_command_OFF}" -> fade down (switch OFF) # -# 3D-printed case for Sinilink XY-WFMS -# https://cults3d.com/en/3d-model/tool/snapfit-enclosure-for-esp8266-sinilink-xy-wfms-5v-36v-mosfet-switch-module -# -########################################################################################## -########################################################################################## +# - Status topic: +# ${mqtt_local_status_topic}/light/state +# Payload "${mqtt_local_device_command_ON}" / "${mqtt_local_device_command_OFF}" +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - MQTT control continues to work +# - LED control logic continues locally +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - HA/API control continues to work (if API enabled) +# - MQTT commands/status will not work while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA/API and no MQTT control available +# - Local button still controls fade up/down +# - Accurate time is NOT needed (SNTP not needed) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-downstairskitchleds" # yaml file should be device_name.yaml friendly_name: "Downstairs Kitchen LEDs" - description_comment: "Downstairs Kitchen Over Pantry LEDs :: Sinilink XY-WFMS" + description_comment: "Downstairs Kitchen Over Pantry LEDs :: Sinilink XY-WFMS (Layout V1.1)" device_area: "Downstairs Kitchen" # Allows the ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. - project_version: "v2.0" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version + project_name: "Sinilink.XY-WFMS" # Project details. Manufacturer before the dot, device after the dot. + project_version: "v2.1" # Project version denotes release of the YAML file, allowing checking of deployed vs latest version - # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) + # Passwords & Secrets (Unfortunately, you can't use substitutions inside secret names) api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass - static_ip_address: !secret esp-downstairskitchleds_ip # CHANGE THIS - + ota_pass: !secret esp-ota_pass + static_ip_address: !secret esp-downstairskitchleds_ip + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # MQTT LOCAL Controls mqtt_local_device_name: "downstairskitchen-pantryleds" mqtt_local_command_main_topic: !secret mqtt_command_main_topic @@ -88,24 +116,24 @@ substitutions: mqtt_local_device_command_OFF: "OFF" # Device Specific Settings - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE - update_interval: "20s" # Update time for general sensors, etc. - led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM - minimum_led_output: "1" # % If at this value or below, we'll switch it completely off - maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics - max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off - pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts + log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG (default), VERBOSE, VERY_VERBOSE + update_interval: "20s" # Update time for general sensors, etc. + led_gamma: "1.2" # Gamma from 1.2-3 is sensible to normalise the LED fading vs PWM + minimum_led_output: "1" # % If at this value or below, we'll switch it completely off + maximum_led_output: "90" # % Maximum output; it is sometimes nice to limit the output for longevity or aesthetics + max_on_default_hours: "24" # The maximum time the LEDs will be on, in case they get left on. 0 = no automatic turn-off + pwm_frequency: "1000" # PWM output Frequency in Hz. High enough to avoid audible/visible artifacts # Device Specific GPIO (so we can easily update for other devices) device_status_led: GPIO02 device_mosfet_out: GPIO04 - device_usr_button: GPIO12 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml - device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml + device_usr_button: GPIO12 # if no button, this is just a fake/safeish choice so it compiles with the generic yaml + device_fading_led: GPIO13 # if no LED, this is just a fake/safeish choice so it compiles with the generic yaml -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -114,6 +142,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -127,22 +156,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome CORE CONFIGURATION +#:########################################################################################:# +# ESPHOME: Core Configuration # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -190,25 +220,10 @@ esphome: # Boot complete: allow OFF handlers again - lambda: 'id(booting) = false;' - # NEW: force indicator OFF after boot logic - # (Removed: output.turn_off: green_led_out) - -# Only if you want to play with build flags... -# platformio_options: -# build_unflags: -# - -flto -# build_flags: -# - -fno-lto -# - -Wl,--gc-sections -# - -ffunction-sections -# - -fdata-sections -# - -DNDEBUG - -########################################################################################## +#:########################################################################################:# # ESP PLATFORM AND FRAMEWORK # https://esphome.io/components/esp8266.html -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp8266: board: esp01_1m restore_from_flash: true # restore some values on reboot @@ -219,118 +234,127 @@ mdns: preferences: flash_write_interval: 2min # enough time to update values for reboots, but not enough to wear flash -########################################################################################## -# GLOBAL VARIABLES +#:########################################################################################:# +# GLOBALS # https://esphome.io/components/globals.html -########################################################################################## +#:########################################################################################:# globals: # Minimum Brightness % for LEDs (will switch off if <=) - id: min_brightness_pct type: int restore_value: true - initial_value: "${minimum_led_output}" # start/finish at X% + initial_value: "${minimum_led_output}" # start/finish at X% + # Maximum Brightness % for LEDs (should never go beyond this) - id: max_brightness_pct type: int restore_value: false - initial_value: "${maximum_led_output}" # hard cap; never exceed this - # The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever + initial_value: "${maximum_led_output}" # hard cap; never exceed this + + # The maximum time the lights will stay on, in hours. 0 = forever - id: max_on_hours type: int restore_value: true initial_value: "${max_on_default_hours}" + # Compile time Gamma - id: led_gamma_f type: float restore_value: false - initial_value: ${led_gamma} # <-- numeric at compile time + initial_value: ${led_gamma} # Default Fading Up Time (Selectable and will be retained) - - id: ramp_up_ms # fade-in when turned ON + - id: ramp_up_ms type: int restore_value: true - initial_value: '5000' # 5 s - # Default Fading Down Time (Selectable and will be retained) - - id: ramp_down_ms # fade-out when turned OFF - type: int - restore_value: true - initial_value: '10000' # 10 s - # Action on Restart. (0=Fade full, 1=Restore brightness, 2=Remain off) - - id: restart_mode - type: int - restore_value: true - initial_value: '0' # default = Fade Up to Full (so can be deployed with no other setup) + initial_value: "5000" # 5 s - # Determine last fade direction. - # true when you asked the light to end up ON (Ramp Up) - # false when you asked the light to end up OFF (Ramp Down) + # Default Fading Down Time (Selectable and will be retained) + - id: ramp_down_ms + type: int + restore_value: true + initial_value: "10000" # 10 s + + # Action on Restart (0=Fade full, 1=Restore brightness, 2=Remain off) + - id: restart_mode + type: int + restore_value: true + initial_value: "0" + + # true when you asked the light to end up ON (Ramp Up); false when OFF (Ramp Down) - id: ramp_switch_target_on type: bool restore_value: true - initial_value: 'false' + initial_value: "false" + # Prevent jitter when adjusting the slider - id: suppress_slider_sync type: bool restore_value: false - initial_value: 'false' - # actual 0..100 seen last time, for restart - - id: last_brightness_pct + initial_value: "false" + + # actual 0..100 seen last time, for restart + - id: last_brightness_pct type: float restore_value: true - initial_value: '0.0' + initial_value: "0.0" + # last published "Output Set (0-100)" integer - id: last_set_pos type: int restore_value: false - initial_value: '-1' - # helper to keep blink time == transition time + initial_value: "-1" + + # helper to keep blink time == transition time - id: last_ramp_ms type: int restore_value: false - initial_value: '0' + initial_value: "0" + # target for "Restore Brightness" scripted ramp - id: restore_target_pct type: float restore_value: false - initial_value: '0.0' + initial_value: "0.0" + # true while a scripted ramp is in progress (to limit flash writes) - id: is_ramping type: bool restore_value: false - initial_value: 'false' + initial_value: "false" + # guards OFF persistence during startup caused by restore_mode: ALWAYS_OFF - id: booting type: bool restore_value: false - initial_value: 'true' + initial_value: "true" + # true only while we are performing a ramp-down that briefly turns the light ON to hit the floor - id: ramping_for_off type: bool restore_value: false - initial_value: 'false' + initial_value: "false" -########################################################################################## -# LOGGER COMPONENT +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -# Logs all log messages through the serial port and through MQTT topics. -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" # INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM, Serial control) + level: "${log_level}" + baud_rate: 0 -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: ${device_status_led} inverted: true -########################################################################################## -# MQTT COMMANDS -# This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# +# MQTT: Device-specific command triggers +#:########################################################################################:# mqtt: on_message: # Light control to ramp up @@ -338,18 +362,19 @@ mqtt: payload: "${mqtt_local_device_command_ON}" then: - switch.turn_on: mosfet_ramp_switch + # Light control to ramp down - topic: "${mqtt_local_command_topic}/light/set" payload: "${mqtt_local_device_command_OFF}" then: - switch.turn_off: mosfet_ramp_switch -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: - # Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce) + # Ramp-aware ON/OFF for HA (asymmetric; no bounce) - platform: template id: mosfet_ramp_switch name: "${friendly_name} Fade Up-Down" @@ -367,10 +392,10 @@ switch: - script.stop: ramp_on_script - script.execute: ramp_off_script -################################################################################################# -# BUTTON COMPONENT +#:########################################################################################:# +# BUTTON # https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# button: # Start ramping UP (from current level) - platform: template @@ -402,15 +427,12 @@ button: name: "${friendly_name} Fade Stop" icon: mdi:pause on_press: - # Stop any pending scripts (and their delayed actions) - script.stop: ramp_on_script - script.stop: ramp_off_script - lambda: |- - // We are no longer ramping (up or down) id(ramping_for_off) = false; id(is_ramping) = false; - // Freeze the light at its *current* level by overwriting the transition const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { auto call = id(mosfet_leds).make_call(); @@ -420,18 +442,15 @@ button: call.perform(); } - // Persist the exact frozen level so restore survives a reboot if (cv.is_on()) { float pct = cv.get_brightness() * 100.0f; id(last_brightness_pct) = pct; } - - -######################################################################################### -# SELECT COMPONENT +#:########################################################################################:# +# SELECT # https://esphome.io/components/select/index.html -######################################################################################### +#:########################################################################################:# select: - platform: template id: restart_action @@ -453,10 +472,10 @@ select: id(restart_mode) = 2; } -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSOR # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio id: btn_gpio12 @@ -475,24 +494,22 @@ binary_sensor: condition: lambda: 'return id(ramp_switch_target_on);' then: - # Target is currently ON -> press should go OFF (start ramp-down) - lambda: |- id(ramp_switch_target_on) = false; id(mosfet_ramp_switch).publish_state(false); // reflect in HA immediately - script.stop: ramp_on_script - script.execute: ramp_off_script else: - # Target is currently OFF -> press should go ON (start ramp-up) - lambda: |- id(ramp_switch_target_on) = true; id(mosfet_ramp_switch).publish_state(true); // reflect in HA immediately - script.stop: ramp_off_script - script.execute: ramp_on_script -########################################################################################## -# SENSOR COMPONENT +#:########################################################################################:# +# SENSOR # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: - platform: template id: mosfet_output_pct @@ -500,17 +517,15 @@ sensor: unit_of_measurement: "%" icon: mdi:percent accuracy_decimals: 0 - update_interval: 2s # consider 200ms if you want fewer updates + update_interval: 2s lambda: |- const auto &cv = id(mosfet_leds).current_values; return cv.is_on() ? (float) (int)(cv.get_brightness() * 100.0f + 0.5f) : 0.0f; - on_value: then: - lambda: |- - // If not suppressing sync, update the 0..100 slider only when its INT changes if (!id(suppress_slider_sync)) { - float actual = x; // x is current Output (%) + float actual = x; float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); if (maxp <= minp) maxp = minp + 1.0f; @@ -541,28 +556,26 @@ sensor: if (pwm > 1.0f) pwm = 1.0f; return pwm * 100.0f; -########################################################################################## -# OUTPUT COMPONENT -# https://esphome.io/components/light/index.html -########################################################################################## -# An OUTPUT can be binary (0,1) or float, which is any value between 0 and 1. -# PWM Outputs such as "ledc" are float. https://esphome.io/components/output/ledc.html -########################################################################################## +#:########################################################################################:# +# OUTPUT +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: mosfet_pwm pin: ${device_mosfet_out} frequency: ${pwm_frequency} + - platform: gpio - id: green_led_out # Green LED + id: green_led_out pin: number: ${device_fading_led} inverted: false -########################################################################################## -# LIGHT COMPONENT +#:########################################################################################:# +# LIGHT # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: monochromatic id: mosfet_leds @@ -573,7 +586,6 @@ light: icon: mdi:led-strip-variant gamma_correct: "${led_gamma}" - # ON: publish state, track intent, arm watchdog if configured on_turn_on: - output.turn_on: green_led_out - mqtt.publish: @@ -581,7 +593,6 @@ light: payload: "${mqtt_local_device_command_ON}" retain: true - lambda: |- - // Do not flip "intent to ON" when we're inside an OFF ramp's floor-kick if (!id(ramping_for_off)) { id(ramp_switch_target_on) = true; } @@ -592,8 +603,6 @@ light: then: - script.execute: max_on_watchdog - # OFF: publish state, track intent, clear watchdog, and persist OFF so Mode 1 will not restore - # Guarded by booting flag so the automatic OFF at boot from ALWAYS_OFF does not zero persistence. on_turn_off: - output.turn_off: green_led_out - if: @@ -611,31 +620,29 @@ light: id(last_set_pos) = 0; id(led_output_set_pct).publish_state(0); - # Cap brightness to max_brightness_pct without a visible step on_state: - lambda: |- const float cap = id(max_brightness_pct) / 100.0f; const auto &cv = id(mosfet_leds).current_values; if (!cv.is_on()) return; const float b = cv.get_brightness(); - if (b <= cap + 0.001f) return; // no call if already at/under cap + if (b <= cap + 0.001f) return; auto call = id(mosfet_leds).make_call(); call.set_state(true); call.set_brightness(cap); call.set_transition_length(0); call.perform(); - -########################################################################################## -# NUMBER COMPONENT +#:########################################################################################:# +# NUMBER # https://esphome.io/components/number/ -########################################################################################## +#:########################################################################################:# number: - platform: template id: cfg_ramp_up_s name: "${friendly_name} Fade Up Time (s)" entity_category: config - unit_of_measurement: s + unit_of_measurement: "s" icon: mdi:timer-sand mode: slider min_value: 0 @@ -655,7 +662,7 @@ number: id: cfg_ramp_down_s name: "${friendly_name} Fade Down Time (s)" entity_category: config - unit_of_measurement: s + unit_of_measurement: "s" icon: mdi:timer-sand-complete mode: slider min_value: 0 @@ -679,24 +686,22 @@ number: min_value: 0 max_value: 100 step: 1 - # Show current position mapped into 0..100 across [min..max] lambda: |- const auto &cv = id(mosfet_leds).current_values; - float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; // 0..100 actual + float actual = cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f; float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); - if (maxp <= minp) maxp = minp + 1.0f; // avoid div/0 - if (actual <= 0.0f) return 0.0f; // when OFF, show 0 + if (maxp <= minp) maxp = minp + 1.0f; + if (actual <= 0.0f) return 0.0f; float pos = (actual - minp) * 100.0f / (maxp - minp); if (pos < 0.0f) pos = 0.0f; if (pos > 100.0f) pos = 100.0f; - return floorf(pos + 0.5f); // integer + return floorf(pos + 0.5f); set_action: - if: condition: lambda: 'return x <= 0.0f;' then: - # 0 means OFF - lambda: 'id(suppress_slider_sync) = true;' - script.stop: ramp_on_script - script.stop: ramp_off_script @@ -706,16 +711,15 @@ number: - lambda: |- id(ramp_switch_target_on) = false; id(led_output_set_pct).publish_state(0); - id(last_brightness_pct) = 0.0f; // persist OFF immediately + id(last_brightness_pct) = 0.0f; id(last_set_pos) = 0; - delay: 400ms - lambda: 'id(suppress_slider_sync) = false;' else: - # Map 1..100 - [min..max] and set ON - lambda: |- id(suppress_slider_sync) = true; - float pos = x; // 0..100 - if (pos < 1.0f) pos = 1.0f; // 0 is OFF + float pos = x; + if (pos < 1.0f) pos = 1.0f; if (pos > 100.0f) pos = 100.0f; id(led_output_set_pct).publish_state((int) floorf(pos + 0.5f)); - script.stop: ramp_off_script @@ -723,7 +727,7 @@ number: - light.turn_on: id: mosfet_leds brightness: !lambda |- - float pos = id(led_output_set_pct).state; // 1..100 + float pos = id(led_output_set_pct).state; float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); if (maxp <= minp) maxp = minp + 1.0f; @@ -733,13 +737,13 @@ number: transition_length: 250ms - lambda: |- id(ramp_switch_target_on) = true; - float pos = id(led_output_set_pct).state; // 1..100 + float pos = id(led_output_set_pct).state; float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); if (maxp <= minp) maxp = minp + 1.0f; float out_pct = minp + (pos * (maxp - minp) / 100.0f); if (out_pct > maxp) out_pct = maxp; - id(last_brightness_pct) = out_pct; // persist exact target now + id(last_brightness_pct) = out_pct; - delay: 400ms - lambda: 'id(suppress_slider_sync) = false;' @@ -747,7 +751,7 @@ number: id: cfg_max_on_hours name: "${friendly_name} Max On (h)" entity_category: config - unit_of_measurement: h + unit_of_measurement: "h" icon: mdi:timer-cog mode: slider min_value: 0 @@ -758,7 +762,7 @@ number: set_action: - lambda: |- int hrs = (int) x; - if (hrs < 0) hrs = 0; + if (hrs < 0) hrs = 0; if (hrs > 48) hrs = 48; id(max_on_hours) = hrs; id(cfg_max_on_hours).publish_state((float) hrs); @@ -773,20 +777,16 @@ number: then: - script.execute: max_on_watchdog -########################################################################################## -# SCRIPT COMPONENT +#:########################################################################################:# +# SCRIPT # https://esphome.io/components/script.html -# Scripts can be executed nearly anywhere in your device configuration with a single call. -########################################################################################## +#:########################################################################################:# script: - - # Script: ramp up from current level. Obey global max. (LED ON while ramping) - id: ramp_on_script mode: restart then: - lambda: 'id(is_ramping) = true;' - script.stop: ramp_off_script - # Ensure we start at at least the floor without a visible "pop". - if: condition: lambda: |- @@ -798,7 +798,6 @@ script: id: mosfet_leds brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' transition_length: 80ms - # Ramp from current (>= floor) to cap over a fraction of ramp_up_ms. - light.turn_on: id: mosfet_leds brightness: !lambda 'return id(max_brightness_pct) / 100.0f;' @@ -814,7 +813,7 @@ script: id(last_ramp_ms) = id(ramp_up_ms); return (uint32_t) id(last_ramp_ms); } - if (curr > cap) curr = cap; + if (curr > cap) curr = cap; if (curr < floor) curr = floor; float frac = (cap - curr) / (cap - floor); if (frac < 0.0f) frac = 0.0f; @@ -827,16 +826,14 @@ script: const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { float pct = cv.get_brightness() * 100.0f; - id(last_brightness_pct) = pct; // persist final level + id(last_brightness_pct) = pct; } - # Script: ramp to a specific target (Restore Brightness path). (LED ON while ramping) - id: ramp_to_target_script mode: restart then: - lambda: 'id(is_ramping) = true;' - script.stop: ramp_off_script - # Ensure we start at the floor cleanly. - if: condition: lambda: |- @@ -848,7 +845,6 @@ script: id: mosfet_leds brightness: !lambda 'return id(min_brightness_pct) / 100.0f;' transition_length: 80ms - # Ramp from current (>= floor) to restore_target_pct over a fraction of ramp_up_ms. - light.turn_on: id: mosfet_leds brightness: !lambda |- @@ -870,7 +866,7 @@ script: return (uint32_t) id(last_ramp_ms); } - if (curr > cap) curr = cap; + if (curr > cap) curr = cap; if (curr < floor) curr = floor; float frac = (cap - curr) / (cap - floor); if (frac < 0.0f) frac = 0.0f; @@ -883,11 +879,9 @@ script: const auto &cv = id(mosfet_leds).current_values; if (cv.is_on()) { float pct = cv.get_brightness() * 100.0f; - id(last_brightness_pct) = pct; // persist final level + id(last_brightness_pct) = pct; } - - # Script: ramp down from current level to floor, then cleanly cut to OFF. (LED ON while ramping) - id: ramp_off_script mode: restart then: @@ -918,7 +912,7 @@ script: - lambda: |- id(is_ramping) = false; id(ramping_for_off) = false; - id(last_brightness_pct) = 0.0f; // persist OFF for restore path + id(last_brightness_pct) = 0.0f; id(last_set_pos) = 0; id(led_output_set_pct).publish_state(0); @@ -940,20 +934,17 @@ script: - script.stop: ramp_on_script - script.execute: ramp_off_script - # Deferred restore to avoid early-boot races and ensure we apply the last saved level - id: deferred_restore_brightness mode: restart then: - - delay: 5s # let preferences/globals load and light settle + - delay: 5s - lambda: |- - // Use ONLY the exact last saved brightness. float target = id(last_brightness_pct); - // Clamp into [min..max] only if we are restoring a non-zero target float minp = (float) id(min_brightness_pct); float maxp = (float) id(max_brightness_pct); if (target > 0.0f && target < minp) target = minp; - if (target > maxp) target = maxp; + if (target > maxp) target = maxp; id(restore_target_pct) = target; @@ -962,16 +953,14 @@ script: lambda: 'return id(restore_target_pct) > 0.5f;' then: - lambda: |- - id(ramp_switch_target_on) = true; // reflect our intent - id(suppress_slider_sync) = true; + id(ramp_switch_target_on) = true; + id(suppress_slider_sync) = true; - script.stop: ramp_off_script - script.execute: ramp_to_target_script - delay: !lambda 'return (uint32_t) id(last_ramp_ms);' - lambda: 'id(suppress_slider_sync) = false;' else: - # Exact last was 0 -> remain OFF - lambda: 'id(ramp_switch_target_on) = false;' - light.turn_off: id: mosfet_leds - transition_length: 0s - # (Removed: output.turn_off: green_led_out) # make sure LED is off if no ramp \ No newline at end of file + transition_length: 0s \ No newline at end of file diff --git a/esphome/esp-downstbathswitch.yaml b/esphome/esp-downstbathswitch.yaml index 6315df5..04bca18 100644 --- a/esphome/esp-downstbathswitch.yaml +++ b/esphome/esp-downstbathswitch.yaml @@ -1,53 +1,77 @@ -########################################################################################## -########################################################################################## -# DOWNSTAIRS BATHROOM MAIN LIGHTSWITCH +#:########################################################################################:# +# TITLE: DOWNSTAIRS BATHROOM MAIN LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstbathswitch.yaml +#:########################################################################################:# +# VERSIONS: # V2.0 2025-06-05 YAML Tidyups # V1.0 2025-02-14 Initial Version -########################################################################################## -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# Zemismart KS-811 Triple push button (KS-811-3) +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Triple wall switch for Downstairs Bathroom +# - Button 1 toggles Relay 1 (Main Lights) +# - Button 2 toggles Relay 2 (Cabinet Light) +# - Button 3 controls Relay 3 (Extract Fan) using multi-click timing: +# - Single click: toggle, or run for 5 minutes then off +# - Double click: run for 30 minutes then off +# - Triple click: run for 4 hours then off +# - Hold (2s+): toggle permanently +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Switch continues operating locally (buttons drive relays) +# - If MQTT is used elsewhere in your system, this device itself does not require it for basic operation +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Switch continues operating locally (buttons drive relays) +# - HA can still control/read the relays via API +# c) Entire WiFi/Network OFFLINE +# - Switch continues operating locally (buttons drive relays) +# - Timeclocks will drift without network (SNTP). Time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-downstbathswitch" friendly_name: "Downstairs Bath Lightswitch (3)" - description_comment: "Downstairs Bathroom Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Light (1), Cabinet Light (2), Extract Fan (3)" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - - # Project Naming - project_name: "Zemismart Technologies.KS-811 Triple" # Project Details - project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + description_comment: "Downstairs Bathroom Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Light (1), Cabinet Light (2), Extract Fan (3) (Layout V1.1)" + device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - # Passwords - api_key: !secret esp-downstbathswitch_api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-downstbathswitch_ota_pass # unfortunately you can't use substitutions inside secrets names + # Project Naming + project_name: "Zemismart Technologies.KS-811 Triple" # Project Details + project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + # Passwords (unfortunately you cannot use substitutions inside secrets names) + api_key: !secret esp-downstbathswitch_api_key + ota_pass: !secret esp-downstbathswitch_ota_pass static_ip_address: !secret esp-downstbathswitch_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + update_interval: "60s" # update time for general sensors etc # Switch Naming switch_1_name: "Main Lights" switch_2_name: "Cabinet Light" - switch_3_name: "Extract Fan" # This is virtual only, no power connected to 3rd relay + switch_3_name: "Extract Fan" # This is virtual only, no power connected to 3rd relay -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -56,6 +80,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -69,65 +94,70 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" #Appears on the esphome page in HA + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -########################################################################################## +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: True + inverted: true -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # GPIO16 does not support interrupts so use polling (suppresses warning). name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 @@ -136,7 +166,7 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - switch.toggle: Relay_2 @@ -145,10 +175,10 @@ binary_sensor: pin: number: GPIO4 mode: INPUT - inverted: True + inverted: true name: "Button 3: ${switch_3_name}" on_multi_click: - # Single click: 1 press → relay on for 5 minutes + # Single click: 1 press -> relay on for 5 minutes - timing: - ON for at most 0.5s - OFF for at least 0.5s @@ -163,7 +193,7 @@ binary_sensor: - delay: 5min - switch.turn_off: Relay_3 - # Double click: 2 presses → relay on for 30 minutes + # Double click: 2 presses -> relay on for 30 minutes - timing: - ON for at most 0.5s - OFF for at most 0.5s @@ -180,7 +210,7 @@ binary_sensor: - delay: 30min - switch.turn_off: Relay_3 - # Triple click: 3 presses → relay on for 4 hours + # Triple click: 3 presses -> relay on for 4 hours - timing: - ON for at most 0.5s - OFF for at most 0.5s @@ -199,7 +229,7 @@ binary_sensor: - delay: 4h - switch.turn_off: Relay_3 - # Hold: pressed for 1 second or more → relay toggles permanently + # Hold: pressed for 2 seconds or more -> relay toggles permanently - timing: - ON for at least 2s then: @@ -211,22 +241,22 @@ binary_sensor: else: - switch.turn_on: Relay_3 -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 id: Relay_1 + - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 id: Relay_2 + - platform: gpio name: "Relay 3: ${switch_3_name}" pin: GPIO14 - id: Relay_3 - - + id: Relay_3 \ No newline at end of file diff --git a/esphome/esp-downstbathtowelrail.yaml b/esphome/esp-downstbathtowelrail.yaml index 7ab7388..999e4ab 100644 --- a/esphome/esp-downstbathtowelrail.yaml +++ b/esphome/esp-downstbathtowelrail.yaml @@ -1,15 +1,22 @@ -########################################################################################## -########################################################################################## -# DOWNSTAIRS BATHROOM HEATED TOWEL RAIL -# Controlled by a Sonoff Basic -# +#:########################################################################################:# +# TITLE: DOWNSTAIRS BATHROOM HEATED TOWEL RAIL +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstbathtowelrail.yaml +#:########################################################################################:# +# VERSIONS: +# V2.3 2026-02-25 Updated yaml to zorruno layout V1.1 # V2.2 2026-01-30 Added Morning/Evening Timer enable switches (gate timer windows) # V2.1 2025-06-12 Added select and button to chose modes, added countdown & startup to boost # V2.0 2025-06-05 YAML Tidyups # V1.1 2025-04-12 Fixes to timers and offline modes # V1.0 2025-02-14 Initial Version -# -# INSTRUCTIONS +#:########################################################################################:# +# HARDWARE: +# Controlled by a Sonoff Basic +#:########################################################################################:# +# OPERATION NOTES: # - It allows the device to work in a standalone timer style operation # - The timer has a morning and evening time (but no weekday/weekend settings) # - Morning Timer Enable / Evening Timer Enable switches gate their timer windows (default ON and restored on reboot) @@ -17,55 +24,68 @@ # - It uses SNTP for time setting (but obviously only if wifi & networking are working) # - It will default to an internal timer if no wifi. To reset internal timer, reboot the device at 12pm (noon) # - If on a network and there is a MQTT server, you can set the on/off times via MQTT (See below commands) -# - You can set 4 modes ON/OFF/TIMER/BOOST via MQTT. Setting BOOST gives you a oneshot operation +# - You can set 4 modes ON/OFF/TIMER/BOOST via MQTT. Setting BOOST gives you a oneshot operation # - Any new timer times set via MQTT will be remembered though a reboot # - On startup, or a reboot, the device will always turn on for the BOOST Duration (BOOST mode, default 2 hours) # - TIMER mode will always be switched on after BOOST mode is complete # - Home Assistant entities are set so that BOOST mode can be pressed with a button and other modes selectable with a dropdown # - If you need it ON continuously with no MQTT, toggle power ON/OFF 4 times within 30 seconds (with ~2 secs in between to allow it to boot) -# -# MQTT Commands -# Values will be set in place on the update_interval time, not immediately -# Use 00:00 in 24hr format for time setting. (Note there is no weekday/weekend setting) -# mqtt_timer_topic/morning-on/06:00 : Time device will go on -# mqtt_timer_topic/morning-off/08:00 : Time device will go off -# mqtt_timer_topic/evening-on/09:00 : Time device will go on -# mqtt_timer_topic/evening-off/00:00 : Time device will go off -# mqtt_timer_topic/boost-time/0000 : Time in minutes device will temporarily go on for (1-1439) -# mqtt_timer_topic/operation/ON : Device permanently on -# mqtt_timer_topic/operation/OFF : Device permanently off -# mqtt_timer_topic/operation/TIMER : Device will obey timer settings -# mqtt_timer_topic/operation/BOOST : Turn on for (boost_duration) minutes then BOOST (also on startup) +#:########################################################################################:# +# MQTT COMMANDS: +# Values will be set in place on the update_interval time, not immediately +# Use 00:00 in 24hr format for time setting. (Note there is no weekday/weekend setting) +# mqtt_timer_topic/morning-on/06:00 : Time device will go on +# mqtt_timer_topic/morning-off/08:00 : Time device will go off +# mqtt_timer_topic/evening-on/09:00 : Time device will go on +# mqtt_timer_topic/evening-off/00:00 : Time device will go off +# mqtt_timer_topic/boost-time/0000 : Time in minutes device will temporarily go on for (1-1439) +# mqtt_timer_topic/operation/ON : Device permanently on +# mqtt_timer_topic/operation/OFF : Device permanently off +# mqtt_timer_topic/operation/TIMER : Device will obey timer settings +# mqtt_timer_topic/operation/BOOST : Turn on for (boost_duration) minutes then BOOST (also on startup) # # operation_mode: # 0 = OFF # 1 = ON # 2 = TIMER # 3 = BOOST -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - The towel rail will stick to its assigned schedule (and should remember on reboot) +# - Schedule times and on/off switching can still occur via MQTT +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - With no MQTT automation controllers, the towel rail will still run its timer logic locally +# - If internet/wifi is still available, timing will be accurate (SNTP) +# c) Entire WiFi/Network OFFLINE +# - The towel rail will still run its timer logic locally, however timing will likely shift without SNTP +# - Timeclocks will drift without network (SNTP). Time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-downstbathtowelrail" friendly_name: "Downstairs Bathroom Towelrail" - description_comment: "Heated Towel Rail, Downstairs Bathroom :: Sonoff Basic" + description_comment: "Heated Towel Rail, Downstairs Bathroom :: Sonoff Basic (Layout V1.1)" device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details - project_version: "v2.2" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_version: "v2.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - # Passwords - api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + # Passwords (unfortunately you can't use substitutions inside secrets names) + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-downstbathtowelrail_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings relay_icon: "mdi:heating-coil" log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE @@ -73,18 +93,16 @@ substitutions: # Timer Settings mqtt_timer_topic: "viewroad-commands/downstbath-towelrail" # Topics you will use to change stuff - boost_duration_default: "120" # Minutes to stay ON in BOOST mode before reverting to TIMER - morning_on_default: "420" # Default in minutes from midnight. Default 07:00 => 420 - morning_off_default: "450" # Default in minutes from midnight. Default 07:30 => 450 - evening_on_default: "1260" # Default in minutes from midnight. Default 21:00 => 1260 - evening_off_default: "1320" # Default in minutes from midnight. Default 22:00 => 1320 => 1440 is midnight + boost_duration_default: "120" # Minutes to stay ON in BOOST mode before reverting to TIMER + morning_on_default: "420" # Default in minutes from midnight. Default 07:00 => 420 + morning_off_default: "450" # Default in minutes from midnight. Default 07:30 => 450 + evening_on_default: "1260" # Default in minutes from midnight. Default 21:00 => 1260 + evening_off_default: "1320" # Default in minutes from midnight. Default 22:00 => 1320 -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -93,6 +111,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -111,31 +130,34 @@ packages: #common_webportal: !include common/webportal_common.yaml #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - diag_debug: !include common/include_debug_diag_sensors.yaml + diag_basic: !include common/include_basic_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 -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" # Appears on the esphome page in HA area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" platformio_options: build_flags: - - "-Os" # optimize for size - - "-Wl,--gc-sections" # drop unused code/data - #- "-fno-exceptions" # strip C++ exceptions - #- "-fno-rtti" # strip C++ RTTI + - "-Os" # optimize for size + - "-Wl,--gc-sections" # drop unused code/data + #- "-fno-exceptions" # strip C++ exceptions + #- "-fno-rtti" # strip C++ RTTI on_boot: - priority: 900 # High priority to run after globals are initialized + priority: 900 # High priority to run after globals are initialized then: # This evaluates if we switch on 4+ times in 20 seconds # If so, just change to on mode permanently. @@ -176,15 +198,16 @@ esphome: id(boost_timer) = 0; // and reset boost_timer = 0 (for time sync if no sntp) ESP_LOGI("power_cycle", "Boot count=%d => BOOST mode", id(boot_count)); } - - script.execute: evaluate_relay_state # Check what the relay should be doing straight away + - script.execute: evaluate_relay_state # Check what the relay should be doing straight away -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: True # restore some values on reboot + board: esp01_1m # The original sonoff basic + restore_from_flash: true # restore some values on reboot preferences: flash_write_interval: 5min @@ -192,21 +215,21 @@ preferences: mdns: disabled: true -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -#################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ # Relay Switch (Sonoff Basic Relay on GPIO12) -#################################################### +#:########################################################################################:# switch: - platform: gpio name: "Towel Rail Power" @@ -242,12 +265,11 @@ switch: on_turn_off: - script.execute: evaluate_relay_state -########################################################################################## -# Global Variables for use in automations etc -# https://esphome.io/guides/automations.html?highlight=globals#global-variables -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/guides/automations.html#global-variables +#:########################################################################################:# globals: - # Tracks the time (in seconds from midnight) at the previous boot - id: last_boot_time_s type: int @@ -260,31 +282,31 @@ globals: restore_value: true initial_value: "0" - # Morning On time (minutes from midnight), + # Morning On time (minutes from midnight) - id: morning_on type: int restore_value: true initial_value: "${morning_on_default}" - # Morning Off time (minutes from midnight), + # Morning Off time (minutes from midnight) - id: morning_off type: int restore_value: true initial_value: "${morning_off_default}" - # Evening On time (minutes from midnight), + # Evening On time (minutes from midnight) - id: evening_on type: int restore_value: true initial_value: "${evening_on_default}" - # Evening Off time (minutes from midnight), + # Evening Off time (minutes from midnight) - id: evening_off type: int restore_value: true initial_value: "${evening_off_default}" - # Boost Duration (minutes), + # Boost Duration (minutes) - id: boost_duration type: int restore_value: true @@ -312,18 +334,16 @@ globals: restore_value: false initial_value: "0" -########################################################################################## -# Text Sensors -# https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# +# TEXT SENSORS: +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# text_sensor: + ############################ + # MQTT Subscriptions + ############################ -############################ -# MQTT Subscriptions -############################ - ############################ # Morning On time => "HH:MM" - ############################ - platform: mqtt_subscribe name: "Morning On Time Setting" id: morning_on_topic @@ -340,9 +360,7 @@ text_sensor: ESP_LOGW("timer","Invalid Morning On format: %s", x.c_str()); } - ############################ # Morning Off time => "HH:MM" - ############################ - platform: mqtt_subscribe name: "Morning Off Time Setting" id: morning_off_topic @@ -359,9 +377,7 @@ text_sensor: ESP_LOGW("timer","Invalid Morning Off format: %s", x.c_str()); } - ############################ # Evening On time => "HH:MM" - ############################ - platform: mqtt_subscribe name: "Evening On Time Setting" id: evening_on_topic @@ -378,9 +394,7 @@ text_sensor: ESP_LOGW("timer","Invalid Evening On format: %s", x.c_str()); } - ############################ # Evening Off time => "HH:MM" - ############################ - platform: mqtt_subscribe name: "Evening Off Time Setting" id: evening_off_topic @@ -397,9 +411,7 @@ text_sensor: ESP_LOGW("timer","Invalid Evening Off format: %s", x.c_str()); } - ############################ # Boost duration => integer minutes (1-1439) - ############################ - platform: mqtt_subscribe name: "Boost Duration" id: boost_time_topic @@ -409,7 +421,6 @@ text_sensor: then: - lambda: |- int v = 0; - // Parse as integer if (sscanf(x.c_str(), "%d", &v) == 1 && v >= 1 && v <= 1439) { id(boost_duration) = v; ESP_LOGI("boost_time","Received new Boost Duration: %d mins", v); @@ -417,9 +428,7 @@ text_sensor: ESP_LOGW("boost_time","Invalid boost_time '%s'", x.c_str()); } - #################################################### # Subscribe to operation mode: OFF, ON, TIMER, BOOST - #################################################### - platform: mqtt_subscribe id: timer_operation_mode_topic topic: "${mqtt_timer_topic}/operation" @@ -427,14 +436,12 @@ text_sensor: on_value: then: - lambda: |- - // Check only the first character for mode char c = x.c_str()[0]; - if (c == 'T') { // "TIMER" + if (c == 'T') { id(operation_mode) = 2; - } else if (c == 'O') { // "ON" or "OFF" - // second letter N->ON, F->OFF + } else if (c == 'O') { id(operation_mode) = (x.size() > 1 && x[1] == 'N') ? 1 : 0; - } else if (c == 'B') { // "BOOST" + } else if (c == 'B') { id(operation_mode) = 3; id(boost_timer) = 0; } else { @@ -442,13 +449,10 @@ text_sensor: } - script.execute: evaluate_relay_state - ###################################################### # Expose the current operation mode (OFF, ON, TIMER, BOOST) - ###################################################### - platform: template name: "Operation Mode State" lambda: |- - // 0=OFF, 1=ON, 2=TIMER, 3=BOOST switch (id(operation_mode)) { case 0: return {"OFF"}; case 1: return {"ON"}; @@ -458,66 +462,54 @@ text_sensor: } update_interval: 5s - ###################################################### # Expose the "Morning On" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Morning On Time" lambda: |- int hour = id(morning_on) / 60; int minute = id(morning_on) % 60; - // Increase to 16 for safety char buff[16]; snprintf(buff, sizeof(buff), "%02d:%02d", hour, minute); return { std::string(buff) }; update_interval: "${update_interval}" - ###################################################### # Expose the "Morning Off" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Morning Off Time" lambda: |- int hour = id(morning_off) / 60; int minute = id(morning_off) % 60; - // Increase to 16 for safety char buff[16]; snprintf(buff, sizeof(buff), "%02d:%02d", hour, minute); return { std::string(buff) }; update_interval: "${update_interval}" - ###################################################### # Expose the "Evening On" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Evening On Time" lambda: |- int hour = id(evening_on) / 60; int minute = id(evening_on) % 60; - // Increase to 16 for safety char buff[16]; snprintf(buff, sizeof(buff), "%02d:%02d", hour, minute); return { std::string(buff) }; update_interval: "${update_interval}" - ###################################################### # Expose the "Evening Off" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Evening Off Time" lambda: |- int hour = id(evening_off) / 60; int minute = id(evening_off) % 60; - // Increase to 16 for safety char buff[16]; snprintf(buff, sizeof(buff), "%02d:%02d", hour, minute); return { std::string(buff) }; update_interval: "${update_interval}" -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: gpio pin: @@ -534,11 +526,9 @@ binary_sensor: then: - lambda: |- if (id(relay).state) { - // Relay is ON: turn it OFF and set mode to 0 (TIMER) id(relay).turn_off(); id(operation_mode) = 2; } else { - // Relay is OFF: turn it ON and set mode to 3 (BOOST) id(relay).turn_on(); id(operation_mode) = 3; } @@ -548,16 +538,16 @@ binary_sensor: lambda: |- return id(relay).state; -########################################################################################## -# Sensors -# https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# +# SENSORS: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: template name: "Timeclock: Boost Duration" id: boost_duration_time unit_of_measurement: "mins" - accuracy_decimals: "0" + accuracy_decimals: 0 update_interval: "${update_interval}" lambda: |- return id(boost_duration); @@ -566,9 +556,9 @@ sensor: name: "Mins from Midnight" id: mins_from_midnight unit_of_measurement: "mins" - accuracy_decimals: "0" + accuracy_decimals: 0 update_interval: "${update_interval}" - internal: True # No need to show this in Home Assistant + internal: true lambda: |- return id(current_mins); @@ -578,41 +568,35 @@ sensor: id: timer_minutes_remaining unit_of_measurement: "Mins" update_interval: 5s - accuracy_decimals: "0" + accuracy_decimals: 0 lambda: |- - // always zero if relay is off if (!id(relay).state) { return 0; } int rem = 0; - // only calculate for mode 2 (scheduled) or mode 3 (BOOST) if (id(operation_mode) == 2) { int a = id(morning_off) - id(current_mins); int b = id(evening_off) - id(current_mins); - // if a is negative, use b; otherwise pick the smaller of a or b rem = (a < 0) ? b : (a < b ? a : b); } else if (id(operation_mode) == 3) { rem = id(boost_duration) - id(boost_timer); } - // never return negative return rem > 0 ? rem : 0; -################################################################################################# -# BUTTON COMPONENT -# https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# +# BUTTON COMPONENT: +# https://esphome.io/components/button/ +#:########################################################################################:# button: - platform: template name: "Boost now" id: boost_button icon: "mdi:play-circle-outline" on_press: - # 1) reset BOOST timer and set mode - lambda: |- id(boost_timer) = 0; id(operation_mode) = 3; - # 2) immediately re-evaluate relay state - script.execute: evaluate_relay_state - platform: template @@ -621,25 +605,22 @@ button: icon: "mdi:restore" on_press: - lambda: |- - // Restore all timing globals to their YAML defaults - id(morning_on) = ${morning_on_default}; - id(morning_off) = ${morning_off_default}; - id(evening_on) = ${evening_on_default}; - id(evening_off) = ${evening_off_default}; - id(boost_duration)= ${boost_duration_default}; - // Reset mode to TIMER and clear any running boost - id(operation_mode)= 2; - id(boost_timer) = 0; + id(morning_on) = ${morning_on_default}; + id(morning_off) = ${morning_off_default}; + id(evening_on) = ${evening_on_default}; + id(evening_off) = ${evening_off_default}; + id(boost_duration) = ${boost_duration_default}; + id(operation_mode) = 2; + id(boost_timer) = 0; ESP_LOGI("timer","Default timer settings applied"); - # Restore timer enable switches to ON (defaults) - switch.turn_on: morning_timer_enable - switch.turn_on: evening_timer_enable - script.execute: evaluate_relay_state -################################################################################################# -# SELECT COMPONENT -# https://esphome.io/components/select/index.html -################################################################################################# +#:########################################################################################:# +# SELECT COMPONENT: +# https://esphome.io/components/select/ +#:########################################################################################:# select: - platform: template name: "Operation Mode" @@ -650,8 +631,6 @@ select: - "ON" - "TIMER" - "BOOST" - - # show the current mode lambda: |- switch (id(operation_mode)) { case 1: return std::string("ON"); @@ -659,43 +638,37 @@ select: case 3: return std::string("BOOST"); default: return std::string("OFF"); } - - # when changed in HA, set mode & re-evaluate set_action: - lambda: |- if (x == "OFF") { id(operation_mode) = 0; } else if (x == "ON") { id(operation_mode) = 1; } else if (x == "TIMER") { id(operation_mode) = 2; } - else { // BOOST + else { id(boost_timer) = 0; id(operation_mode) = 3; } - script.execute: evaluate_relay_state -################################################################################################# -# SCRIPT COMPONENT +#:########################################################################################:# +# SCRIPT COMPONENT: # https://esphome.io/components/script.html -################################################################################################# -# Script: evaluate and drive the relay +#:########################################################################################:# script: - id: evaluate_relay_state then: - lambda: |- int mode = id(operation_mode); - // BOOST just forces the relay on if (mode == 3) { id(relay).turn_on(); return; } - // OFF -> always off if (mode == 0) { id(relay).turn_off(); return; } - // ON -> always on if (mode == 1) { id(relay).turn_on(); return; @@ -705,14 +678,12 @@ script: { bool should_on = false; - // Morning window only applies when Morning Timer Enable is enabled if (id(morning_timer_enable).state) { if (id(current_mins) >= id(morning_on) && id(current_mins) < id(morning_off)) { should_on = true; } } - // Evening window only applies when Evening Timer Enable is enabled if (id(evening_timer_enable).state) { if (id(current_mins) >= id(evening_on) && id(current_mins) < id(evening_off)) { should_on = true; @@ -723,16 +694,15 @@ script: else id(relay).turn_off(); } -################################################################################################# -# INTERVAL COMPONENT +#:########################################################################################:# +# INTERVAL COMPONENT: # https://esphome.io/components/interval.html -################################################################################################# -# Interval: bumps time (even if no SNTP), then calls the script to evaluate relay state +#:########################################################################################:# interval: - interval: "1min" then: - lambda: |- - // - update current_mins via SNTP or fallback + // update current_mins via SNTP or fallback if (!id(sntp_time).now().is_valid()) { id(current_mins)++; if (id(current_mins) >= 1440) id(current_mins) = 0; @@ -741,12 +711,11 @@ interval: id(current_mins) = now.hour * 60 + now.minute; } - // - if in BOOST, advance boost_timer and expire when done + // if in BOOST, advance boost_timer and expire when done if (id(operation_mode) == 3) { id(boost_timer)++; if (id(boost_timer) >= id(boost_duration)) { id(operation_mode) = 2; - //id(mqtt_client).publish("${mqtt_timer_topic}/operation", "TIMER"); } } - - script.execute: evaluate_relay_state + - script.execute: evaluate_relay_state \ No newline at end of file diff --git a/esphome/esp-downstbedrm2lights.yaml b/esphome/esp-downstbedrm2lights.yaml index a33b2e0..9dfc2b1 100644 --- a/esphome/esp-downstbedrm2lights.yaml +++ b/esphome/esp-downstbedrm2lights.yaml @@ -1,62 +1,71 @@ -########################################################################################## -########################################################################################## -# DOwNSTAIRS BEDROOM 2 LIGHTSWITCH +#:########################################################################################:# +# TITLE: DOWNSTAIRS BEDROOM 2 LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstbedrm2lights.yaml +#:########################################################################################:# +# VERSIONS: +# V3.6 2026-02-25 Updated yaml to zorruno layout V1.1 # V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Single push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# Controlled by a Zemismart KS-811 Single push button +# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Single-button wall switch controlling a single relay output. +# - Button press toggles the relay state (Main Lights). +# - KS-811-1 button input is GPIO0 (note: boot-strap pin). +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - The device will keep operating locally (button still toggles the relay). +# - MQTT may still function (if used elsewhere), but HA entities will be unavailable until HA returns. +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - The device remains controllable from Home Assistant via API. +# - Local button control continues to work. +# c) Entire WiFi/Network OFFLINE +# - The device continues to operate locally (button toggles relay). +# - SNTP is not needed (no timeclocks used). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-downstbedrm2lights" friendly_name: "Downstairs Bedroom 2 Lightswitch (1)" - description_comment: "Downstairs Bedroom 2 Main Lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1)" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Downstairs Bedroom 2 Main Lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1) (Layout V1.1)" + device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Single" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Single" # Project Details + project_version: "v3.6" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-downstbedrm2lights_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc - # MQTT LOCAL Controls - #mqtt_device_name: "downst-bedroom2-lights" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - - # MQTT REMOTE Controls - # Switch/Relay/Button Naming & Icons #relay_icon: "mdi:lightbulb-group" switch_1_name: "Main Lights" - #switch_2_name: "Nil" - #switch_3_name: "Nil" -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -65,6 +74,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -78,23 +88,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -103,96 +113,55 @@ esphome: project: name: "${project_name}" version: "${project_version}" - #on_boot: - # priority: 200 - # then: - # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: - number: GPIO02 - inverted: yes + number: GPIO2 + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: -# GPIO16 for KS-811 first button UNLESS -# it is a single button KS-811 in which case it is GPIO00 + # GPIO16 for KS-811 first button UNLESS it is a single button KS-811 in which case it is GPIO00 - platform: gpio pin: number: GPIO0 mode: INPUT - inverted: True + inverted: true name: "Button 1: ${switch_1_name}" on_press: - - switch.toggle: Relay_1 + - switch.toggle: relay_1 -# GPIO05 for second button (only for KS-811-2 Double or -3 Triple) -# - platform: gpio -# pin: -# number: GPIO05 -# mode: INPUT -# inverted: True -# name: "Button 2: ${switch_2_name}" -# on_press: -# - switch.toggle: Relay_2 - -# GPIO04 for third button (only for KS-811-3 Triple) -# - platform: gpio -# pin: -# number: GPIO4 -# mode: INPUT -# inverted: True -# name: "Button 3: ${switch_3_name}" -# on_press: -# - switch.toggle: Relay_3 - -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: -# GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GIPO12 + # GPIO13 for KS-811 first relay UNLESS it is KS-811-1 then it is GPIO12 - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO12 - id: Relay_1 - -# GPIO12 for second relay (only for KS-811-2 Double or -3 Triple) -# - platform: gpio -# name: "Relay 2: ${switch_2_name}" -# pin: GPIO12 -# id: Relay_2 - -# GPIO14 for third relay (only for KS-811-3 Triple) -# - platform: gpio -# name: "Relay 3: ${switch_3_name}" -# pin: GPIO14 -# id: Relay_3 - - + id: relay_1 \ No newline at end of file diff --git a/esphome/esp-downstkitchlights.yaml b/esphome/esp-downstkitchlights.yaml index e963cc4..fa2c547 100644 --- a/esphome/esp-downstkitchlights.yaml +++ b/esphome/esp-downstkitchlights.yaml @@ -1,49 +1,79 @@ -############################################# -############################################# -# DOWNSTAIRS KITCHEN MAIN LIGHTSWITCH -# V2.0 2025-06-05 YAML tidyups -# V1.0 2025-03-28 Initial Version -############################################# -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -############################################# -############################################# +#:########################################################################################:# +# TITLE: DOWNSTAIRS KITCHEN MAIN LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstkitchlights.yaml +#:########################################################################################:# +# VERSIONS: +# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 +# v2.0 2025-06-05 YAML tidyups +# v1.0 2025-03-28 Initial Version +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button (ESP8266) +# - ESP8266 board: esp01_1m +# - Pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Downstairs Kitchen main lightswitch (3-gang logical) +# - Relay 1: Dining Light +# - Relay 2: Kitchen Light +# - Relay 3: Extract Fan (virtual only, no power connected to 3rd relay) +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Physical buttons continue to toggle relays +# - MQTT (if used) continues to work +# - HA API is unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Physical buttons continue to toggle relays +# - HA API control continues to work (if enabled) +# - MQTT features will not work while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - Physical buttons continue to toggle relays +# - Accurate time is NOT needed (SNTP not needed) +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-downstkitchlights" friendly_name: "Downstairs Kitchen Lightswitch (3)" - description_comment: "Downstairs Kitch Main Lightswitch using a Zemismart KS-811 Triple Push Button. Dining Light (1), Kitchen Light (2), Extract Fan (3)" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Downstairs Kitch Main Lightswitch using a Zemismart KS-811 Triple Push Button. Dining Light (1), Kitchen Light (2), Extract Fan (3) (Layout V1.1)" + device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - # Passwords + # Project Naming + project_name: "Zemismart Technologies.KS-811 Triple" + project_version: "v2.1" + + # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-downstkitchlights_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # Switch Naming switch_1_name: "Dining Light" switch_2_name: "Kitchen Light" - switch_3_name: "Extract Fan" # This is virtual only, no power connected to 3rd relay + switch_3_name: "Extract Fan" # This is virtual only, no power connected to 3rd relay -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -52,6 +82,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -65,66 +96,69 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} # Appears on the esphome page in HA - area: ${device_area} + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -############################################# +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -############################################# +#:########################################################################################:# status_led: pin: number: GPIO2 inverted: yes -############################################# +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT inverted: True - use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning. + use_interrupt: false # This pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 @@ -147,22 +181,22 @@ binary_sensor: on_press: - switch.toggle: Relay_3 -############################################# -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -############################################# +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 id: Relay_1 + - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 id: Relay_2 + - platform: gpio name: "Relay 3: ${switch_3_name}" pin: GPIO14 - id: Relay_3 - - + id: Relay_3 \ No newline at end of file diff --git a/esphome/esp-downstloungeentry.yaml b/esphome/esp-downstloungeentry.yaml index c88630f..3e46d6f 100644 --- a/esphome/esp-downstloungeentry.yaml +++ b/esphome/esp-downstloungeentry.yaml @@ -1,31 +1,65 @@ -########################################################################################## -########################################################################################## -# DOwNSTAIRS BEDROOM 2 LIGHTSWITCH -# V3.6 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Single push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# TITLE: DOWNSTAIRS LOUNGE ENTRY LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungeentry.yaml +#:########################################################################################:# +# VERSIONS: +# v3.7 2026-02-25 Updated yaml to zorruno layout V1.1 +# v3.6 2025-07-24 YAML tidyups +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Single push button (ESP8266) +# - ESP8266 board: esp01_1m +# - Pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - This KS-811 single button is used as a remote MQTT controller (no physical load connected). +# - Button press publishes MQTT to toggle a remote device light (based on our mirrored Relay_1 state). +# - Relay_1 is used as a mirrored state holder only (kept in sync via the remote device status topic). +#:########################################################################################:# +# MQTT COMMANDS: +# - Remote command topic: +# ${mqtt_remote_device_command_topic} +# Payloads: +# ${mqtt_remote_device_command_on} +# ${mqtt_remote_device_command_off} # -# NOTES -# - -# -########################################################################################## -########################################################################################## +# - Remote status topic (mirrors remote state to Relay_1): +# ${mqtt_remote_status_topic} +# Expected payloads: +# ${mqtt_remote_device_command_on} +# ${mqtt_remote_device_command_off} +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Button continues to control the remote device via MQTT (broker must be reachable) +# - Relay_1 mirror continues to update from the remote status topic +# b) MQTT OFFLINE (or broker unreachable) +# - Button presses cannot control the remote device (publish fails) +# - Relay_1 mirror will not update (no remote status updates) +# c) Entire WiFi/Network OFFLINE +# - No remote control possible (MQTT unavailable) +# - Accurate time is NOT needed (SNTP not needed) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-downstloungeentry" friendly_name: "Downstairs Lounge Entry Lightswitch (1)" - description_comment: "Downstairs Lounge Entry Lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1)" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Downstairs Lounge Entry Lightswitch using a Zemismart KS-811 Single Push Button. Main Lights (1) (Layout V1.1)" + device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Single" # Project Details - project_version: "v3.6" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Single" + project_version: "v3.7" # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names @@ -34,35 +68,28 @@ substitutions: mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic - # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} - # MQTT LOCAL Controls - #mqtt_device_name: "downst-lounge-entry-light" - #mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + # Device Settings + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # MQTT REMOTE Controls mqtt_remote_device_name: "downst-lounge-main-lights" mqtt_remote_device_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device_name}/light1/set" - mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}/light1/state" # Topic we will use to view status locally without HA + mqtt_remote_status_topic: "${mqtt_status_main_topic}/${mqtt_remote_device_name}/light1/state" mqtt_remote_device_command_on: "On" mqtt_remote_device_command_off: "Off" - # Switch/Relay/Button Naming & Icons - #relay_icon: "mdi:lightbulb-group" switch_1_name: "Main Lights" # NOTE there is no physical connection to the lights on this switch - #switch_2_name: "Nil" - #switch_3_name: "Nil" -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -71,6 +98,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -84,23 +112,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -109,70 +137,68 @@ esphome: project: name: "${project_name}" version: "${project_version}" - #on_boot: - # priority: 200 - # then: - # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: Device-specific MQTT command triggers # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: + # Mirror remote state onto Relay_1 (only toggle if a change is needed) - topic: "${mqtt_remote_status_topic}" payload: "${mqtt_remote_device_command_on}" then: - delay: 50ms - if: condition: - lambda: 'return !id(Relay_1).state;' # Only turn on if currently OFF + lambda: 'return !id(Relay_1).state;' then: - switch.turn_on: Relay_1 + - topic: "${mqtt_remote_status_topic}" payload: "${mqtt_remote_device_command_off}" then: - delay: 50ms - if: condition: - lambda: 'return id(Relay_1).state;' # Only turn off if currently ON + lambda: 'return id(Relay_1).state;' then: - switch.turn_off: Relay_1 -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO02 inverted: yes -######################################################################################### +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: -# GPIO16 for KS-811 first button UNLESS it is KS-811-1 in which case it is GPIO00 + # GPIO16 for KS-811 first button UNLESS it is KS-811-1 in which case it is GPIO00 - platform: gpio pin: number: GPIO0 @@ -189,47 +215,13 @@ binary_sensor: return "${mqtt_remote_device_command_on}"; } -# GPIO05 for second button (only for KS-811-2 Double or -3 Triple) -# - platform: gpio -# pin: -# number: GPIO05 -# mode: INPUT -# inverted: True -# name: "Button 2: ${switch_2_name}" -# on_press: -# - switch.toggle: Relay_2 - -# GPIO04 for third button (only for KS-811-3 Triple) -# - platform: gpio -# pin: -# number: GPIO4 -# mode: INPUT -# inverted: True -# name: "Button 3: ${switch_3_name}" -# on_press: -# - switch.toggle: Relay_3 - -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: -# GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GPIO12 + # GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GPIO12 - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO12 - id: Relay_1 - -# GPIO12 for second relay (only for KS-811-2 Double or -3 Triple) -# - platform: gpio -# name: "Relay 2: ${switch_2_name}" -# pin: GPIO12 -# id: Relay_2 - -# GPIO14 for third relay (only for KS-811-3 Triple) -# - platform: gpio -# name: "Relay 3: ${switch_3_name}" -# pin: GPIO14 -# id: Relay_3 - - + id: Relay_1 \ No newline at end of file diff --git a/esphome/esp-downstloungemain.yaml b/esphome/esp-downstloungemain.yaml index 26d58c0..d775fbd 100644 --- a/esphome/esp-downstloungemain.yaml +++ b/esphome/esp-downstloungemain.yaml @@ -1,60 +1,95 @@ -########################################################################################## -########################################################################################## -# DOWNSTAIRS LOUNGE MAIN LIGHTS -# V3.5 2025-07-28 YAML tidyups -########################################################################################## -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# TITLE: DOWNSTAIRS LOUNGE MAIN LIGHTS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungemain.yaml +#:########################################################################################:# +# VERSIONS: +# v3.6 2026-02-25 Updated yaml to zorruno layout V1.1 +# v3.5 2025-07-28 YAML tidyups +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button (ESP8266) +# - Pinout/Schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - 3-gang KS-811 triple switch. +# - Button 1 toggles Relay 1 (Main Lights). Relay 1 also supports local MQTT ON/OFF commands. +# - Relay 1 publishes MQTT state updates on turn on/off. +# - Button 2 toggles Relay 2 (Back Wall Lights). +# - Button 3 toggles Relay 3 (Spare). NOTE: nothing connected to this output (as noted). +# - GPIO16 does not support interrupts; polling is used for Button 1 (suppresses warning). +#:########################################################################################:# +# MQTT COMMANDS: +# - Local command topic (Main Lights): +# ${mqtt_local_command_topic}/light1/set +# Payload "On" -> Relay 1 ON +# Payload "Off" -> Relay 1 OFF # -# NOTES -# - +# - Local status topic (Main Lights): +# ${mqtt_local_status_topic}/light1/state +# Payload "On" / "Off" published when Relay 1 changes state +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, WiFi OK +# - Physical buttons still control relays locally. +# - MQTT local control still works if broker is reachable. # -########################################################################################## -########################################################################################## +# b) MQTT OFFLINE (or broker unreachable) +# - Physical buttons still control relays locally. +# - HA/API control (if available) still works, but no MQTT command/status. +# +# c) Entire WiFi/Network OFFLINE +# - Physical buttons still control relays locally. +# - Accurate time is NOT needed (SNTP not needed). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-downstloungemain" friendly_name: "Downstairs Lounge Main Lightswitch (3)" - description_comment: "Downstairs Bedroom Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Lights (1), Back Wall Lights (2), Spare (3)" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Downstairs Bedroom Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Lights (1), Back Wall Lights (2), Spare (3) (Layout V1.1)" + device_area: "Downstairs Flat" # Project Naming - project_name: "Zemismart Technologies.KS-811 Triple" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Triple" + project_version: "v3.6" # Passwords & Secrets - api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-downstloungemain_ip mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "INFO" + update_interval: "60s" # MQTT LOCAL Controls mqtt_device_name: "downst-lounge-main-lights" - mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" + mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}" - # MQTT REMOTE Controls - - # Switch/Relay/Button Naming & Icons - #relay_icon: "mdi:lightbulb-group" + # Switch/Relay/Button Naming switch_1_name: "Main Lights" switch_2_name: "Back Wall Lights" switch_3_name: "Spare" # NOTE, Nothing connected to this switch output -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -63,6 +98,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -76,135 +112,114 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml - #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" project: name: "${project_name}" version: "${project_version}" - #on_boot: - # priority: 200 - # then: - # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + #baud_rate: 0 -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: Device-specific MQTT command triggers # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: - # Light control + # Main Lights control (Relay 1) - topic: "${mqtt_local_command_topic}/light1/set" payload: "On" then: - - switch.turn_on: Relay_1 + - switch.turn_on: relay_1 - topic: "${mqtt_local_command_topic}/light1/set" payload: "Off" then: - - switch.turn_off: Relay_1 + - switch.turn_off: relay_1 -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: - number: GPIO02 - inverted: yes + number: GPIO2 + inverted: true -######################################################################################### +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: -# GPIO16 for KS-811 first button UNLESS -# it is a single button KS-811 in which case it is GPIO00 + # Button 1 (GPIO16) - polling (GPIO16 has no interrupts) - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false name: "Button 1: ${switch_1_name}" on_press: - - switch.toggle: Relay_1 - # - mqtt.publish: - # topic: "${mqtt_local_command_topic}" - # payload: !lambda |- - # if (id(Relay_1).state) { - # return "${mqtt_local_command_off}"; - # } else { - # return "${mqtt_local_command_on}"; - # } + - switch.toggle: relay_1 -# GPIO05 for second button (only for KS-811-2 Double or -3 Triple) + # Button 2 (GPIO05) - platform: gpio pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - - switch.toggle: Relay_2 + - switch.toggle: relay_2 -# GPIO04 for third button (only for KS-811-3 Triple) + # Button 3 (GPIO04) - platform: gpio pin: number: GPIO4 mode: INPUT - inverted: True + inverted: true name: "Button 3: ${switch_3_name}" on_press: - - switch.toggle: Relay_3 + - switch.toggle: relay_3 -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: -# GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GIPO12 + # Relay 1 (GPIO13) + publish MQTT status - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 - id: Relay_1 - # publish status updates when the light turns on/off: + id: relay_1 on_turn_on: - mqtt.publish: topic: "${mqtt_local_status_topic}/light1/state" @@ -214,17 +229,14 @@ switch: topic: "${mqtt_local_status_topic}/light1/state" payload: "Off" - -# GPIO12 for second relay (only for KS-811-2 Double or -3 Triple) + # Relay 2 (GPIO12) - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 - id: Relay_2 + id: relay_2 -# GPIO14 for third relay (only for KS-811-3 Triple) + # Relay 3 (GPIO14) - platform: gpio name: "Relay 3: ${switch_3_name}" pin: GPIO14 - id: Relay_3 - - + id: relay_3 \ No newline at end of file diff --git a/esphome/esp-downstloungeoutside.yaml b/esphome/esp-downstloungeoutside.yaml index c73b0ac..87320e1 100644 --- a/esphome/esp-downstloungeoutside.yaml +++ b/esphome/esp-downstloungeoutside.yaml @@ -1,60 +1,76 @@ -########################################################################################## -########################################################################################## -# DOwNSTAIRS BEDROOM 2 LIGHTSWITCH -# V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# TITLE: DOWNSTAIRS LOUNGE OUTSIDE LIGHTS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstloungeoutside.yaml +#:########################################################################################:# +# VERSIONS: +# v3.6 2026-02-25 Updated yaml to zorruno layout V1.1 +# v3.5 2025-07-24 YAML tidyups +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Double push button (ESP8266) +# - Pinout/Schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - 2-gang KS-811 double switch. +# - Button 1 toggles Relay 1 (Outside Lights). +# - Button 2 toggles Relay 2 (Spare). +# - GPIO16 does not support interrupts; polling is used for Button 1 (suppresses warning). +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, WiFi OK +# - Physical buttons still control relays locally. +# - MQTT is optional; device operates as a normal switch without HA. # -# NOTES -# - +# b) MQTT OFFLINE (or broker unreachable) +# - Physical buttons still control relays locally. +# - HA/API control (if available) still works, but no MQTT command/status. # -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network OFFLINE +# - Physical buttons still control relays locally. +# - Accurate time is NOT needed (SNTP not needed). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-downstloungeoutside" friendly_name: "Downstairs Lounge Outside Lights (2)" - description_comment: "Downstairs Lounge Outside Lightswitch using a Zemismart KS-811 Double Push Button. Outside Lights (1), Spare (2)" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Downstairs Lounge Outside Lightswitch using a Zemismart KS-811 Double Push Button. Outside Lights (1), Spare (2) (Layout V1.1)" + device_area: "Downstairs Flat" # Project Naming - project_name: "Zemismart Technologies.KS-811 Triple" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" + project_version: "v3.6" # Passwords & Secrets - api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-downstloungeoutside_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "INFO" + update_interval: "60s" - # MQTT LOCAL Controls - #mqtt_device_name: "downst-bedroom2-lights" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - - # MQTT REMOTE Controls - - # Switch/Relay/Button Naming & Icons - #relay_icon: "mdi:lightbulb-group" + # Switch/Relay/Button Naming switch_1_name: "Outside Lights" switch_2_name: "Spare" #switch_3_name: "Nil" -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -63,6 +79,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -76,121 +93,91 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml - #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" project: name: "${project_name}" version: "${project_version}" - #on_boot: - # priority: 200 - # then: - # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + #baud_rate: 0 -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: -# GPIO16 for KS-811 first button UNLESS -# it is a single button KS-811 in which case it is GPIO00 + # Button 1 (GPIO16) - polling (GPIO16 has no interrupts) - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false name: "Button 1: ${switch_1_name}" on_press: - - switch.toggle: Relay_1 + - switch.toggle: relay_1 -# GPIO05 for second button (only for KS-811-2 Double or -3 Triple) + # Button 2 (GPIO05) - platform: gpio pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - - switch.toggle: Relay_2 + - switch.toggle: relay_2 -# GPIO04 for third button (only for KS-811-3 Triple) -# - platform: gpio -# pin: -# number: GPIO4 -# mode: INPUT -# inverted: True -# name: "Button 3: ${switch_3_name}" -# on_press: -# - switch.toggle: Relay_3 - -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: -# GPIO13 for KS-811 first button + # Relay 1 (GPIO13) - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 - id: Relay_1 + id: relay_1 -# GPIO12 for second relay (only for KS-811-2 Double or -3 Triple) + # Relay 2 (GPIO12) - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 - id: Relay_2 - -# GPIO14 for third relay (only for KS-811-3 Triple) -# - platform: gpio -# name: "Relay 3: ${switch_3_name}" -# pin: GPIO14 -# id: Relay_3 - - + id: relay_2 \ No newline at end of file diff --git a/esphome/esp-downstmasterbedrmlights.yaml b/esphome/esp-downstmasterbedrmlights.yaml index 1e23230..6ca4013 100644 --- a/esphome/esp-downstmasterbedrmlights.yaml +++ b/esphome/esp-downstmasterbedrmlights.yaml @@ -1,62 +1,77 @@ -########################################################################################## -########################################################################################## -# DOWNSTAIRS MASTER BEDROOM 1 LIGHTS -# V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# TITLE: DOWNSTAIRS MASTER BEDROOM 1 LIGHTS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-downstmasterbedrmlights.yaml +#:########################################################################################:# +# VERSIONS: +# v3.6 2026-02-25 Updated yaml to zorruno layout V1.1 +# v3.5 2025-07-24 YAML tidyups +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button (ESP8266) +# - ESP8266 board: esp01_1m +# - Pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Downstairs Master Bedroom 1 main lightswitch using a KS-811 (triple style device). +# - Intended circuits: +# 1) Main Lights (Relay 1 / Button 1) +# 2) Wardrobe Lights (Relay 2 / Button 2) +# 3) Spare (not configured in this YAML; commented sections provided) +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Local button control continues to toggle relays. +# - MQTT/API publishing to HA may not be available until HA returns. +# b) MQTT OFFLINE (or broker unreachable) +# - Local button control continues to toggle relays. +# - MQTT state updates (if any) will not publish. +# c) Entire WiFi/Network OFFLINE +# - Local button control continues to toggle relays. +# - Accurate time is NOT needed (SNTP not needed). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-downstmasterbedrmlights" friendly_name: "Downstairs Master Bedroom 1 Lightswitch (2)" - description_comment: "Downstairs Master Bedroom 1 Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Lights (1), Wardrobe Lights (2), Spare (3)" - device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Downstairs Master Bedroom 1 Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Lights (1), Wardrobe Lights (2), Spare (3) (Layout V1.1)" + device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" + project_version: "v3.6" # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-downstmasterbedrmlights_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - - # MQTT LOCAL Controls - #mqtt_device_name: "downst-bedroom2-lights" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA - - # MQTT REMOTE Controls + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # Switch/Relay/Button Naming & Icons - #relay_icon: "mdi:lightbulb-group" switch_1_name: "Main Lights" switch_2_name: "Wardrobe Lights" #switch_3_name: "Spare" -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -65,6 +80,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -78,23 +94,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -103,56 +119,52 @@ esphome: project: name: "${project_name}" version: "${project_version}" - #on_boot: - # priority: 200 - # then: - # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO02 inverted: yes -######################################################################################### +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: -# GPIO16 for KS-811 first button + # GPIO16 for KS-811 first button - platform: gpio pin: number: GPIO16 mode: INPUT inverted: True - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 -# GPIO05 for second button (only for KS-811-2 Double or -3 Triple) + # GPIO05 for second button (only for KS-811-2 Double or -3 Triple) - platform: gpio pin: number: GPIO05 @@ -162,37 +174,35 @@ binary_sensor: on_press: - switch.toggle: Relay_2 -# GPIO04 for third button (only for KS-811-3 Triple) -# - platform: gpio -# pin: -# number: GPIO4 -# mode: INPUT -# inverted: True -# name: "Button 3: ${switch_3_name}" -# on_press: -# - switch.toggle: Relay_3 + # GPIO04 for third button (only for KS-811-3 Triple) + # - platform: gpio + # pin: + # number: GPIO4 + # mode: INPUT + # inverted: True + # name: "Button 3: ${switch_3_name}" + # on_press: + # - switch.toggle: Relay_3 -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: -# GPIO13 for KS-811 first relay + # GPIO13 for KS-811 first relay - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 id: Relay_1 -# GPIO12 for second relay (only for KS-811-2 Double or -3 Triple) + # GPIO12 for second relay (only for KS-811-2 Double or -3 Triple) - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 id: Relay_2 -# GPIO14 for third relay (only for KS-811-3 Triple) -# - platform: gpio -# name: "Relay 3: ${switch_3_name}" -# pin: GPIO14 -# id: Relay_3 - - + # GPIO14 for third relay (only for KS-811-3 Triple) + # - platform: gpio + # name: "Relay 3: ${switch_3_name}" + # pin: GPIO14 + # id: Relay_3 \ No newline at end of file diff --git a/esphome/esp-entbtproxy.yaml b/esphome/esp-entbtproxy.yaml index 14d3c56..b02d92d 100644 --- a/esphome/esp-entbtproxy.yaml +++ b/esphome/esp-entbtproxy.yaml @@ -1,35 +1,66 @@ -############################################# -############################################# -# ESP32 -# Bluetooth Proxy -############################################# -############################################# +#:########################################################################################:# +# TITLE: OUTSIDE ENTRANCE BLUETOOTH PROXY +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-entbtproxy.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 +# V1.0 Unknown Initial version +#:########################################################################################:# +# HARDWARE: +# - D1 Mini ESP32 (ESP32) +#:########################################################################################:# +# OPERATION NOTES: +# - Bluetooth Proxy for ESPHome / Home Assistant (BLE tracking + proxy) +# - Uses ESP-IDF framework for stability and (often) smaller binary size +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - BLE scanning/proxy continues running +# - HA entities unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - BLE scanning/proxy continues running +# - MQTT features (if any) will not function until MQTT returns +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available +# - BLE scanning continues locally, but proxy functions needing network will not be usable +# - Accurate time is NOT needed (SNTP not needed) +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: + # Device Naming device_name: "esp-entbtproxy" friendly_name: "Outside Entrance Bluetooth Proxy" - description_comment: "D1 Mini ESP32 outside entranceway with BT Proxy" - api_key: !secret esp-entbtproxy_api_key #unfortunately you can't use substitutions in secrets names - ota_pass: !secret esp-entbtproxy_ota_pass #unfortunately you can't use substitutions in secrets names + description_comment: "D1 Mini ESP32 outside entranceway with BT Proxy (Layout V1.1)" + device_area: "Entranceway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + + # Project Naming + project_name: "Generic.ESP32 Bluetooth Proxy" + project_version: "v1.1" + + # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) + api_key: !secret esp-entbtproxy_api_key + ota_pass: !secret esp-entbtproxy_ota_pass static_ip_address: !secret esp-entbtproxy_ip - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - room: "Entranceway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - ############################################# - # SPECIFIC PROJECT VARIABLE SUBSTITUTIONS - ############################################# - # - # + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} -########################################################################################## + # Device Settings + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -38,6 +69,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -51,68 +83,62 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 - -############################################# -# ESPHome -# https://esphome.io/components/esphome.html -############################################# -esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} #appears on the esphome page in HA - min_version: 2024.6.0 # + diag_basic: !include common/include_basic_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 -############################################# -# ESP Platform and Framework +#:########################################################################################:# +# ESPHOME: +# https://esphome.io/components/esphome.html +#:########################################################################################:# +esphome: + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # appears on the esphome page in HA + area: "${device_area}" + min_version: 2024.6.0 + project: + name: "${project_name}" + version: "${project_version}" + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# esp32: board: esp32dev framework: - #type: arduino - type: esp-idf #Suggested Use ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. - version: recommended #recommended, latest or dev + type: esp-idf # Suggested ESP-IDF framework + version: recommended advanced: minimum_chip_revision: "3.1" # This makes the binary slightly smaller -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART if you want -############################################# -# Bluetooth +#:########################################################################################:# +# BLUETOOTH: # https://esphome.io/components/bluetooth_proxy.html # https://esphome.io/components/esp32_ble_tracker.html -# Remember that this takes a LOT of processing. On the -# ESP32, enable the IDF framework, and disable the -# Web server component. Changing to the IDF framework -# needs to be via cable not OTA to change the -# partition setup. -############################################# +#:########################################################################################:# bluetooth_proxy: active: true esp32_ble_tracker: scan_parameters: - # We currently use the defaults to ensure Bluetooth - # can co-exist with WiFi In the future we may be able to - # enable the built-in coexistence logic in ESP-IDF - active: true - + # Defaults used so Bluetooth can co-exist with WiFi + active: true \ No newline at end of file diff --git a/esphome/esp-entmulti.yaml b/esphome/esp-entmulti.yaml index dc8e1fa..bfaade8 100644 --- a/esphome/esp-entmulti.yaml +++ b/esphome/esp-entmulti.yaml @@ -1,53 +1,92 @@ -############################################# -############################################# -# +#:########################################################################################:# +# TITLE: OUTSIDE ENTRANCE MULTISENSOR +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-entmulti.yaml +#:########################################################################################:# +# VERSIONS: +# V1.2 2026-02-25 Updated yaml to zorruno layout V1.1 +# V1.1 2026-02-23 +# - Add full header + project metadata block +# - Fix LD2140 -> LD2410 typos throughout +# - Normalize booleans and tidy naming consistency +# - Prefix LD2410 entity names with friendly name for cleaner HA entities +# - Add LD2410 buttons (factory reset/restart/query) + text sensors (fw version/bt mac) +# - Add composite Occupancy sensor (mmWave OR PIR) with delayed-off +# - Correct UART comments (LD2410 uses 256000 baud out-of-box in ESPHome) +# V1.0 2026-02-xx Initial version (as provided) +#:########################################################################################:# +# HARDWARE: +# - D1 Mini ESP32 (ESP32) +# - HI-LINK LD2410 mmWave presence sensor (UART) +# - PIR sensor on GPIO13 +# - 2x RF vibration inputs (bins) on GPIO4 and GPIO15 # -############################################# -############################################# +# NOTES: +# - ESPHome 2026.1+ requires API encryption and OTA SHA256 authentication. +# Ensure your common package files are updated accordingly. +# - LD2410 via ESPHome uses 256000 baud by default; parity NONE, stop_bits 1. +# - GPIO2/GPIO15 are strapping pins on ESP32. You are already suppressing warnings, +# but be aware boot behavior can be affected by external circuitry on these pins. +#:########################################################################################:# +# OPERATION NOTES: +# - Provides LD2410 presence (moving/still/target), plus PIR motion and 2x vibration inputs. +# - Composite Occupancy sensor is mmWave OR PIR with delayed-off for stable lighting triggers. +# - Device is sensor-driven only (no timeclocks); SNTP is optional for diagnostics/time entities. +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Sensors continue running locally +# - MQTT (if enabled/online) continues publishing; HA entities unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Sensors remain available to Home Assistant via API +# - MQTT-based automations/commands will not work while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT +# - Sensors continue running locally; automation depends on local logic only +# - Accurate time is NOT needed (SNTP not needed); loss of network does not affect timing +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: + # Device Naming device_name: "esp-entmulti" friendly_name: "Outside Entrance Multisensor" - description_comment: "D1 Mini ESP32 outside entranceway with, mmWave presence, PIR and more" - api_key: !secret esp-entmulti_api_key #unfortunately you can't use substitutions in secrets names - ota_pass: !secret esp-entmulti_ota_pass #unfortunately you can't use substitutions in secrets names - static_ip_address: !secret esp-entmulti_ip - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_time: 30s #update time for for general temp sensors etc - update_interval: "60s" # update time for for general sensors etc - room: "Entranceway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "D1 Mini ESP32 outside entranceway with mmWave presence, PIR and more (Layout V1.1)" + device_area: "Entranceway" # Allows ESP device to be automatically linked to an Area in Home Assistant. - ############################################# - # SPECIFIC PROJECT VARIABLE SUBSTITUTIONS - ############################################# - # - # + # Project Naming (shown in ESPHome dashboard / HA device info) + project_name: "zorruno.esp-entmulti" + project_version: "v1.2" - #if NOT using a secrets file, just replace these with the passwords etc (in quotes) - #wifi_ssid: !secret wifi_ssid - #wifi_password: !secret wifi_password - #fallback_ap_password: !secret fallback_ap_password - #Add these if we are giving it a static ip, or remove them in the Wifi section - #static_ip_address: !secret esp-entmulti_static_ip - #static_ip_gateway: !secret esp-entmulti_gateway - #static_ip_subnet: !secret esp-entmulti_subnet + # Passwords & Secrets + api_key: !secret esp-entmulti_api_key + ota_pass: !secret esp-entmulti_ota_pass + static_ip_address: !secret esp-entmulti_ip # unfortunately you can't use substitutions inside secrets names + mqtt_command_main_topic: !secret mqtt_command_main_topic + mqtt_status_main_topic: !secret mqtt_status_main_topic - #mqtt_server: !secret mqtt_server - #mqtt_username: !secret mqtt_username - #mqtt_password: !secret mqtt_password - #mqtt_topic: "esphome" #main topic for the mqtt server, call it what you like + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} - #web_server_username: !secret web_server_username - #web_server_password: !secret web_server_password + # MQTT LOCAL Controls (default to this device name to avoid accidental cross-device topics) + #mqtt_local_device_name: "${device_name}" + #mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_local_device_name}" + #mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_local_device_name}" -########################################################################################## + # Device Settings + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE + update_interval: "60s" # general sensor update interval (if/when used) + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -56,6 +95,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -69,378 +109,403 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} #appears on the esphome page in HA - min_version: 2024.6.0 + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" # appears on the ESPHome page in HA + area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" + min_version: 2026.2.0 - -############################################# -# ESP Platform and Framework +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# esp32: board: esp32dev framework: #type: arduino - type: esp-idf #Suggested Use ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. - version: recommended #recommended, latest or dev + type: esp-idf + version: recommended -############################################# -# ESPHome external or custom components to use -# https://esphome.io/components/external_components.html -# https://github.com/ssieb/esphome_components/tree/master/components/serial -############################################# -#external_components: -# - source: -# type: git -# url: https://github.com/ssieb/custom_components #Thanks for @ssieb components. -# components: [ serial ] #text_sensor that reads lines for a uart. Also, a sensor that reads single binary values from the uart. - -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 # set to 0 for no logging via UART (keeps UART free for sensors) -############################################# -# i2c bus -# https://esphome.io/components/i2c.html -# 10, 50, 100, 200, 800 are possible settings -# for frequency, 50kHz is default -############################################# -#i2c: -# sda: GPIO19 -# scl: GPIO21 -# scan: True #look for devices on boot up and report - #frequency: 100kHz - -############################################# -# UART Serial -# hardware on EPS32, but software, and can be glitchy on ESP8266 +#:########################################################################################:# +# UART: LD2410 Serial # https://esphome.io/components/uart.html -############################################# +#:########################################################################################:# uart: id: ld2410_uart - rx_pin: GPIO16 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang - tx_pin: GPIO17 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang - baud_rate: 256000 # default for LD2410 is 25600, 8, 0, NONE + rx_pin: GPIO16 + tx_pin: GPIO17 + baud_rate: 256000 data_bits: 8 stop_bits: 1 parity: NONE -############################################# -# Bluetooth -# https://esphome.io/components/bluetooth_proxy.html -# https://esphome.io/components/esp32_ble_tracker.html -# Remember that this takes a LOT of processing. On the -# ESP32, enable the IDF framework, and disable the -# Web server component. Changing to the IDF framework -# needs to be via cable not OTA to change the -# partition setup. -############################################# -#bluetooth_proxy: -# active: true -# cache_services: true -# -#esp32_ble_tracker: -# scan_parameters: -# active: true -# continuous: false - -############################################# -# Global Variables for use in automations etc -# https://esphome.io/guides/automations.html?highlight=globals#global-variables -############################################# - - -############################################# -# General esp status LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -############################################# +#:########################################################################################:# status_led: pin: - number: GPIO2 #ESP32 Onboard LED - ignore_strapping_warning: True #https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins + number: GPIO2 + ignore_strapping_warning: true inverted: false -############################################# -# Interval Automations -# https://esphome.io/guides/automations.html -############################################# - -############################################# -# LD2410 Sensors +#:########################################################################################:# +# LD2410: # https://esphome.io/components/sensor/ld2410.html -# https://www.hlktech.net/index.php?id=988 -############################################# +#:########################################################################################:# ld2410: + id: ld2410_1 uart_id: ld2410_uart -############################################# -# Number Sensors (custom component) -# refer https://github.com/ssieb/esphome_components/tree/master/components/serial -############################################# +#:########################################################################################:# +# NUMBER: +# https://esphome.io/components/number/ +#:########################################################################################:# number: - platform: ld2410 + ld2410_id: ld2410_1 + timeout: - name: Timeout + name: "${friendly_name} LD2410 Timeout" + entity_category: config + light_threshold: - name: Light Threshold + name: "${friendly_name} LD2410 Light Threshold" + entity_category: config + max_move_distance_gate: - name: Max Move Distance Gate + name: "${friendly_name} LD2410 Max Move Distance Gate" + entity_category: config + max_still_distance_gate: - name: Max Still Distance Gate + name: "${friendly_name} LD2410 Max Still Distance Gate" + entity_category: config + g0: move_threshold: - name: g0 move threshold + name: "${friendly_name} LD2410 G0 Move Threshold" + entity_category: config still_threshold: - name: g0 still threshold + name: "${friendly_name} LD2410 G0 Still Threshold" + entity_category: config g1: move_threshold: - name: g1 move threshold + name: "${friendly_name} LD2410 G1 Move Threshold" + entity_category: config still_threshold: - name: g1 still threshold + name: "${friendly_name} LD2410 G1 Still Threshold" + entity_category: config g2: move_threshold: - name: g2 move threshold + name: "${friendly_name} LD2410 G2 Move Threshold" + entity_category: config still_threshold: - name: g2 still threshold + name: "${friendly_name} LD2410 G2 Still Threshold" + entity_category: config g3: move_threshold: - name: g3 move threshold + name: "${friendly_name} LD2410 G3 Move Threshold" + entity_category: config still_threshold: - name: g3 still threshold + name: "${friendly_name} LD2410 G3 Still Threshold" + entity_category: config g4: move_threshold: - name: g4 move threshold + name: "${friendly_name} LD2410 G4 Move Threshold" + entity_category: config still_threshold: - name: g4 still threshold + name: "${friendly_name} LD2410 G4 Still Threshold" + entity_category: config g5: move_threshold: - name: g5 move threshold + name: "${friendly_name} LD2410 G5 Move Threshold" + entity_category: config still_threshold: - name: g5 still threshold + name: "${friendly_name} LD2410 G5 Still Threshold" + entity_category: config g6: move_threshold: - name: g6 move threshold + name: "${friendly_name} LD2410 G6 Move Threshold" + entity_category: config still_threshold: - name: g6 still threshold + name: "${friendly_name} LD2410 G6 Still Threshold" + entity_category: config g7: move_threshold: - name: g7 move threshold + name: "${friendly_name} LD2410 G7 Move Threshold" + entity_category: config still_threshold: - name: g7 still threshold + name: "${friendly_name} LD2410 G7 Still Threshold" + entity_category: config g8: move_threshold: - name: g8 move threshold + name: "${friendly_name} LD2410 G8 Move Threshold" + entity_category: config still_threshold: - name: g8 still threshold + name: "${friendly_name} LD2410 G8 Still Threshold" + entity_category: config -#The ld2410 select allows you to control your LD2410 Sensor. -#distance_resolution (Optional): Control the gates distance resolution. Can be 0.75m or 0.2m. Defaults to 0.75m. All options from Select. -#baud_rate (Optional): Control the serial port baud rate. Defaults to 256000. Once changed, all sensors will stop working until a fresh install with an updated UART Component configuration. All options from Select. -#light_function (Optional): If set, will affect the OUT pin value, based on light threshold. Can be off, low or above. Defaults to off. All options from Select. -#out_pin_level (Optional): Control OUT pin away value. Can be low or high. Defaults to low. All options from Select. -#ld2410_id (Optional, ID): Manually specify the ID for the LD2410 Sensor component if you are using multiple components. +#:########################################################################################:# +# SELECT: +# https://esphome.io/components/select/index.html +#:########################################################################################:# select: - platform: ld2410 - distance_resolution: - name: ${friendly_name} LD2140 Distance Resolution + ld2410_id: ld2410_1 + + distance_resolution: + name: "${friendly_name} LD2410 Distance Resolution" + entity_category: config baud_rate: - name: ${friendly_name} LD2140 Baud Rate + name: "${friendly_name} LD2410 Baud Rate" + entity_category: config light_function: - name: ${friendly_name} LD2140 Light Function + name: "${friendly_name} LD2410 Light Function" + entity_category: config out_pin_level: - name: ${friendly_name} LD2140 Out Pin Level + name: "${friendly_name} LD2410 Out Pin Level" + entity_category: config -############################################# -# General Sensors -# https://esphome.io/components/sensor/index.html -############################################# +#:########################################################################################:# +# SENSOR: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: -# - platform: bme280_i2c -# address: 0x76 -# update_interval: ${update_time} -# temperature: -# name: ${friendly_name} BME280 Temp -# accuracy_decimals: 1 -# oversampling: 2x -# pressure: -# name: ${friendly_name} BME280 Pressure -# oversampling: 2x -# humidity: -# name: ${friendly_name} BME280 Humidity -# accuracy_decimals: 1 -# oversampling: 2x - -#The ld2410 sensor values - platform: ld2410 + ld2410_id: ld2410_1 + light: - name: Light + name: "${friendly_name} LD2410 Light" + entity_category: diagnostic moving_distance: - name : Moving Distance + name: "${friendly_name} LD2410 Moving Distance" + entity_category: diagnostic still_distance: - name: Still Distance + name: "${friendly_name} LD2410 Still Distance" + entity_category: diagnostic moving_energy: - name: Move Energy + name: "${friendly_name} LD2410 Move Energy" + entity_category: diagnostic still_energy: - name: Still Energy + name: "${friendly_name} LD2410 Still Energy" + entity_category: diagnostic detection_distance: - name: Detection Distance + name: "${friendly_name} LD2410 Detection Distance" + entity_category: diagnostic + g0: move_energy: - name: g0 move energy + name: "${friendly_name} LD2410 G0 Move Energy" + entity_category: diagnostic still_energy: - name: g0 still energy + name: "${friendly_name} LD2410 G0 Still Energy" + entity_category: diagnostic g1: move_energy: - name: g1 move energy + name: "${friendly_name} LD2410 G1 Move Energy" + entity_category: diagnostic still_energy: - name: g1 still energy + name: "${friendly_name} LD2410 G1 Still Energy" + entity_category: diagnostic g2: move_energy: - name: g2 move energy + name: "${friendly_name} LD2410 G2 Move Energy" + entity_category: diagnostic still_energy: - name: g2 still energy + name: "${friendly_name} LD2410 G2 Still Energy" + entity_category: diagnostic g3: move_energy: - name: g3 move energy + name: "${friendly_name} LD2410 G3 Move Energy" + entity_category: diagnostic still_energy: - name: g3 still energy + name: "${friendly_name} LD2410 G3 Still Energy" + entity_category: diagnostic g4: move_energy: - name: g4 move energy + name: "${friendly_name} LD2410 G4 Move Energy" + entity_category: diagnostic still_energy: - name: g4 still energy + name: "${friendly_name} LD2410 G4 Still Energy" + entity_category: diagnostic g5: move_energy: - name: g5 move energy + name: "${friendly_name} LD2410 G5 Move Energy" + entity_category: diagnostic still_energy: - name: g5 still energy + name: "${friendly_name} LD2410 G5 Still Energy" + entity_category: diagnostic g6: move_energy: - name: g6 move energy + name: "${friendly_name} LD2410 G6 Move Energy" + entity_category: diagnostic still_energy: - name: g6 still energy + name: "${friendly_name} LD2410 G6 Still Energy" + entity_category: diagnostic g7: move_energy: - name: g7 move energy + name: "${friendly_name} LD2410 G7 Move Energy" + entity_category: diagnostic still_energy: - name: g7 still energy + name: "${friendly_name} LD2410 G7 Still Energy" + entity_category: diagnostic g8: move_energy: - name: g8 move energy + name: "${friendly_name} LD2410 G8 Move Energy" + entity_category: diagnostic still_energy: - name: g8 still energy + name: "${friendly_name} LD2410 G8 Still Energy" + entity_category: diagnostic -# The ld2410 switch allows you to control your LD2410 Sensor. -#Bluetooth switch is only useful of you have a B or C model +#:########################################################################################:# +# SWITCH: +# https://esphome.io/components/switch/ +#:########################################################################################:# switch: - platform: ld2410 + ld2410_id: ld2410_1 + engineering_mode: - name: ${friendly_name} LD2140 Engineering Mode + name: "${friendly_name} LD2410 Engineering Mode" + entity_category: config + + # Only useful if you have a B/C model (bluetooth hardware present) #bluetooth: - #name: ${friendly_name} LD2140 Control Bluetooth - - -#The ld2410 button allows resetting -#button: -# - platform: ld2410 -# factory_reset: -# name: ${friendly_name} LD2140 Factory reset" -# restart: -# name: ${friendly_name} LD2140 Restart -## query_params: -# name: Query Parameters - -############################################# -# Text Sensors -# refer https://esphome.io/components/text_sensor/index.html -############################################# -#The ld2410 text sensor allows you to get information about your LD2410 Sensor. -#Bluetooth sensor is only useful of you have a B or C model -#text_sensor: -# - platform: ld2410 -# version: -# name: ${friendly_name} LD2140 Firmware Version - #mac_address: - #name: ${friendly_name} LD2140 BT MAC Address - - -############################################# -# Binary Sensors -# https://esphome.io/components/binary_sensor/index.html -############################################# -binary_sensor: + # name: "${friendly_name} LD2410 Bluetooth Enable" + # entity_category: config +#:########################################################################################:# +# BUTTON: +# https://esphome.io/components/button/index.html +#:########################################################################################:# +button: - platform: ld2410 - has_target: - name: ${friendly_name} Presence - has_moving_target: - name: ${friendly_name} Moving Target - has_still_target: - name: ${friendly_name} Still Target - out_pin_presence_status: - name: ${friendly_name} LD2140 Out Pin Presence Status + ld2410_id: ld2410_1 - #Standard PIR Sensor + factory_reset: + name: "${friendly_name} LD2410 Factory Reset" + entity_category: config + restart: + name: "${friendly_name} LD2410 Restart" + entity_category: config + query_params: + name: "${friendly_name} LD2410 Query Params" + entity_category: diagnostic + +#:########################################################################################:# +# TEXT SENSOR: +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# +text_sensor: + - platform: ld2410 + ld2410_id: ld2410_1 + + version: + name: "${friendly_name} LD2410 Firmware Version" + entity_category: diagnostic + mac_address: + name: "${friendly_name} LD2410 Bluetooth MAC" + entity_category: diagnostic + +#:########################################################################################:# +# BINARY SENSOR: +# https://esphome.io/components/binary_sensor/ +#:########################################################################################:# +binary_sensor: + # LD2410 presence states + - platform: ld2410 + ld2410_id: ld2410_1 + + has_target: + name: "${friendly_name} Presence" + id: mmwave_presence + has_moving_target: + name: "${friendly_name} Moving Target" + id: mmwave_moving + has_still_target: + name: "${friendly_name} Still Target" + id: mmwave_still + out_pin_presence_status: + name: "${friendly_name} LD2410 Out Pin Presence Status" + entity_category: diagnostic + + # Standard PIR Sensor - platform: gpio + id: pir_motion pin: number: GPIO13 mode: - input: True - pullup: True - inverted: True - filters: + input: true + pullup: false + inverted: false + filters: - delayed_on: 50ms - name: ${friendly_name} PIR Sensor + name: "${friendly_name} PIR Sensor" device_class: motion - #RF Input from Vibration Sensor (Green Bin) + # RF Input from Vibration Sensor (Green Bin) - platform: gpio + id: green_bin_motion pin: - number: GPIO04 + number: GPIO4 mode: input: true pullup: true - inverted: True + inverted: true filters: - delayed_on: 20ms - name: ${friendly_name} Green Bin motion + name: "${friendly_name} Green Bin Motion" device_class: vibration - #RF Input from Vibration Sensor (Red Bin) + # RF Input from Vibration Sensor (Red Bin) - platform: gpio + id: red_bin_motion pin: number: GPIO15 mode: input: true pullup: true - ignore_strapping_warning: true # GPIO15: This just supresses a warning, we know what we are doing - inverted: True + ignore_strapping_warning: true + inverted: true filters: - delayed_on: 20ms - name: ${friendly_name} Red Bin motion - device_class: vibration \ No newline at end of file + name: "${friendly_name} Red Bin Motion" + device_class: vibration + + # Composite occupancy (mmWave OR PIR) for lighting/automation use + - platform: template + name: "${friendly_name} Occupancy" + device_class: occupancy + lambda: |- + return id(mmwave_presence).state || id(pir_motion).state; + filters: + - delayed_off: 30s \ No newline at end of file diff --git a/esphome/esp-entrancebathrmlights.yaml b/esphome/esp-entrancebathrmlights.yaml index a380461..0d470e1 100644 --- a/esphome/esp-entrancebathrmlights.yaml +++ b/esphome/esp-entrancebathrmlights.yaml @@ -1,59 +1,75 @@ -########################################################################################## -########################################################################################## -# ENTRANCE BATHROOM LIGHTSWITCH -# V3.7 2025-09-34 upload to this bathroom -# V3.5 2025-07-24 YAML tidyups -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - Light switch with light and extract fan -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# TITLE: ENTRANCE BATHROOM LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-entrancebathrmlights.yaml +#:########################################################################################:# +# VERSIONS: +# 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) +# v3.5 2025-07-24 YAML tidyups +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Double push button (ESP8266) +# - ESP8266 board: esp01_1m +# - Pinout/schematic: +# https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Entrance bathroom switch with 2 outputs: +# 1) Main Lights +# 2) Extract Fan +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Local button control continues to toggle relays. +# - MQTT/API publishing to HA may not be available until HA returns. +# b) MQTT OFFLINE (or broker unreachable) +# - Local button control continues to toggle relays. +# - MQTT state updates (if any) will not publish. +# c) Entire WiFi/Network OFFLINE +# - Local button control continues to toggle relays. +# - Accurate time is NOT needed (SNTP not needed). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-entrancebathrmlights" friendly_name: "Entrance Bathroom Lightswitch (2)" - description_comment: "Entrance bathroom lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Extract Fan (2)" - device_area: "Entranceway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Entrance bathroom lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Extract Fan (2) (Layout V1.1)" + device_area: "Entranceway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v3.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" + project_version: "v3.8" # Passwords & Secrets api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-entrancebathrmlights_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings - #relay_icon: "mdi:lightbulb-group" - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - - # MQTT LOCAL Controls - #mqtt_device_name: "bedroom2-lights" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # Switch Naming switch_1_name: "Main Lights" switch_2_name: "Extract Fan" - #switch_3_name: "Nil" -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -62,6 +78,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -75,22 +92,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -99,50 +117,46 @@ esphome: project: name: "${project_name}" version: "${project_version}" - #on_boot: - # priority: 200 - # then: - # - switch.turn_on: Relay_2 -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + #baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 inverted: yes -######################################################################################### +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT inverted: True - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 @@ -156,20 +170,10 @@ binary_sensor: on_press: - switch.toggle: Relay_2 -# KS-811-2 is a double only -# - platform: gpio -# pin: -# number: GPIO4 -# mode: INPUT -# inverted: True -# name: "Button 3: ${switch_3_name}" -# on_press: -# - switch.toggle: Relay_3 - -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -179,12 +183,4 @@ switch: - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 - id: Relay_2 - -# KS-811-2 is a double only -# - platform: gpio -# name: "Relay 3: ${switch_3_name}" -# pin: GPIO14 -# id: Relay_3 - - + id: Relay_2 \ No newline at end of file diff --git a/esphome/esp-entrancelightswitch.yaml b/esphome/esp-entrancelightswitch.yaml index c4f05c6..f73d7b6 100644 --- a/esphome/esp-entrancelightswitch.yaml +++ b/esphome/esp-entrancelightswitch.yaml @@ -1,59 +1,83 @@ -########################################################################################## -########################################################################################## -# Main Entrance LIGHTSWITCH -# V3.7 2025-09-15 upload to this lightswitch from copy -# -########################################################################################## -# Zemismart KS-811 Double push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - Light switch with 2 sets of lights -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# TITLE: MAIN ENTRANCE LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-entrancelightswitch.yaml +#:########################################################################################:# +# VERSIONS: +# V3.8 2026-02-25 Updated yaml to zorruno layout V1.1 +# V3.7 2025-09-15 Upload to this lightswitch from copy +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Double push button (ESP8266) +# - Status LED: GPIO2 +# - Buttons: GPIO16 (Button 1), GPIO5 (Button 2) +# - Relays: GPIO13 (Relay 1), GPIO12 (Relay 2) +# - Pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Button 1 toggles Relay 1 (Entrance Lights). +# - Relay 2 is forced ON at boot (permanently on) to power an external light controller. +# - Button 2 is currently not assigned to any action (relay remains ON from boot). +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Physical button control continues (Relay 1 toggles locally) +# - Relay 2 remains ON (external controller stays powered) +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Physical button control continues +# - HA control continues via API +# c) Entire WiFi/Network OFFLINE +# - Physical button control continues (local operation) +# - Relay 2 remains ON (external controller stays powered) +# - Accurate time is NOT needed (SNTP not needed) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-entrancelightswitch" friendly_name: "Main Entrance Lightswitch (2)" - description_comment: "Main Entrance lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Bench Lights (2)" - device_area: "Kitchen" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Main Entrance lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Bench Lights (2) (Layout V1.1)" + device_area: "Kitchen" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Zemismart Technologies.KS-811 Double" # Project Details - project_version: "v3.7" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Zemismart Technologies.KS-811 Double" # Project Details + project_version: "v3.8" # Project version denotes release of yaml file, allowing checking of deployed vs latest version - # Passwords & Secrets - api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-entrancelightswitch_ip #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - #relay_icon: "mdi:lightbulb-group" - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # MQTT LOCAL Controls #mqtt_device_name: "bedroom2-lights" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" + #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Switch Naming switch_1_name: "Entrance Lights" - switch_2_name: "External Light Controller" #permanently on, and pushbutton sends MQTT - #switch_3_name: "Nil" - -######################################################################################### + switch_2_name: "External Light Controller" # permanently on, and pushbutton sends MQTT (not configured here) + #switch_3_name: "Nil" + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -62,6 +86,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -75,22 +100,23 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -99,50 +125,48 @@ esphome: project: name: "${project_name}" version: "${project_version}" - on_boot: + on_boot: priority: 200 then: - - switch.turn_on: Relay_2 # Permanently on + - switch.turn_on: Relay_2 # Permanently on -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + early_pin_init: false # Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + #baud_rate: 0 -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only suppresses a warning. name: "Button 1: ${switch_1_name}" on_press: - switch.toggle: Relay_1 @@ -151,25 +175,25 @@ binary_sensor: pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" -# on_press: -# - switch.toggle: Relay_2 + #on_press: + # - switch.toggle: Relay_2 -# KS-811-2 is a double only -# - platform: gpio -# pin: -# number: GPIO4 -# mode: INPUT -# inverted: True -# name: "Button 3: ${switch_3_name}" -# on_press: -# - switch.toggle: Relay_3 + # KS-811-2 is a double only + #- platform: gpio + # pin: + # number: GPIO4 + # mode: INPUT + # inverted: true + # name: "Button 3: ${switch_3_name}" + # on_press: + # - switch.toggle: Relay_3 -######################################################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -######################################################################################### +#:########################################################################################:# switch: - platform: gpio name: "Relay 1: ${switch_1_name}" @@ -181,10 +205,8 @@ switch: pin: GPIO12 id: Relay_2 -# KS-811-2 is a double only -# - platform: gpio -# name: "Relay 3: ${switch_3_name}" -# pin: GPIO14 -# id: Relay_3 - - + # KS-811-2 is a double only + #- platform: gpio + # name: "Relay 3: ${switch_3_name}" + # pin: GPIO14 + # id: Relay_3 \ No newline at end of file diff --git a/esphome/esp-entranceoutsideledlights.yaml b/esphome/esp-entranceoutsideledlights.yaml new file mode 100644 index 0000000..7f9f48f --- /dev/null +++ b/esphome/esp-entranceoutsideledlights.yaml @@ -0,0 +1,969 @@ +########################################################################################## +########################################################################################## +# FRONT ENTRANCEWAY LED LIGHT CONTROLS +# File: esp-entranceoutsideledlights.yaml +# +# v1.0 - 2026-02-23 Initial version (converted from Tasmota) +# +# Hardware: H801 (ESP8266EX) 5-channel PWM MOSFET LED controller +# +########################################################################################### +# NOTES +# - H801 PWM outputs (typical / ESPHome Devices): +# PWM1 / R -> GPIO15 +# PWM2 / G -> GPIO13 +# PWM3 / B -> GPIO12 +# PWM4 / W1 -> GPIO14 +# PWM5 / W2 -> GPIO4 +# Some templates swap G/B labeling (GPIO12 vs GPIO13). If outputs appear swapped, +# just swap out2_pwm_pin and out3_pwm_pin below. +# +# - We expose helper entities per channel: +# * On/Off switch (ramps using per-channel ramp time) +# * Brightness slider 0-100% normalized to the per-channel hard limit +# * Ramp time (seconds) for a full 0 -> hard limit transition +# * Hard limit (percent) absolute cap for that channel +# +# - Underlying PWM light entities are INTERNAL so HA cannot bypass the hard limit. +# +########################################################################################## +########################################################################################## + +########################################################################################## +# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +# If NOT using a secrets file, just replace these with the passwords etc (in quotes) +########################################################################################## +substitutions: + # Device Naming + device_name: "esp-entranceoutsideledlights" + friendly_name: "Front Entranceway LED Light controls" + description_comment: "H801 ESP8266 5-channel PWM LED controller (Entranceway)" + device_area: "Entranceway" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + + # Project Naming + project_name: "H801.5CH PWM LED Controller" + project_version: "v1.0" + + # Passwords & Secrets + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass + static_ip_address: !secret esp-entranceoutsideledlights_ip # unfortunately you can't use substitutions inside secrets names + #mqtt_command_main_topic: !secret mqtt_command_main_topic + #mqtt_status_main_topic: !secret mqtt_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # MQTT LOCAL Controls (optional, kept for consistency with your templates) + #mqtt_local_device_name: "entranceoutsideledlights" + #mqtt_local_command_topic: "${mqtt_command_main_topic}/${mqtt_local_device_name}" + #mqtt_local_status_topic: "${mqtt_status_main_topic}/${mqtt_local_device_name}" + + # Device Settings + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG, VERBOSE, VERY_VERBOSE + update_interval: "60s" + + # OUTPUT NAMES + out1_name: "Main Entrance Outside LED Lights" + out2_name: "Number 16 LED Light" + out3_name: "Spare 3" + out4_name: "Spare 4" + out5_name: "Spare 5" + + # H801 PWM PINS (easy swap here if needed) + out1_pwm_pin: "GPIO15" + out2_pwm_pin: "GPIO13" + out3_pwm_pin: "GPIO12" + out4_pwm_pin: "GPIO14" + out5_pwm_pin: "GPIO4" + pwm_frequency: "1000 Hz" + +########################################################################################## +# PACKAGES: Included Common Packages +# https://esphome.io/components/packages.html +########################################################################################## +packages: + #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### + common_wifi: !include + file: common/network_common.yaml + vars: + local_device_name: "${device_name}" + local_static_ip_address: "${static_ip_address}" + local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" + + #### HOME ASSISTANT API (choose encryption or no encryption options) #### + common_api: !include + file: common/api_common.yaml + #file: common/api_common_noencryption.yaml + vars: + local_api_key: "${api_key}" + + #### MQTT #### + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + + #### SNTP (Only use if you want/need accurate timeclocks) #### + common_sntp: !include common/sntp_common.yaml + + #### DIAGNOSTICS Sensors #### + diag_basic: !include common/include_basic_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 + +############################################# +# ESPHome +# https://esphome.io/components/esphome.html +############################################# +esphome: + name: ${device_name} + friendly_name: ${friendly_name} + comment: ${description_comment} # appears on the esphome page in HA + min_version: 2025.11.0 + area: ${device_area} + project: + name: ${project_name} + version: ${project_version} + +############################################# +# ESP Platform and Framework +# https://esphome.io/components/esp8266.html +############################################# +esp8266: + board: esp01_1m + +############################################# +# ESPHome Logging Enable +# https://esphome.io/components/logger.html +############################################# +logger: + level: ${log_level} + baud_rate: 0 # set to 0 for no logging via UART + +########################################################################################## +# OUTPUTS (H801 PWM MOSFET CHANNELS) +########################################################################################## +output: + - platform: esp8266_pwm + id: out1_pwm + pin: ${out1_pwm_pin} + frequency: ${pwm_frequency} + + - platform: esp8266_pwm + id: out2_pwm + pin: ${out2_pwm_pin} + frequency: ${pwm_frequency} + + - platform: esp8266_pwm + id: out3_pwm + pin: ${out3_pwm_pin} + frequency: ${pwm_frequency} + + - platform: esp8266_pwm + id: out4_pwm + pin: ${out4_pwm_pin} + frequency: ${pwm_frequency} + + - platform: esp8266_pwm + id: out5_pwm + pin: ${out5_pwm_pin} + frequency: ${pwm_frequency} + +########################################################################################## +# INTERNAL LIGHTS (do not expose to HA; use helper entities below) +########################################################################################## +light: + - platform: monochromatic + id: out1_light_raw + name: "${out1_name} (RAW)" + output: out1_pwm + internal: true + restore_mode: RESTORE_DEFAULT_OFF + + - platform: monochromatic + id: out2_light_raw + name: "${out2_name} (RAW)" + output: out2_pwm + internal: true + restore_mode: RESTORE_DEFAULT_OFF + + - platform: monochromatic + id: out3_light_raw + name: "${out3_name} (RAW)" + output: out3_pwm + internal: true + restore_mode: RESTORE_DEFAULT_OFF + + - platform: monochromatic + id: out4_light_raw + name: "${out4_name} (RAW)" + output: out4_pwm + internal: true + restore_mode: RESTORE_DEFAULT_OFF + + - platform: monochromatic + id: out5_light_raw + name: "${out5_name} (RAW)" + output: out5_pwm + internal: true + restore_mode: RESTORE_DEFAULT_OFF + +########################################################################################## +# GLOBALS (store "last non-zero" brightness per channel) +########################################################################################## +globals: + - id: out1_last_nonzero_pct + type: float + restore_value: true + initial_value: "100.0" + + - id: out2_last_nonzero_pct + type: float + restore_value: true + initial_value: "100.0" + + - id: out3_last_nonzero_pct + type: float + restore_value: true + initial_value: "100.0" + + - id: out4_last_nonzero_pct + type: float + restore_value: true + initial_value: "100.0" + + - id: out5_last_nonzero_pct + type: float + restore_value: true + initial_value: "100.0" + +########################################################################################## +# SCRIPTS (apply normalized brightness + proportional ramping) +########################################################################################## +script: + ############################################# + # OUT1 + ############################################# + - id: out1_apply_target + mode: restart + then: + - lambda: |- + const float slider_pct = id(out1_brightness_pct).state; + const float limit_pct = id(out1_max_limit_pct).state; + const float ramp_s = id(out1_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float slider_frac = slider_pct / 100.0f; + if (slider_frac < 0.0f) slider_frac = 0.0f; + if (slider_frac > 1.0f) slider_frac = 1.0f; + + float target = slider_frac * limit_frac; + + float current = 0.0f; + if (id(out1_light_raw).current_values.is_on()) { + current = id(out1_light_raw).current_values.get_brightness(); + } + + float delta = target - current; + if (delta < 0.0f) delta = -delta; + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (delta / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + if (target <= 0.0001f) { + auto call = id(out1_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + } else { + auto call = id(out1_light_raw).turn_on(); + call.set_brightness(target); + call.set_transition_length(trans_ms); + call.perform(); + } + + - id: out1_turn_off + mode: restart + then: + - lambda: |- + const float limit_pct = id(out1_max_limit_pct).state; + const float ramp_s = id(out1_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float current = 0.0f; + if (id(out1_light_raw).current_values.is_on()) { + current = id(out1_light_raw).current_values.get_brightness(); + } + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (current / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + auto call = id(out1_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + + ############################################# + # OUT2 + ############################################# + - id: out2_apply_target + mode: restart + then: + - lambda: |- + const float slider_pct = id(out2_brightness_pct).state; + const float limit_pct = id(out2_max_limit_pct).state; + const float ramp_s = id(out2_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float slider_frac = slider_pct / 100.0f; + if (slider_frac < 0.0f) slider_frac = 0.0f; + if (slider_frac > 1.0f) slider_frac = 1.0f; + + float target = slider_frac * limit_frac; + + float current = 0.0f; + if (id(out2_light_raw).current_values.is_on()) { + current = id(out2_light_raw).current_values.get_brightness(); + } + + float delta = target - current; + if (delta < 0.0f) delta = -delta; + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (delta / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + if (target <= 0.0001f) { + auto call = id(out2_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + } else { + auto call = id(out2_light_raw).turn_on(); + call.set_brightness(target); + call.set_transition_length(trans_ms); + call.perform(); + } + + - id: out2_turn_off + mode: restart + then: + - lambda: |- + const float limit_pct = id(out2_max_limit_pct).state; + const float ramp_s = id(out2_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float current = 0.0f; + if (id(out2_light_raw).current_values.is_on()) { + current = id(out2_light_raw).current_values.get_brightness(); + } + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (current / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + auto call = id(out2_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + + ############################################# + # OUT3 + ############################################# + - id: out3_apply_target + mode: restart + then: + - lambda: |- + const float slider_pct = id(out3_brightness_pct).state; + const float limit_pct = id(out3_max_limit_pct).state; + const float ramp_s = id(out3_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float slider_frac = slider_pct / 100.0f; + if (slider_frac < 0.0f) slider_frac = 0.0f; + if (slider_frac > 1.0f) slider_frac = 1.0f; + + float target = slider_frac * limit_frac; + + float current = 0.0f; + if (id(out3_light_raw).current_values.is_on()) { + current = id(out3_light_raw).current_values.get_brightness(); + } + + float delta = target - current; + if (delta < 0.0f) delta = -delta; + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (delta / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + if (target <= 0.0001f) { + auto call = id(out3_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + } else { + auto call = id(out3_light_raw).turn_on(); + call.set_brightness(target); + call.set_transition_length(trans_ms); + call.perform(); + } + + - id: out3_turn_off + mode: restart + then: + - lambda: |- + const float limit_pct = id(out3_max_limit_pct).state; + const float ramp_s = id(out3_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float current = 0.0f; + if (id(out3_light_raw).current_values.is_on()) { + current = id(out3_light_raw).current_values.get_brightness(); + } + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (current / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + auto call = id(out3_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + + ############################################# + # OUT4 + ############################################# + - id: out4_apply_target + mode: restart + then: + - lambda: |- + const float slider_pct = id(out4_brightness_pct).state; + const float limit_pct = id(out4_max_limit_pct).state; + const float ramp_s = id(out4_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float slider_frac = slider_pct / 100.0f; + if (slider_frac < 0.0f) slider_frac = 0.0f; + if (slider_frac > 1.0f) slider_frac = 1.0f; + + float target = slider_frac * limit_frac; + + float current = 0.0f; + if (id(out4_light_raw).current_values.is_on()) { + current = id(out4_light_raw).current_values.get_brightness(); + } + + float delta = target - current; + if (delta < 0.0f) delta = -delta; + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (delta / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + if (target <= 0.0001f) { + auto call = id(out4_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + } else { + auto call = id(out4_light_raw).turn_on(); + call.set_brightness(target); + call.set_transition_length(trans_ms); + call.perform(); + } + + - id: out4_turn_off + mode: restart + then: + - lambda: |- + const float limit_pct = id(out4_max_limit_pct).state; + const float ramp_s = id(out4_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float current = 0.0f; + if (id(out4_light_raw).current_values.is_on()) { + current = id(out4_light_raw).current_values.get_brightness(); + } + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (current / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + auto call = id(out4_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + + ############################################# + # OUT5 + ############################################# + - id: out5_apply_target + mode: restart + then: + - lambda: |- + const float slider_pct = id(out5_brightness_pct).state; + const float limit_pct = id(out5_max_limit_pct).state; + const float ramp_s = id(out5_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float slider_frac = slider_pct / 100.0f; + if (slider_frac < 0.0f) slider_frac = 0.0f; + if (slider_frac > 1.0f) slider_frac = 1.0f; + + float target = slider_frac * limit_frac; + + float current = 0.0f; + if (id(out5_light_raw).current_values.is_on()) { + current = id(out5_light_raw).current_values.get_brightness(); + } + + float delta = target - current; + if (delta < 0.0f) delta = -delta; + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (delta / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + if (target <= 0.0001f) { + auto call = id(out5_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + } else { + auto call = id(out5_light_raw).turn_on(); + call.set_brightness(target); + call.set_transition_length(trans_ms); + call.perform(); + } + + - id: out5_turn_off + mode: restart + then: + - lambda: |- + const float limit_pct = id(out5_max_limit_pct).state; + const float ramp_s = id(out5_ramp_s).state; + + float limit_frac = limit_pct / 100.0f; + if (limit_frac < 0.0f) limit_frac = 0.0f; + if (limit_frac > 1.0f) limit_frac = 1.0f; + + float current = 0.0f; + if (id(out5_light_raw).current_values.is_on()) { + current = id(out5_light_raw).current_values.get_brightness(); + } + + float full_scale = limit_frac; + if (current > full_scale) full_scale = current; + if (full_scale < 0.0001f) full_scale = 0.0001f; + + uint32_t trans_ms = (uint32_t) (ramp_s * 1000.0f * (current / full_scale)); + if (trans_ms > 600000) trans_ms = 600000; + + auto call = id(out5_light_raw).turn_off(); + call.set_transition_length(trans_ms); + call.perform(); + +########################################################################################## +# NUMBERS (brightness normalized to limit, plus per-channel ramp and hard limit) +########################################################################################## +number: + ############################################# + # OUT1 + ############################################# + - platform: template + id: out1_ramp_s + name: "${out1_name} Ramp" + icon: mdi:timer-outline + entity_category: config + unit_of_measurement: "s" + min_value: 0.0 + max_value: 30.0 + step: 0.1 + restore_value: true + initial_value: 2.0 + optimistic: true + set_action: + - script.execute: out1_apply_target + + - platform: template + id: out1_max_limit_pct + name: "${out1_name} Max Limit" + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - script.execute: out1_apply_target + + - platform: template + id: out1_brightness_pct + name: "${out1_name} Brightness" + icon: mdi:lightbulb-on-outline + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - lambda: |- + if (x > 0.0f) id(out1_last_nonzero_pct) = x; + - script.execute: out1_apply_target + + ############################################# + # OUT2 + ############################################# + - platform: template + id: out2_ramp_s + name: "${out2_name} Ramp" + icon: mdi:timer-outline + entity_category: config + unit_of_measurement: "s" + min_value: 0.0 + max_value: 30.0 + step: 0.1 + restore_value: true + initial_value: 2.0 + optimistic: true + set_action: + - script.execute: out2_apply_target + + - platform: template + id: out2_max_limit_pct + name: "${out2_name} Max Limit" + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - script.execute: out2_apply_target + + - platform: template + id: out2_brightness_pct + name: "${out2_name} Brightness" + icon: mdi:lightbulb-on-outline + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - lambda: |- + if (x > 0.0f) id(out2_last_nonzero_pct) = x; + - script.execute: out2_apply_target + + ############################################# + # OUT3 + ############################################# + - platform: template + id: out3_ramp_s + name: "${out3_name} Ramp" + icon: mdi:timer-outline + entity_category: config + unit_of_measurement: "s" + min_value: 0.0 + max_value: 30.0 + step: 0.1 + restore_value: true + initial_value: 2.0 + optimistic: true + set_action: + - script.execute: out3_apply_target + + - platform: template + id: out3_max_limit_pct + name: "${out3_name} Max Limit" + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - script.execute: out3_apply_target + + - platform: template + id: out3_brightness_pct + name: "${out3_name} Brightness" + icon: mdi:lightbulb-on-outline + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - lambda: |- + if (x > 0.0f) id(out3_last_nonzero_pct) = x; + - script.execute: out3_apply_target + + ############################################# + # OUT4 + ############################################# + - platform: template + id: out4_ramp_s + name: "${out4_name} Ramp" + icon: mdi:timer-outline + entity_category: config + unit_of_measurement: "s" + min_value: 0.0 + max_value: 30.0 + step: 0.1 + restore_value: true + initial_value: 2.0 + optimistic: true + set_action: + - script.execute: out4_apply_target + + - platform: template + id: out4_max_limit_pct + name: "${out4_name} Max Limit" + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - script.execute: out4_apply_target + + - platform: template + id: out4_brightness_pct + name: "${out4_name} Brightness" + icon: mdi:lightbulb-on-outline + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - lambda: |- + if (x > 0.0f) id(out4_last_nonzero_pct) = x; + - script.execute: out4_apply_target + + ############################################# + # OUT5 + ############################################# + - platform: template + id: out5_ramp_s + name: "${out5_name} Ramp" + icon: mdi:timer-outline + entity_category: config + unit_of_measurement: "s" + min_value: 0.0 + max_value: 30.0 + step: 0.1 + restore_value: true + initial_value: 2.0 + optimistic: true + set_action: + - script.execute: out5_apply_target + + - platform: template + id: out5_max_limit_pct + name: "${out5_name} Max Limit" + icon: mdi:brightness-percent + entity_category: config + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - script.execute: out5_apply_target + + - platform: template + id: out5_brightness_pct + name: "${out5_name} Brightness" + icon: mdi:lightbulb-on-outline + unit_of_measurement: "%" + min_value: 0 + max_value: 100 + step: 1 + restore_value: true + initial_value: 100 + optimistic: true + set_action: + - lambda: |- + if (x > 0.0f) id(out5_last_nonzero_pct) = x; + - script.execute: out5_apply_target + +########################################################################################## +# SWITCHES (On/Off that respects ramping; brightness slider remains unchanged when off) +########################################################################################## +switch: + - platform: template + id: out1_switch + name: ${out1_name} + icon: mdi:lightbulb + lambda: |- + return id(out1_light_raw).current_values.is_on(); + turn_on_action: + - if: + condition: + lambda: |- + return id(out1_brightness_pct).state <= 0.0f; + then: + - number.set: + id: out1_brightness_pct + value: !lambda "return id(out1_last_nonzero_pct);" + else: + - script.execute: out1_apply_target + turn_off_action: + - script.execute: out1_turn_off + + - platform: template + id: out2_switch + name: ${out2_name} + icon: mdi:lightbulb + lambda: |- + return id(out2_light_raw).current_values.is_on(); + turn_on_action: + - if: + condition: + lambda: |- + return id(out2_brightness_pct).state <= 0.0f; + then: + - number.set: + id: out2_brightness_pct + value: !lambda "return id(out2_last_nonzero_pct);" + else: + - script.execute: out2_apply_target + turn_off_action: + - script.execute: out2_turn_off + + - platform: template + id: out3_switch + name: ${out3_name} + icon: mdi:lightbulb + lambda: |- + return id(out3_light_raw).current_values.is_on(); + turn_on_action: + - if: + condition: + lambda: |- + return id(out3_brightness_pct).state <= 0.0f; + then: + - number.set: + id: out3_brightness_pct + value: !lambda "return id(out3_last_nonzero_pct);" + else: + - script.execute: out3_apply_target + turn_off_action: + - script.execute: out3_turn_off + + - platform: template + id: out4_switch + name: ${out4_name} + icon: mdi:lightbulb + lambda: |- + return id(out4_light_raw).current_values.is_on(); + turn_on_action: + - if: + condition: + lambda: |- + return id(out4_brightness_pct).state <= 0.0f; + then: + - number.set: + id: out4_brightness_pct + value: !lambda "return id(out4_last_nonzero_pct);" + else: + - script.execute: out4_apply_target + turn_off_action: + - script.execute: out4_turn_off + + - platform: template + id: out5_switch + name: ${out5_name} + icon: mdi:lightbulb + lambda: |- + return id(out5_light_raw).current_values.is_on(); + turn_on_action: + - if: + condition: + lambda: |- + return id(out5_brightness_pct).state <= 0.0f; + then: + - number.set: + id: out5_brightness_pct + value: !lambda "return id(out5_last_nonzero_pct);" + else: + - script.execute: out5_apply_target + turn_off_action: + - script.execute: out5_turn_off \ No newline at end of file diff --git a/esphome/esp-flysprayer1.yaml b/esphome/esp-flysprayer1.yaml index bbacdef..740c459 100644 --- a/esphome/esp-flysprayer1.yaml +++ b/esphome/esp-flysprayer1.yaml @@ -1,56 +1,84 @@ -########################################################################################## -########################################################################################## -# FLY SPRAYER - Sinilink XY-WFUSB (ESP8266/ESP8285) - ESPHome +#:########################################################################################:# +# TITLE: FLY SPRAYER - SINILINK XY-WFUSB +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-flysprayer1.yaml +#:########################################################################################:# +# VERSIONS: +# v1.1 2026-02-25 Updated yaml to zorruno layout V1.1 +# v1.0 2025-05-30 Initial Version +#:########################################################################################:# +# HARDWARE: +# - Sinilink XY-WFUSB (ESP8266/ESP8285) +# - Device link: https://www.aliexpress.com/item/1005005815472269.html +# - GPIO (from Tasmota template): +# - Button = GPIO4 +# - Relay = GPIO5 +# - Led_i = GPIO14 (Red LED, inverted) +# - LedLink= GPIO16 (Green LED, status) +#:########################################################################################:# +# OPERATION NOTES: +# - Purpose: +# - Pulse a MOSFET/relay with 5 V to trigger a fly spray can at selectable intervals. +# - The sprayer has its own timers, but it fires whenever it is started up; we utilize that. +# - Safety / Reliability: +# - Cooldown is enforced so it never double-fires too quickly (sprayer has some memory). +# - Interval can be randomized by +- a percentage (jitter) to avoid a perfectly regular pattern. +# - Scheduling: +# - Operation modes: Night only / Day only / 24 Hours / On / Off. +# - Night window spans across midnight (night_start_h -> night_end_h). +# - Indicators: +# - Red LED (GPIO14, inverted) pulses slowly when idle; goes solid ON during spray. +# - Green LED (GPIO16) is used as the ESPHome status LED. +# - Counters / UI: +# - Total spray count (resettable). +# - Daily spray count (resets at local midnight when time is valid). +# - Countdown until next spray (seconds + friendly text). +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, WiFi OK +# - Device continues operating locally (spray loop, cooldown, LEDs, counters). +# - You can still trigger "Spray Now" via the local button; HA UI will update when HA returns. # -# V1.0 2025-05-30 Initial Version +# b) MQTT OFFLINE (or broker unreachable) +# - No device-specific MQTT commands are used in this YAML (MQTT section is commented out), +# so behavior is unchanged. # -# Device: Sinilink XY-WFUSB module https://www.aliexpress.com/item/1005005815472269.html -# GPIO: Tasmota template: Button=GPIO4, Relay=GPIO5, Led_i=GPIO14, LedLink=GPIO16 -# -# Purpose: -# - Pulse a MOSFET/relay with 5 V to trigger a fly spray can at selectable intervals. -# - Sprayer has its own timers, but it fires whenever it is started up, which we utilise here. -# - Enforce a cooldown so it never double-fires too quickly (Sprayer has some memory) -# - Operation window select: Night only / Day only / 24 Hours / On / Off. -# - Randomize each interval by +- a percentage to avoid a perfectly regular pattern. -# - Red LED (GPIO14, inverted) pulses slowly when idle; goes solid ON during spray. -# - Green LED (GPIO16) as standard ESPHome status LED. -# - Has a resettable total spray count, and a daily spray count -# - has a countdown until next spray -# -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network OFFLINE +# - Accurate time IS needed for Night/Day modes and daily counter reset (SNTP required). +# - If time is invalid, this YAML is conservative for Night/Day modes (skips those cycles). +# 24 Hours / On still allows operation, but daily reset will not occur until time is valid. +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-flysprayer1" friendly_name: "Fly Sprayer" - description_comment: "Control of generic automatic fly sprayer on a configurable interval" - device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Control of generic automatic fly sprayer on a configurable interval (Layout V1.1)" + device_area: "Lounge" # Project Naming - project_name: "Generic ESP8266.XY-WFUSB" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Generic ESP8266.XY-WFUSB" + project_version: "v1.1" # Passwords & Secrets - api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-flysprayer1_ip - #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic - #mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - - # MQTT Controls - #mqtt_device_name: "lounge-flyspray" - #mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA - #mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA + log_level: "INFO" + update_interval: "60s" # Hardware pins (XY-WFUSB per your Tasmota screen) pin_button: 4 # GPIO4 -> momentary button (optional local trigger) @@ -61,19 +89,19 @@ substitutions: # Timing configuration relay_activation_ms: 5000 # Relay Activation Time (ms). Nominally 5 seconds. - relay_cooldown_ms: 30000 # Relay Cool Down Period (ms). Minimum gap between sprays. + relay_cooldown_ms: 30000 # Relay Cool Down Period (ms). Minimum gap between sprays. # Operation windows (local 24h). Night is from night_start_h to night_end_h across midnight. - night_start_h: 21 # 21:00 (9pm) - night_end_h: 7 # 07:00 (7am) + night_start_h: 21 # 21:00 (9pm) + night_end_h: 7 # 07:00 (7am) # Interval jitter (+- percent of selected interval) - interval_jitter_pct: 10 # Default +-10% + interval_jitter_pct: 10 # Default +-10% -######################################################################################### +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -82,6 +110,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -96,21 +125,19 @@ packages: vars: local_device_name: "${device_name}" - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome CORE CONFIGURATION +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -142,105 +169,91 @@ esphome: id(next_spray_in_text).publish_state("Ready"); - script.execute: spray_loop -########################################################################################## +#:########################################################################################:# # ESP PLATFORM AND FRAMEWORK # https://esphome.io/components/esp8266.html -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp8266: board: esp8285 - early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout preferences: flash_write_interval: 20s -########################################################################################## -# GLOBAL VARIABLES +#:########################################################################################:# +# GLOBALS # https://esphome.io/components/globals.html -########################################################################################## +#:########################################################################################:# globals: - # millisecond tick when we last fired successfully + # millisecond tick when we last fired successfully - id: last_fire_ms type: uint32_t restore_value: no - initial_value: '0' + initial_value: "0" - id: last_wait_ms type: uint32_t restore_value: no - initial_value: '60000' + initial_value: "60000" - id: window_allowed type: bool restore_value: no - initial_value: 'false' + initial_value: "false" # absolute millis() when the next spray countdown ends - id: next_target_ms type: uint32_t restore_value: no - initial_value: '0' + initial_value: "0" # total successful sprays (persists across reboots) - id: spray_count type: uint32_t restore_value: yes - initial_value: '0' + initial_value: "0" # total sprays since local midnight - id: spray_count_today type: uint32_t restore_value: yes - initial_value: '0' + initial_value: "0" # day-of-month snapshot to detect midnight rollover - id: last_day type: int restore_value: yes - initial_value: '-1' + initial_value: "-1" -########################################################################################## -# LOGGER COMPONENT +#:########################################################################################:# +# LOGGER # https://esphome.io/components/logger.html -# Logs all log messages through the serial port and through MQTT topics. -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + #baud_rate: 0 -########################################################################################## -# MQTT COMMANDS -# This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## -#mqtt: -# on_message: -# # Light control to ramp up -# - topic: "${mqtt_local_command_topic}/light/set" -# payload: "${mqtt_local_device_command_ON}" -# then: -# - switch.turn_on: mosfet_ramp_switch -# # Light control to ramp down -# - topic: "${mqtt_local_command_topic}/light/set" -# payload: "${mqtt_local_device_command_OFF}" -# then: -# - switch.turn_off: mosfet_ramp_switch - -######################################################################################### +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# status_led: pin: number: ${pin_led_green} inverted: false -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# MQTT COMMANDS +# (No device-specific MQTT triggers are enabled in this file currently) +#:########################################################################################:# +#mqtt: +# on_message: + +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: - platform: gpio id: relay_out @@ -264,10 +277,10 @@ switch: brightness: 50% effect: red_idle_pulse -################################################################################################# -# BUTTON COMPONENT +#:########################################################################################:# +# BUTTON # https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# button: - platform: template id: spray_now @@ -276,6 +289,7 @@ button: on_press: then: - script.execute: try_spray_now + - platform: template id: reset_spray_count name: "Reset Spray Count" @@ -286,10 +300,10 @@ button: id(spray_count) = 0; id(spray_count_sensor).publish_state(0); -######################################################################################### -# SELECT COMPONENT +#:########################################################################################:# +# SELECT # https://esphome.io/components/select/index.html -######################################################################################### +#:########################################################################################:# select: - platform: template id: spray_interval @@ -333,12 +347,12 @@ select: args: [ 'id(spray_operation).current_option().c_str()' ] - script.execute: spray_loop -########################################################################################## +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - # Front panel/local button (GPIO4) - single press triggers a Spray Now (honors cooldown) + # Front panel/local button (GPIO4) - triggers Spray Now (honors cooldown) - platform: gpio id: btn_local pin: @@ -352,10 +366,10 @@ binary_sensor: then: - button.press: spray_now -########################################################################################## -# SENSOR COMPONENT +#:########################################################################################:# +# SENSORS # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: # Next spray remaining time in seconds (updated by the scheduler) - platform: template @@ -364,7 +378,6 @@ sensor: icon: mdi:timer-sand unit_of_measurement: "s" accuracy_decimals: 0 - #entity_category: diagnostic update_interval: never # Total sprays counter (persisted; updated on each spray and when reset) @@ -379,7 +392,7 @@ sensor: filters: - round: 0 - # Sprays since local midnight (auto-resets at midnight) + # Sprays since local midnight (auto-resets at midnight when time is valid) - platform: template id: spray_count_today_sensor name: "${friendly_name} Spray Count Today" @@ -391,36 +404,32 @@ sensor: filters: - round: 0 -########################################################################################## -# TEXT SENSOR COMPONENT +#:########################################################################################:# +# TEXT SENSORS # https://esphome.io/components/text_sensor/ -########################################################################################## +#:########################################################################################:# text_sensor: - platform: template id: next_spray_in_text name: "Next Spray In" icon: mdi:clock-outline - #entity_category: diagnostic update_interval: never -########################################################################################## -# OUTPUT COMPONENT -# https://esphome.io/components/light/index.html -########################################################################################## -# An OUTPUT can be binary (0,1) or float, which is any value between 0 and 1. -# PWM Outputs such as "ledc" are float. https://esphome.io/components/output/ledc.html -########################################################################################## +#:########################################################################################:# +# OUTPUT +# https://esphome.io/components/output/ +#:########################################################################################:# output: - platform: esp8266_pwm id: red_led_pwm pin: number: ${pin_led_red} - inverted: true # Tasmota showed Led_i on GPIO14 + inverted: true -########################################################################################## -# LIGHT COMPONENT +#:########################################################################################:# +# LIGHT # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: monochromatic id: red_led @@ -435,18 +444,10 @@ light: transition_length: 1500ms update_interval: 1500ms -########################################################################################## -# NUMBER COMPONENT -# https://esphome.io/components/number/ -########################################################################################## - -########################################################################################## -# SCRIPT COMPONENT +#:########################################################################################:# +# SCRIPTS # https://esphome.io/components/script.html -# Scripts can be executed nearly anywhere in your device configuration with a single call. -########################################################################################## -# SCRIPTS - main loop, cooldown-safe trigger, and actual spray action -########################################################################################## +#:########################################################################################:# script: # Cooldown-checked "Spray Now" - id: try_spray_now @@ -463,7 +464,7 @@ script: id(last_fire_ms) = millis(); - script.execute: do_spray else: - - logger.log: "Spray request ignored: Fired during cool down period." + - logger.log: "Spray request ignored: fired during cool down period." # Actual relay action for the configured activation time - id: do_spray @@ -473,7 +474,7 @@ script: id(spray_count)++; id(spray_count_sensor).publish_state((float) id(spray_count)); id(spray_count_today)++; - id(spray_count_today_sensor).publish_state(id(spray_count_today)); // publish as int + id(spray_count_today_sensor).publish_state(id(spray_count_today)); - switch.turn_on: relay_out - light.turn_on: id: red_led @@ -486,7 +487,7 @@ script: brightness: 50% effect: red_idle_pulse - # Scheduler loop - waits a randomized interval, updates countdown text, checks window, then tries to spray + # Scheduler loop - waits a randomized interval, updates countdown, checks window, then tries to spray - id: spray_loop mode: restart then: @@ -510,8 +511,9 @@ script: const uint32_t pct = ${interval_jitter_pct}; const uint32_t jitter = (base_sec * pct) / 100; const uint32_t span = (jitter * 2u) + 1u; - const uint32_t rnd = random_uint32() % span; // 0..(2*jitter) - const int32_t delta = (int32_t) rnd - (int32_t) jitter; // -jitter..+jitter + const uint32_t rnd = random_uint32() % span; // 0..(2*jitter) + const int32_t delta = (int32_t) rnd - (int32_t) jitter; // -jitter..+jitter + int32_t next_sec = (int32_t) base_sec + delta; if (next_sec < 1) next_sec = 1; @@ -521,11 +523,11 @@ script: id(last_wait_ms) = (uint32_t) next_sec * 1000u; id(next_target_ms) = millis() + id(last_wait_ms); - // Publish an initial countdown snapshot (minutes only for text; seconds kept for numeric sensor) + // Publish an initial countdown snapshot uint32_t rem_ms = id(next_target_ms) > millis() ? (id(next_target_ms) - millis()) : 0; - uint32_t sec = (rem_ms + 999u) / 1000u; // seconds, rounded up + uint32_t sec = (rem_ms + 999u) / 1000u; // seconds, rounded up id(next_spray_seconds).publish_state(sec); - uint32_t min = (sec + 59u) / 60u; // minutes, ceiling + uint32_t min = (sec + 59u) / 60u; // minutes, ceiling char buf[16]; snprintf(buf, sizeof(buf), "%u min", (unsigned) min); std::string countdown_txt(buf); @@ -562,7 +564,7 @@ script: bool is_night; if (nh > eh) is_night = (hour >= nh) || (hour < eh); else is_night = (hour >= nh) && (hour < eh); - in_window = !is_night; // day is the opposite of night window + in_window = !is_night; } if (!in_window) { snprintf(await_buf, sizeof(await_buf), "%02d:00", ${night_end_h}); @@ -581,14 +583,14 @@ script: then: - lambda: |- uint32_t rem_ms = id(next_target_ms) > millis() ? (id(next_target_ms) - millis()) : 0; - uint32_t sec = (rem_ms + 999u) / 1000u; // seconds, rounded up + uint32_t sec = (rem_ms + 999u) / 1000u; id(next_spray_seconds).publish_state(sec); - uint32_t min = (sec + 59u) / 60u; // minutes, ceiling + + uint32_t min = (sec + 59u) / 60u; char buf[16]; snprintf(buf, sizeof(buf), "%u min", (unsigned) min); std::string countdown_txt(buf); - // Override text for specific modes auto op = id(spray_operation).current_option(); char await_buf[16]; @@ -637,10 +639,8 @@ script: auto n = id(sntp_time).now(); int d = n.day_of_month; if (id(last_day) == -1) { - // First valid time after boot: initialise without reset - id(last_day) = d; + id(last_day) = d; // first valid time after boot } else if (id(last_day) != d) { - // New day -> reset today's counter id(last_day) = d; id(spray_count_today) = 0; id(spray_count_today_sensor).publish_state(0); @@ -659,16 +659,15 @@ script: allowed = true; } else { if (!id(sntp_time).now().is_valid()) { - allowed = false; // no time yet; be conservative + allowed = false; // no time yet; be conservative } else { auto n = id(sntp_time).now(); - int hour = n.hour; // 0..23 + int hour = n.hour; int nh = ${night_start_h}; int eh = ${night_end_h}; bool is_night; if (nh > eh) { - // window crosses midnight (e.g., 21:00..07:00) is_night = (hour >= nh) || (hour < eh); } else { is_night = (hour >= nh) && (hour < eh); @@ -683,10 +682,9 @@ script: else ESP_LOGI("spray", "Window blocked: skipping this cycle."); id(window_allowed) = allowed; + - if: condition: lambda: "return id(window_allowed);" then: - - script.execute: try_spray_now - - + - script.execute: try_spray_now \ No newline at end of file diff --git a/esphome/esp-garagedbcontrols.yaml b/esphome/esp-garagedbcontrols.yaml index 6d3d52c..11946dd 100644 --- a/esphome/esp-garagedbcontrols.yaml +++ b/esphome/esp-garagedbcontrols.yaml @@ -1,65 +1,109 @@ -############################################# -############################################# -# GARAGE DB CONTROLS -# Controlled by a Sonoff 4Ch R2 -# https://github.com/jvyoralek/homeassistant-config/blob/master/esphome/sonoff-4ch.yaml +#:########################################################################################:# +# TITLE: GARAGE DB CONTROLS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garagedbcontrols.yaml +#:########################################################################################:# +# VERSIONS: +# v1.1 2026-02-25 Updated yaml to zorruno layout V1.1 +# v1.0 2025-10-23 Initial Version +#:########################################################################################:# +# HARDWARE: +# - Sonoff 4CH R2 (ESP8266 / ESP8285) +# - Reference YAML: https://github.com/jvyoralek/homeassistant-config/blob/master/esphome/sonoff-4ch.yaml +# - Relays (4CH R2): GPIO12, GPIO5, GPIO4, GPIO15 +# - Buttons (4CH R2): GPIO0, GPIO9, GPIO10, GPIO14 +# - Status LED: GPIO13 (active-low) +# - Extras (as used here): +# - EV pulse input: GPIO2 (must be HIGH at boot; INPUT_PULLUP used) +# - DHT sensor: GPIO3 (note: UART RX pin on ESP8266; ensure logger baud_rate=0) +#:########################################################################################:# +# OPERATION NOTES: +# - Provides 4 relay outputs with matching local buttons. +# - Relay restore modes are set per-output (some default ON, some default OFF). +# - Includes EV charger energy monitoring via pulse input (2.0 Wh per pulse): +# - "Power Now" derived from pulse rate (pulse_meter). +# - Lifetime kWh total from pulse total (pulse_meter total). +# - 1-hour sliding average for power. +# - Daily kWh using total_daily_energy, with "Energy Yesterday" snap at 23:59 when time is valid. +# - Publishes a Tasmota-like MQTT telemetry message once per 60s with windowed Wh delta. +#:########################################################################################:# +# MQTT COMMANDS: +# - Publishes windowed EV Wh count every 60s: +# Topic: stat/tasmo-s4chan-7594-garage-1/EnergyMeterCount +# Payload example: {"EVChargerWhCount":123.456} +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, WiFi OK +# - Device continues relay/button operation and continues pulse metering locally. +# - MQTT telemetry publishing depends on MQTT broker availability. # -# V1.0 2025-10-23 Initial Version +# b) MQTT OFFLINE (or broker unreachable) +# - Relays/buttons still operate locally and via HA API (if HA is available). +# - MQTT telemetry messages will not be delivered until broker returns. # -########################################################################################## -########################################################################################## +# c) Entire WiFi/Network OFFLINE +# - Accurate time IS needed for the "Energy Yesterday" snapshot at 23:59 (SNTP required). +# - Power/energy totals still accumulate, but "Energy Yesterday" will not update without valid time. +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Custom Naming + # Device Naming device_name: "esp-garagedbcontrols" friendly_name: "Garage DB Control" - description_comment: "Garage DB Power, EV Power & Mesure, Lighting :: Sonoff 4ch R2" - device_area: "Garage" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Garage DB Power, EV Power & Measure, Lighting :: Sonoff 4ch R2 (Layout V1.1)" + device_area: "Garage" + + # Project Naming + project_name: "Sonoff Technologies.Sonoff 4Ch R2" + project_version: "v1.1" + + # Passwords & Secrets + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-garagedbcontrols_ip - #mqtt_device_name_1: "garage-dbcontrols" + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # General Settings + log_level: "ERROR" + update_interval: "60s" # I/O Naming switch_1_name: "Small EV Charger" button_1_name: "Button 1" - relay_1_icon: "mdi:power-socket-au" + relay_1_icon: "mdi:power-socket-au" + switch_2_name: "Garage West Power" button_2_name: "Button 2" - relay_2_icon: "mdi:power-socket-au" + relay_2_icon: "mdi:power-socket-au" + switch_3_name: "Spare 3" button_3_name: "Button 3" - relay_3_icon: "mdi:toggle-switch" + relay_3_icon: "mdi:toggle-switch" + switch_4_name: "Spare 4" button_4_name: "Button 4" - relay_4_icon: "mdi:toggle-switch" + relay_4_icon: "mdi:toggle-switch" - # Project Naming - project_name: "Sonoff Technologies.Sonoff 4Ch R2" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + # EV pulse settings + ev_pulse_wh: "2.0" # Wh per pulse + ev_pulse_filter: "10ms" # debounce pulses + ev_pulse_timeout: "2min" # set power to 0W if no pulses + ev_tasmota_tele_topic: "stat/tasmo-s4chan-7594-garage-1/EnergyMeterCount" - # MQTT Controls - #mqtt_command_main_topic: !secret mqtt_command_main_topic - #mqtt_status_main_topic: !secret mqtt_status_main_topic - #mqtt_command_topic_1: "${mqtt_command_main_topic}/${mqtt_device_name_1}" - #mqtt_status_topic_1: "${mqtt_status_main_topic}/${mqtt_device_name_1}" - #mqtt_command_ON: "ON" - #mqtt_command_OFF: "OFF" - - # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) - api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass - - # General Settings - log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -68,6 +112,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -81,27 +126,28 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" + project: + name: "${project_name}" + version: "${project_version}" # On boot, initialise the window start so the first publish isn't huge on_boot: priority: -10 @@ -113,123 +159,149 @@ esphome: id(ev_last_total_kwh) = 0.0f; } -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp8285 - #board: esp01_1m - restore_from_flash: True # restore some values on reboot + restore_from_flash: true preferences: flash_write_interval: 5min mdns: - disabled: False + disabled: false -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# STATUS LED +# https://esphome.io/components/status_led.html +#:########################################################################################:# +status_led: + pin: + number: GPIO13 + inverted: yes + +#:########################################################################################:# +# GLOBALS +# https://esphome.io/components/globals.html +#:########################################################################################:# +globals: + # Store the last published total (kWh) for 60s delta windowing + - id: ev_last_total_kwh + type: float + restore_value: true + initial_value: "0.0" + + - id: ev_energy_yesterday_kwh + type: float + restore_value: true + initial_value: "0.0" + + # Track last day-of-year we snapped so it only happens once per day + - id: ev_last_snapshot_doy + type: int + restore_value: no + initial_value: "-1" + +#:########################################################################################:# +# SWITCHES # https://esphome.io/components/switch/ -########################################################################################## -# Sonoff 4Ch R2 Relays are GPIO12,05,04,15 -############################################# +#:########################################################################################:# switch: + # Sonoff 4Ch R2 Relays are GPIO12, GPIO5, GPIO4, GPIO15 - platform: gpio id: relay1 name: "${switch_1_name}" restore_mode: RESTORE_DEFAULT_OFF pin: GPIO12 - icon: "${relay_1_icon}" + icon: "${relay_1_icon}" + - platform: gpio id: relay2 name: "${switch_2_name}" - restore_mode: RESTORE_DEFAULT_ON + restore_mode: RESTORE_DEFAULT_ON pin: GPIO5 - icon: "${relay_2_icon}" + icon: "${relay_2_icon}" + - platform: gpio - id: relay3 + id: relay3 name: "${switch_3_name}" - restore_mode: RESTORE_DEFAULT_ON + restore_mode: RESTORE_DEFAULT_ON pin: GPIO4 - icon: "${relay_3_icon}" + icon: "${relay_3_icon}" + - platform: gpio id: relay4 name: "${switch_4_name}" restore_mode: RESTORE_DEFAULT_OFF pin: GPIO15 - icon: "${relay_4_icon}" + icon: "${relay_4_icon}" -########################################################################################## +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -########################################################################################## -# Sonoff 4Ch R2 Buttons are GPIO00,09,10,14 -############################################# +#:########################################################################################:# binary_sensor: + # Sonoff 4Ch R2 Buttons are GPIO0, GPIO9, GPIO10, GPIO14 - platform: gpio id: button1 name: "${button_1_name}" pin: number: GPIO0 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay1 + - switch.toggle: relay1 + - platform: gpio id: button2 name: "${button_2_name}" pin: number: GPIO9 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay2 + - switch.toggle: relay2 + - platform: gpio id: button3 name: "${button_3_name}" pin: number: GPIO10 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay3 + - switch.toggle: relay3 + - platform: gpio id: button4 name: "${button_4_name}" pin: number: GPIO14 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay4 + - switch.toggle: relay4 -########################################################################################## -# STATUS LED -# https://esphome.io/components/status_led.html -########################################################################################## -status_led: - pin: - number: GPIO13 - inverted: yes - -########################################################################################## -# EV CHARGER ENERGY (PULSE INPUT ON GPIO2, 2.0 Wh PER PULSE) -# - Uses pulse_meter for stable pulse rate and total count -# - Derives instantaneous Power (W), 1h average Power, Today kWh, and lifetime kWh -########################################################################################## +#:########################################################################################:# +# SENSORS +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - # Pulse rate -> Power Now (W) + ######################################################################################## + # EV CHARGER ENERGY (PULSE INPUT ON GPIO2, 2.0 Wh PER PULSE) + # - Uses pulse_meter for stable pulse rate and total count + # - Derives Power (W), 1h average Power, Today kWh, and lifetime kWh + ######################################################################################## - platform: pulse_meter id: ev_pulse_pm pin: @@ -237,17 +309,16 @@ sensor: mode: INPUT_PULLUP # GPIO2 must be HIGH at boot inverted: false name: "${switch_1_name} Power Now" - # pulse_meter reports pulses/min; each pulse = 2 Wh => W = pulses/min * 2 * 60 = x120 unit_of_measurement: "W" device_class: power state_class: measurement accuracy_decimals: 0 - internal_filter: 10ms # debounce pulses - timeout: 2min # set to 0 W if no pulses for 2 minutes + internal_filter: ${ev_pulse_filter} + timeout: ${ev_pulse_timeout} + # pulse_meter reports pulses/min; each pulse = 2 Wh => W = pulses/min * 2 * 60 = x120 filters: - - multiply: 120.0 # convert pulses/min to Watts + - multiply: 120.0 - # Lifetime energy total (monotonic) total: id: ev_energy_total_kwh name: "${switch_1_name} Energy Cumulative Total" @@ -256,9 +327,9 @@ sensor: state_class: total_increasing accuracy_decimals: 1 filters: - - multiply: 0.002 # kWh per pulse (2.0 Wh = 0.002 kWh) + # kWh per pulse (2.0 Wh = 0.002 kWh) + - multiply: 0.002 - # 1-hour sliding average of power (W) - platform: template id: ev_power_avg_1h name: "${switch_1_name} Power (1h avg)" @@ -274,7 +345,6 @@ sensor: window_size: 360 # 10 s * 360 ≈ 1 hour send_every: 6 # update HA once per minute - # Today's energy (kWh), integrates "Power Now" and resets at local midnight - platform: total_daily_energy id: ev_energy_today_kwh name: "${switch_1_name} Energy Today" @@ -284,9 +354,9 @@ sensor: state_class: total accuracy_decimals: 1 filters: - - multiply: 0.001 # total_daily_energy outputs Wh; convert to kWh + # total_daily_energy outputs Wh; convert to kWh + - multiply: 0.001 -# Expose "Energy Yesterday" as a normal sensor - platform: template id: ev_energy_yesterday_sensor name: "${switch_1_name} Energy Yesterday" @@ -296,85 +366,59 @@ sensor: accuracy_decimals: 1 update_interval: 30s lambda: |- - return id(ev_energy_yesterday_kwh); + return id(ev_energy_yesterday_kwh); -########################################################################################## -# DHT SENSOR -# https://esphome.io/components/sensor/dht/ -########################################################################################## -#sensor: + ######################################################################################## + # DHT SENSOR (GPIO3) + # NOTE: GPIO3 is UART RX on ESP8266; logger baud_rate=0 avoids conflicts. + ######################################################################################## - platform: dht pin: GPIO3 + update_interval: 60s temperature: name: "${friendly_name} Temperature" humidity: name: "${friendly_name} Humidity" - update_interval: 60s -########################################################################################## -# Tasmota-like teleperiod publish of windowed Wh count every 60 s -########################################################################################## -# Store the last published total (kWh) -globals: - - id: ev_last_total_kwh - type: float - restore_value: true - initial_value: "0.0" - - id: ev_energy_yesterday_kwh - type: float - restore_value: true - initial_value: "0.0" - # Track last day-of-year we snapped so it only happens once per day - - id: ev_last_snapshot_doy - type: int - restore_value: no - initial_value: '-1' - -# Teleperiod = 60s: publish JSON and advance the window +#:########################################################################################:# +# INTERVALS +# https://esphome.io/components/interval.html +#:########################################################################################:# interval: + # Teleperiod = 60s: publish JSON and advance the window - interval: 60s then: - mqtt.publish: - topic: "stat/tasmo-s4chan-7594-garage-1/EnergyMeterCount" + topic: "${ev_tasmota_tele_topic}" qos: 0 retain: false payload: !lambda |- - // Current lifetime kWh from pulse_meter "total" float current = id(ev_energy_total_kwh).state; if (!isfinite(current)) current = id(ev_last_total_kwh); - // Delta since last publish (kWh -> Wh) float delta_kwh = current - id(ev_last_total_kwh); if (delta_kwh < 0.0f || !isfinite(delta_kwh)) delta_kwh = 0.0f; float delta_wh = delta_kwh * 1000.0f; - // Advance the window (equivalent of "counter1 0") id(ev_last_total_kwh) = current; - // Build JSON payload char buf[64]; snprintf(buf, sizeof(buf), "{\"EVChargerWhCount\":%.3f}", delta_wh); return std::string(buf); -# YESTERDAY ENERGY (device-side snapshot of today's total at end-of-day) -# Uses existing time id(sntp_time) from sntp_common.yaml + # YESTERDAY ENERGY snapshot (once per day at 23:59, when time is valid) - interval: 60s then: - lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return; - // Snapshot once per day at 23:59 (minute precision) if (now.hour != 23 || now.minute != 59) return; - // Prevent repeats if this runs multiple times during 23:59 if (id(ev_last_snapshot_doy) == now.day_of_year) return; if (isfinite(id(ev_energy_today_kwh).state)) { id(ev_energy_yesterday_kwh) = id(ev_energy_today_kwh).state; } - id(ev_last_snapshot_doy) = now.day_of_year; - - - + id(ev_last_snapshot_doy) = now.day_of_year; \ No newline at end of file diff --git a/esphome/esp-lounge6chdimmer.yaml b/esphome/esp-lounge6chdimmer.yaml index 8aeca4e..b692a9f 100644 --- a/esphome/esp-lounge6chdimmer.yaml +++ b/esphome/esp-lounge6chdimmer.yaml @@ -1,69 +1,75 @@ -########################################################################################## -########################################################################################## -# 4 Channel DMX Mains Dimmer -# This is using an esp8366 (D1 Mini) sending DMX512 Serial to a trio of 2 channel -# mains lighting contollers (1.2A/Channel) -# -# Contoller: https://www.aliexpress.com/item/32838426377.html -# RS-485 TTL converter: https://www.aliexpress.com/item/1005005737922222.html -# +#:########################################################################################:# +# TITLE: 6 CHANNEL LOUNGE DMX MAINS DIMMER +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: # V1.1 2025-09-13 Extended to 3 modules and installed # V1.0 2025-09-06 First Rev (only tested one module, 2 channels at this stage, and incandescent) -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - ESP8266 D1 Mini Pro +# - 3 x 2-channel DMX mains dimmer modules (1.2 A per channel) +# Contoller: https://www.aliexpress.com/item/32838426377.html +# - RS-485 TTL converter (MAX485 style) +# RS-485 TTL converter: https://www.aliexpress.com/item/1005005737922222.html # -# NOTES -# ------ -# - Trialling with an incandescent bulb, 10% writes 26. Max value is 255 so this is 10% -# - With an incandescent, I can't see any light output below about 15% -# - Using GPIO2 as the UART TX on an ESP8266 is handy, as the onboard LED flashes with TX -# - The dimmer needs to be set to DMX mode, and given an ID of 1-999 (not standalone or dynamic) -# - there is no reason you can't run many dimmers off one ESP (limit may be in data speed lags?) -# - The dimmer is pretty smooth, and it remembers values even if no data being transmitted. -# - On my system, I am restoring all channels to ON. Power is controlled by a (smart) wallswitch -# so if all networks fail, switching the switch will power these on and restore to full brightness. +# MAX485 Module (You could also use a MAX3485 which is 3.3 V) +# - MAX485 VCC -> ESP +5V +# - MAX485 GND -> ESP GND +# - MAX485 DE -> ESP +5V +# - MAX485 RE -> Pullup so can leave unconnected (or +5V) or a designated enable_pin +# - MAX485 DI -> ESP GPIO2 (ESP8266) or GPIO5 (ESP32) +# - MAX485 A -> XLR 3 (DMX +) +# - MAX485 B -> XLR 2 (DMX -) +# - MAX485 GND -> XLR 1 (DMX GND) +#:########################################################################################:# +# OPERATION NOTES: +# - ESP8266 transmits DMX512 over UART (one-way TX only) via RS-485 adaptor +# - Dimmer modules must be set to DMX mode and assigned a fixed ID (1-999) +# - Incandescent trial notes: +# - 10% writes ~26 (max 255) +# - Very low levels may not visibly output below ~15% +# - Using GPIO2 as UART TX on ESP8266 is handy, as the onboard LED flashes with TX +# - Dimmers are smooth and remember values even if DMX data stops transmitting +# - This design assumes mains power is controlled by a smart wall switch: +# - If networks fail, toggling power restores the dimmer outputs (and this YAML restores channels to ON) # # System Settings on Dimmer: (onboard buttons M and < held for 2 secs) -# ------ -# - Set "1 Channel" (d-1) and both channels will output the same levels. Or "2 Channel" (d-2) -# - Set reverse phase dimming/trailing edge (C-R) or Forward/Leading Edge (C-F) -# - Set minimum brightness on the dimmer, from b01-b40. Min is then 5% if b01 -# - Set the 3x 8 Segment display to automatically turn off (Bon/BoF) after a period -# - pull both DE & RE high on the 485 converter to ensure data enabled (or wire to enable_pin) -# -# MAX485 Module (You could also use a MAX3485 which is 3.3V) -# ------ -# MAX485 VCC -> ESP +5V -# MAX485 GND -> ESP GND -# MAX485 DE -> ESP +5V -# MAX485 RE -> Has a pullup so can leave unconnected, (or +5V)or an designated enable_pin -# MAX485 DI -> ESP32 GPIO5 or ESP8266 GPIO2 -# MAX485 A -> XLR 3 (DMX +) -# MAX485 B -> XLR 2 (DMX -) -# MAX485 GND -> XLR 1 (DMX GND) +# - Set "1 Channel" (d-1) and both channels output the same level, or "2 Channel" (d-2) +# - Set reverse phase dimming / trailing edge (C-R) or forward / leading edge (C-F) +# - Set minimum brightness on the dimmer, from b01-b40 (b01 gives ~5% min) +# - Set the 3x 8 segment display to automatically turn off (Bon/BoF) +# - Pull both DE and RE high on the 485 converter to ensure data enabled (or wire enable_pin) # # Other useful references -# ------ -# - Arduino DMX Controller https://www.youtube.com/watch?v=4PjBBBQB2m4 -# - ESP32 DMX Contoller with ESPixelstick (errors in his wiring diagram) -# https://www.youtube.com/watch?v=GWZ63vsKzT8 -# - ESPHome DMX512 Custom component used here: https://github.com/andyboeh/esphome-dmx512 -# Includes good examples if you are expanding -########################################################################################## -########################################################################################## +# - Arduino DMX Controller: https://www.youtube.com/watch?v=4PjBBBQB2m4 +# - ESP32 DMX Contoller with ESPixelstick (errors in his wiring diagram): +# https://www.youtube.com/watch?v=GWZ63vsKzT8 +# - ESPHome DMX512 Custom component used here: +# https://github.com/andyboeh/esphome-dmx512 +#:########################################################################################:# +# MQTT COMMANDS: +# +#:########################################################################################:# +# OFFLINE NOTES: +# - If Home Assistant is offline, lights can still be controlled locally (device continues DMX output) +# - If Wi-Fi is offline, wall switch power-cycling restores dimmer module output state (modules remember) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: - # Device Naming + # Device Naming device_name: "esp-lounge6chdimmer" friendly_name: "6 Channel Lounge Dimmer" - description_comment: "Lounge 6 Channel Mains Lighting Dimmer (3 x 2 channel modules) controlled using DMX512 protocol with a D1 Mini Pro" - device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Lounge 6 Channel Mains Lighting Dimmer (3 x 2 channel modules) controlled using DMX512 protocol with a D1 Mini Pro (Layout V1.0)" + device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Generic ESP8266.D1 Mini" # Project Details + project_name: "Generic ESP8266.D1 Mini" # Project Details project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version # Passwords & Secrets @@ -104,12 +110,12 @@ substitutions: gamma_output_5: "2.2" gamma_output_6: "2.2" -######################################################################################### + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## # Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -132,23 +138,24 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_diag_sensors.yaml - diag_more: !include common/include_more_diag_sensors.yaml - diag_debug: !include common/include_debug_diag_sensors.yaml + diag_basic: !include common/include_basic_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 -######################################################################################### -# ESPHome + +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -######################################################################################### +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -168,113 +175,126 @@ esphome: id(dmx_ch5_sensor).publish_state(0); id(dmx_ch6_sensor).publish_state(0); -######################################################################################### -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -######################################################################################### + +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +#:########################################################################################:# esp8266: board: d1_mini_pro - #early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. + #early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to true. board_flash_mode: dout # Default is dout restore_from_flash: true # restore some values on reboot + +#:########################################################################################:# +# MDNS: +# https://esphome.io/components/mdns.html +#:########################################################################################:# mdns: disabled: false # Disabling will make the build file smaller (and it is still available via static IP) -#preferences: -# flash_write_interval: 0s -######################################################################################### -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -######################################################################################### -# STATUS LED + +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### +#:########################################################################################:# #status_led: # pin: # number: GPIO2 -# inverted: yes +# inverted: true -######################################################################################### -# UART COMPONENT + +#:########################################################################################:# +# UART COMPONENT: # https://esphome.io/components/uart/ -######################################################################################### +#:########################################################################################:# uart: # Needed for the DMX component. - # This UART talks to the RS485 adaptor - # There is no receiving, it is a one way send + # This UART talks to the RS485 adaptor. + # There is no receiving, it is a one-way send. id: uart_bus baud_rate: 250000 - tx_pin: - number: GPIO2 #ESP8266 + tx_pin: + number: GPIO2 # ESP8266 allow_other_uses: true # For ESPHome >= 2023.12.0 stop_bits: 2 -########################################################################################## -# LIGHT COMPONENT + +#:########################################################################################:# +# LIGHT COMPONENT: # https://esphome.io/components/light/ -########################################################################################## +#:########################################################################################:# light: - platform: monochromatic - name: ${output_1_name} + name: "${output_1_name}" output: dmx_1 id: light_test_1 default_transition_length: 10s - gamma_correct: ${gamma_output_1} - restore_mode: ALWAYS_ON + gamma_correct: "${gamma_output_1}" + restore_mode: ALWAYS_ON + - platform: monochromatic - name: ${output_2_name} + name: "${output_2_name}" output: dmx_2 id: light_test_2 default_transition_length: 10s - gamma_correct: ${gamma_output_2} - restore_mode: ALWAYS_ON + gamma_correct: "${gamma_output_2}" + restore_mode: ALWAYS_ON + - platform: monochromatic - name: ${output_3_name} + name: "${output_3_name}" output: dmx_3 id: light_test_3 default_transition_length: 10s - gamma_correct: ${gamma_output_3} - restore_mode: ALWAYS_ON + gamma_correct: "${gamma_output_3}" + restore_mode: ALWAYS_ON + - platform: monochromatic - name: ${output_4_name} + name: "${output_4_name}" output: dmx_4 id: light_test_4 default_transition_length: 10s - gamma_correct: ${gamma_output_4} + gamma_correct: "${gamma_output_4}" restore_mode: ALWAYS_ON + - platform: monochromatic - name: ${output_5_name} + name: "${output_5_name}" output: dmx_5 id: light_test_5 default_transition_length: 3s - gamma_correct: ${gamma_output_5} + gamma_correct: "${gamma_output_5}" restore_mode: RESTORE_DEFAULT_OFF + - platform: monochromatic - name: ${output_6_name} + name: "${output_6_name}" output: dmx_6 id: light_test_6 default_transition_length: 3s - gamma_correct: ${gamma_output_6} + gamma_correct: "${gamma_output_6}" restore_mode: RESTORE_DEFAULT_OFF -########################################################################################## -# SENSOR COMPONENT + +#:########################################################################################:# +# SENSOR COMPONENT: # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: - # Expose each DMX channel's current output level as 0..255 integers (post-gamma) + # Expose each DMX channel's current output level as 0..255 integers - platform: template id: dmx_ch1_sensor - name: ${output_1_name} Output + name: "${output_1_name} Output" icon: mdi:counter #entity_category: diagnostic accuracy_decimals: 0 @@ -289,7 +309,7 @@ sensor: - platform: template id: dmx_ch2_sensor - name: ${output_2_name} Output + name: "${output_2_name} Output" icon: mdi:counter #entity_category: diagnostic accuracy_decimals: 0 @@ -304,7 +324,7 @@ sensor: - platform: template id: dmx_ch3_sensor - name: ${output_3_name} Output + name: "${output_3_name} Output" icon: mdi:counter #entity_category: diagnostic accuracy_decimals: 0 @@ -319,7 +339,7 @@ sensor: - platform: template id: dmx_ch4_sensor - name: ${output_4_name} Output + name: "${output_4_name} Output" icon: mdi:counter #entity_category: diagnostic accuracy_decimals: 0 @@ -334,7 +354,7 @@ sensor: - platform: template id: dmx_ch5_sensor - name: ${output_5_name} Output + name: "${output_5_name} Output" icon: mdi:counter #entity_category: diagnostic accuracy_decimals: 0 @@ -349,7 +369,7 @@ sensor: - platform: template id: dmx_ch6_sensor - name: ${output_6_name} Output + name: "${output_6_name} Output" icon: mdi:counter #entity_category: diagnostic accuracy_decimals: 0 @@ -362,53 +382,65 @@ sensor: min_value: 0 max_value: 255 -########################################################################################## -# CUSTOM COMPONENT DMX512 + +#:########################################################################################:# +# EXTERNAL COMPONENTS: # https://github.com/andyboeh/esphome-dmx512 -########################################################################################## +#:########################################################################################:# external_components: - source: github://andyboeh/esphome-dmx512 + +#:########################################################################################:# +# DMX512 COMPONENT: +# https://github.com/andyboeh/esphome-dmx512 +#:########################################################################################:# dmx512: id: dmx uart_id: uart_bus - #enable_pin: GPIOXX (Optional, I've wire them to be always active) - tx_pin: + #enable_pin: GPIOXX (Optional, I have wired them to be always active) + tx_pin: number: GPIO2 allow_other_uses: true # For ESPHome >= 2023.12.0 uart_num: 1 periodic_update: true # optional. Some dimmers may turn off without regular updates. #force_full_frames: false # optional. If true the 513 byte is always sent - #custom_break_len: 92 # optional. Break Length. Default is 92uS + #custom_break_len: 92 # optional. Break Length. Default is 92uS #custom_mab_len: 12 # optional. Mark after Break Length. Default is 12mS #update_interval: 500 # optional. Custom update interval. Default is 500mS -########################################################################################## -# OUTPUT COMPONENT -# https://esphome.io/components/output/ledc.html -########################################################################################## + +#:########################################################################################:# +# OUTPUT COMPONENT: +# https://esphome.io/components/output/ +#:########################################################################################:# output: # Raw DMX slots (these are the actual DMX universes/slots) - platform: dmx512 channel: 1 # The ID we set the device to universe: dmx # The ID of the DMX512 Component id: dmx_1_raw + - platform: dmx512 channel: 2 # The ID we set the device to universe: dmx # The ID of the DMX512 Component id: dmx_2_raw + - platform: dmx512 channel: 3 # The ID we set the device to universe: dmx # The ID of the DMX512 Component id: dmx_3_raw + - platform: dmx512 channel: 4 # The ID we set the device to universe: dmx # The ID of the DMX512 Component id: dmx_4_raw + - platform: dmx512 channel: 5 # The ID we set the device to universe: dmx # The ID of the DMX512 Component id: dmx_5_raw + - platform: dmx512 channel: 6 # The ID we set the device to universe: dmx # The ID of the DMX512 Component @@ -492,5 +524,4 @@ output: scaled = state * (1.0f - MIN) + MIN; } id(dmx_ch6_sensor).publish_state(scaled * 255.0f); - id(dmx_6_raw).set_level(scaled); - + id(dmx_6_raw).set_level(scaled); \ No newline at end of file diff --git a/esphome/esp-mainbathfancombo.yaml b/esphome/esp-mainbathfancombo.yaml index 85cb2b8..83567fe 100644 --- a/esphome/esp-mainbathfancombo.yaml +++ b/esphome/esp-mainbathfancombo.yaml @@ -1,6 +1,7 @@ ########################################################################################## +# TITLE: MAIN BATHROOM FAN/HEAT COMBO SWITCH ########################################################################################## -# MAIN BATHROOM FAN/HEAT COMBO SWITCH +# VERSIONS: # V1.5 2026-02-23 MQTT numeric timer only applies if fan already ON (does not turn fan ON) # V1.4 2026-02-23 Add mm:ss countdown text sensor (eg 22:12) + per-second countdown engine # V1.3 2026-02-23 Add 60-min cap timer + Remaining Minutes sensor (counts down) @@ -8,21 +9,37 @@ # V1.1 2025-08-26 Minor Changes (MQTT) # V1.0 2025-06-01 Initial Version ########################################################################################## +# HARDWARE: # Zemismart KS-811 Double Push Button # pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ -# -# NOTES -# - MQTT Local Usage -# Send ON to ${mqtt_command_main_topic}/${mqtt_local_device_name} and it will turn the fan ON (60 min cap) -# Send OFF to ${mqtt_command_main_topic}/${mqtt_local_device_name} and it will turn the fan OFF -# Send a value from 1 to 60 to ${mqtt_command_main_topic}/${mqtt_local_device_name} -# and it will ONLY start/restart the countdown IF the fan is already ON (in minutes) -# ########################################################################################## +# OPERATION NOTES: +# a) MQTT Local Usage +# Send ON to ${mqtt_command_main_topic}/${mqtt_local_device_name} and it will turn the fan ON (60 min cap) +# Send OFF to ${mqtt_command_main_topic}/${mqtt_local_device_name} and it will turn the fan OFF +# Send a value from 1 to 60 to ${mqtt_command_main_topic}/${mqtt_local_device_name} +# and it will ONLY start/restart the countdown IF the fan is already ON (in minutes) +# b) IR Heater Safety +# It is designed so there should be no situation that the Heater can be on without the fan. +# If the fan turns off, so will the IR Heater. +# c) Timing functions +# By default, the fan will be on for 60mins max. Other values can be sent via MQTT/HA +# d) Other device control +# This device can turn on the heated towel rail via MQTT (doubleclick button 2) +########################################################################################## +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - The fan can still be controlled with ON, OFF and given a timer value, via MQTT. +# - The Heated towel rail can also be switched on. +# b) HA/MQTT OFFLINE +# With no automation controllers, fan and heater can be controlled on/off with the switches. +# Auto timers cannot be changed, but the fam will be on for 60mins max. +# c) Internet/Wifi OFFLINE +# No further changes, SNTP not required as timing functions do not rely on accurate clock. ########################################################################################## ########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS: # If NOT using a secrets file, just replace these with the passwords etc (in quotes) ########################################################################################## substitutions: @@ -61,7 +78,7 @@ substitutions: # 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_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}" mqtt_remote_device1_command1: "BOOST" ########################################################################################## @@ -103,7 +120,7 @@ packages: #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml ########################################################################################## -# ESPHome +# ESPHOME # https://esphome.io/components/esphome.html ########################################################################################## esphome: @@ -140,7 +157,7 @@ esphome: id(relay2_forced_relay1) = false; ########################################################################################## -# ESP Platform and Framework +# ESP PLATFORM AND FRAMEWORK # https://esphome.io/components/esp32.html ########################################################################################## esp8266: @@ -149,7 +166,7 @@ esp8266: board_flash_mode: dout # Default is dout ########################################################################################## -# ESPHome Logging Enable +# LOGGING # https://esphome.io/components/logger.html ########################################################################################## logger: diff --git a/esphome/esp-mainpowermonitor.yaml b/esphome/esp-mainpowermonitor.yaml index 0ac8a61..0f895d5 100644 --- a/esphome/esp-mainpowermonitor.yaml +++ b/esphome/esp-mainpowermonitor.yaml @@ -1,15 +1,30 @@ -########################################################################################## -########################################################################################## -# MAIN HOUSE 3 PHASE POWER MONITOR -# Power Monitor using 3x PZEM004 for 3 phase monitoring plus energy monitoring for 32A EV Charger +#:########################################################################################:# +# TITLE: MAIN HOUSE 3 PHASE POWER MONITOR +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-mainpowermonitor.yaml +#:########################################################################################:# +# VERSIONS: +# v1.3 2026-02-25 Updated yaml to zorruno layout V1.1 +# v1.2 2026-02-25 Updated yaml to zorruno layout V1.1. Added EV charging binary sensor +# and EV power rolling average (default 5 min). Clarified EV pulse notes. +# v1.1 2026-02-21 Fix globals array init compile error, reduce flash writes (globals update_interval) +# v1.0 2026-02-21 Initial Version +#:########################################################################################:# +# HARDWARE: +# - Wemos D1 mini (ESP8266) +# - 3x PZEM-004T V3 (Modbus, 9600 baud) +# - DHT11 (GPIO2) +# - EV pulse input (GPIO14) +#:########################################################################################:# +# OPERATION NOTES: +# - Power Monitor using 3x PZEM-004T V3 (Modbus) for 3-phase monitoring +# - Pulse input energy monitoring for 32A EV Charger (2 Wh per pulse) +# - Adds a 5 minute rolling average for EV power to avoid spiky readings at low loads +# - Adds a binary sensor to indicate when the EV charger is operating (threshold configurable) # -# Hardware: Wemos D1 mini (ESP8266) + 3x PZEM-004T V3 (Modbus) + DHT11 + EV Pulse Input -# -# V1.1 2026-02-21 Fix globals array init compile error, reduce flash writes (globals update_interval) -# V1.0 2026-02-21 Initial Version -# -# NOTES -# - PZEM-004T V3 uses Modbus over UART at 9600 baud. +# NOTES: # - UART is on GPIO1 (TX) and GPIO3 (RX). Logger UART is disabled (baud_rate: 0). # - You will usually need to disconnect PZEM UART wires while flashing via USB. # - DHT11 is on GPIO2 (boot-strap pin and D1 mini onboard LED pin). Usually OK, but if you ever @@ -17,23 +32,35 @@ # - PZEM "energy" from ESPHome pzemac is in Wh, converted to kWh in this YAML. # - Phase mapping requested: Red=0, Yellow=1, Blue=2 (Tasmota-style). In ESPHome pzemac Modbus # addresses must be 0x01..0xF7, so this YAML maps to Red=0x01, Yellow=0x02, Blue=0x03. -# - 365-day history array is RAM-only (not restored) to avoid ESP8266 restore limits and flash wear. -########################################################################################## -########################################################################################## +# - EV pulse power at very low load is inherently "chunky" due to 2 Wh pulses. Energy totals +# remain accurate. Rolling average reduces spikes but can still read 0 W between infrequent pulses. +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, WiFi OK +# - Device continues measuring power, energy, and pulses locally. +# - MQTT/API publishing will fail until HA is back. +# b) WiFi OFFLINE (LAN down), Device powered +# - No SNTP updates, so time may become invalid or drift (depending on last sync). +# - Power and energy totals continue accumulating, but period rollovers (today/month/year) +# will not update unless time is valid. +# c) Entire WiFi/Network OFFLINE +# - Accurate time IS needed for daily/monthly/year rollovers (SNTP required for correct period boundaries). +# - Loss of network will drift the timeclocks; time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS -########################################################################################## +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-mainpowermonitor" friendly_name: "Main House 3 Phase Power Monitor" - description_comment: "Power Monitor using 3x PZEM004 for 3 phase monitoring plus energy monitoring for 32A EV Charger" + description_comment: "Power Monitor using 3x PZEM004 for 3 phase monitoring plus energy monitoring for 32A EV Charger (Layout V1.1)" device_area: "Data Cupboard" # Project Naming project_name: "Wemos.D1Mini PZEM-004T V3 3-Phase Power Monitor" - project_version: "v1.1" + project_version: "v1.3" # Passwords api_key: !secret esp-api_key @@ -45,10 +72,6 @@ substitutions: # Don't forget to switch it back when changed. current_ip_address: ${static_ip_address} - # MQTT Controls - #mqtt_device_name: "main-house-3phase-power" - #mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" - # Device Settings log_level: "ERROR" pzem_update_interval: "10s" @@ -70,6 +93,20 @@ substitutions: ev_pulse_filter_ms: "50ms" # Debounce / filter ev_pulse_pin_mode: "INPUT_PULLUP" + # EV Charging Detection (Averaged power + binary sensor) + # Minimum EV charging power threshold (W) for binary sensor + # NOTE: Pick a value comfortably above idle (idle can be ~0.2 kWh/day = very infrequent pulses). + ev_charging_min_power_w: "300" + + # Rolling average window - configuration notes: + # - Substitutions are string replacements, so window samples must be updated manually if you change times. + # - window_samples = (avg_minutes * 60) / sample_interval_seconds + ev_power_avg_window_minutes: "5" # informational + ev_power_avg_sample_interval: "10s" + ev_power_avg_sample_interval_seconds: "10" # must match the value above + ev_power_avg_window_samples: "30" # 5 min @ 10s = 30 samples + ev_power_avg_buffer_size: "180" # ring buffer >= window_samples (180 @ 10s = 30 minutes) + # Names - PZEM (per phase) pzem_red_v_name: "Main Power Red Voltage" pzem_red_i_name: "Main Power Red Current" @@ -109,6 +146,7 @@ substitutions: # Names - EV Wallcharger ev_power_name: "EV Wallcharger Power" + ev_charging_name: "EV Wallcharger Charging" ev_total_energy_name: "EV Wallcharger Total Energy" ev_today_name: "EV Wallcharger Energy Today" ev_yesterday_name: "EV Wallcharger Energy Yesterday" @@ -122,9 +160,9 @@ substitutions: hum_name: "Main Power Monitor Humidity" dew_name: "Main Power Monitor Dew Point" -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -154,9 +192,10 @@ packages: diag_basic: !include common/include_basic_diag_sensors.yaml diag_more: !include common/include_more_diag_sensors.yaml -########################################################################################## -# ESPHome -########################################################################################## +#:########################################################################################:# +# ESPHOME: +# https://esphome.io/components/esphome.html +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -172,9 +211,10 @@ esphome: - delay: 3s - script.execute: rollover_check -########################################################################################## -# ESP Platform and Framework -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +#:########################################################################################:# esp8266: board: d1_mini restore_from_flash: true @@ -185,16 +225,17 @@ preferences: mdns: disabled: false -########################################################################################## -# LOGGING -########################################################################################## +#:########################################################################################:# +# LOGGING: +# https://esphome.io/components/logger.html +#:########################################################################################:# logger: level: "${log_level}" baud_rate: 0 -########################################################################################## -# UART + MODBUS (PZEM-004T V3) -########################################################################################## +#:########################################################################################:# +# UART + MODBUS (PZEM-004T V3): +#:########################################################################################:# uart: id: uart_pzem_bus tx_pin: GPIO1 @@ -205,9 +246,9 @@ modbus: id: modbus_pzem_bus send_wait_time: 200ms -########################################################################################## -# GLOBALS (Energy rollovers + 365-day history + temp min/max) -########################################################################################## +#:########################################################################################:# +# GLOBALS (Energy rollovers + 365-day history + temp min/max): +#:########################################################################################:# globals: # Date tracking for rollovers (restored) - id: g_last_day @@ -320,6 +361,25 @@ globals: update_interval: ${globals_save_interval_pulses} initial_value: "0" + # EV rolling average power (RAM only) + - id: g_ev_power_avg_w + type: float + restore_value: no + initial_value: "0.0" + + # EV pulse history ring buffer for rolling average (RAM only) + - id: g_ev_pulses_hist + type: uint32_t[${ev_power_avg_buffer_size}] + restore_value: no + - id: g_ev_pulses_hist_index + type: int + restore_value: no + initial_value: "0" + - id: g_ev_pulses_hist_count + type: int + restore_value: no + initial_value: "0" + # Temperature min/max tracking (RAM ONLY - not restored, gentler on flash) - id: g_temp_today_min type: float @@ -357,18 +417,35 @@ globals: restore_value: no initial_value: "-9999.0" -########################################################################################## -# INTERVAL (periodic rollover checks) -# NOTE: common_sntp may define its own interval. That is OK. -########################################################################################## +#:########################################################################################:# +# INTERVAL (periodic rollover checks + EV rolling average updates): +#:########################################################################################:# interval: - interval: "${rollover_check_interval}" then: - script.execute: rollover_check -########################################################################################## -# SENSORS -########################################################################################## + - interval: "${ev_power_avg_sample_interval}" + then: + - script.execute: ev_power_avg_update + +#:########################################################################################:# +# BINARY SENSORS: +#:########################################################################################:# +binary_sensor: + - platform: template + name: "${ev_charging_name}" + id: ev_wallcharger_charging + device_class: power + icon: "mdi:ev-station" + lambda: |- + const float p = id(ev_power_avg_w).state; + if (isnan(p)) return false; + return (p >= ${ev_charging_min_power_w}); + +#:########################################################################################:# +# SENSORS: +#:########################################################################################:# sensor: ######################################################################################## # PZEM-004T V3 - RED PHASE @@ -851,23 +928,16 @@ sensor: ######################################################################################## # EV WALLCHARGER PULSE ENERGY (GPIO14) - # - pulse_counter reports pulses/minute - # - Power (W) = pulses_per_min * (Wh_per_pulse) * 60 ######################################################################################## - platform: pulse_counter id: ev_pulse_rate_ppm + internal: true pin: number: GPIO14 mode: ${ev_pulse_pin_mode} inverted: false update_interval: 10s internal_filter: ${ev_pulse_filter_ms} - name: "${ev_power_name}" - unit_of_measurement: "W" - accuracy_decimals: 0 - filters: - - lambda: |- - return x * (${ev_pulse_wh} * 60.0f); total: id: ev_pulses_raw_total internal: true @@ -882,6 +952,15 @@ sensor: id(g_ev_pulses_total_abs) += (raw - last); id(g_ev_pulses_raw_last) = raw; + - platform: template + name: "${ev_power_name}" + id: ev_power_avg_w + unit_of_measurement: "W" + accuracy_decimals: 0 + update_interval: "${ev_power_avg_sample_interval}" + lambda: |- + return id(g_ev_power_avg_w); + - platform: template name: "${ev_total_energy_name}" id: ev_total_energy_kwh @@ -957,9 +1036,9 @@ sensor: lambda: |- return id(g_ev_last_year_kwh); -########################################################################################## -# SCRIPTS -########################################################################################## +#:########################################################################################:# +# SCRIPTS: +#:########################################################################################:# script: # Initialize RAM-only history arrays and counters - id: init_history_arrays @@ -972,6 +1051,59 @@ script: id(g_mains_daily_hist_index) = 0; id(g_mains_daily_hist_count) = 0; + // Init EV pulse history buffer so rolling average starts stable after boot + const int ev_buf = ${ev_power_avg_buffer_size}; + const uint32_t p0 = id(g_ev_pulses_total_abs); + + for (int i = 0; i < ev_buf; i++) { + id(g_ev_pulses_hist)[i] = p0; + } + id(g_ev_pulses_hist_index) = 0; + id(g_ev_pulses_hist_count) = ev_buf; + id(g_ev_power_avg_w) = 0.0f; + + # EV rolling average update (based on absolute pulse total) + - id: ev_power_avg_update + mode: queued + then: + - lambda: |- + const int buf = ${ev_power_avg_buffer_size}; + int idx = id(g_ev_pulses_hist_index); + if (idx < 0 || idx >= buf) idx = 0; + + const uint32_t p_now = id(g_ev_pulses_total_abs); + id(g_ev_pulses_hist)[idx] = p_now; + + idx = (idx + 1) % buf; + id(g_ev_pulses_hist_index) = idx; + + if (id(g_ev_pulses_hist_count) < buf) id(g_ev_pulses_hist_count)++; + + int win = ${ev_power_avg_window_samples}; + if (win < 1) win = 1; + if (win > buf) win = buf; + + if (id(g_ev_pulses_hist_count) < win) { + return; + } + + int old_idx = idx - win; + if (old_idx < 0) old_idx += buf; + + const uint32_t p_old = id(g_ev_pulses_hist)[old_idx]; + const uint32_t dp = (p_now >= p_old) ? (p_now - p_old) : 0; + + const float wh = ((float) dp) * (${ev_pulse_wh}); + const float seconds = ((float) win) * (${ev_power_avg_sample_interval_seconds}); + + if (seconds <= 0.0f) { + id(g_ev_power_avg_w) = 0.0f; + return; + } + + // W = Wh * 3600 / seconds + id(g_ev_power_avg_w) = wh * 3600.0f / seconds; + # Period rollover check (day/month/year) for: # - Main total energy (sum of 3 PZEM channels) # - EV total energy (pulse derived) @@ -1117,9 +1249,42 @@ script: if (t < id(g_temp_month_min)) id(g_temp_month_min) = t; if (t > id(g_temp_month_max)) id(g_temp_month_max) = t; -########################################################################################## -# SWITCHES -########################################################################################## +#:########################################################################################:# +# SWITCHES: +#:########################################################################################:# switch: - platform: restart - name: "Main Power Monitor Restart" \ No newline at end of file + name: "Main Power Monitor Restart" + +#:########################################################################################:# +# ROLLBACK COPY (v1.1) - EV POWER SECTION (for quick revert) +# NOTE: This is commented out. Remove the new EV blocks and uncomment to restore old behavior. +#:########################################################################################:# +#sensor: +# - platform: pulse_counter +# id: ev_pulse_rate_ppm +# pin: +# number: GPIO14 +# mode: ${ev_pulse_pin_mode} +# inverted: false +# update_interval: 10s +# internal_filter: ${ev_pulse_filter_ms} +# name: "${ev_power_name}" +# unit_of_measurement: "W" +# accuracy_decimals: 0 +# filters: +# - lambda: |- +# return x * (${ev_pulse_wh} * 60.0f); +# total: +# id: ev_pulses_raw_total +# internal: true +# on_value: +# then: +# - lambda: |- +# uint32_t raw = (uint32_t) x; +# uint32_t last = id(g_ev_pulses_raw_last); +# if (raw < last) { +# last = 0; +# } +# id(g_ev_pulses_total_abs) += (raw - last); +# id(g_ev_pulses_raw_last) = raw; \ No newline at end of file diff --git a/esphome/esp-masterbathtowelrail.yaml b/esphome/esp-masterbathtowelrail.yaml index d0b2697..02e2860 100644 --- a/esphome/esp-masterbathtowelrail.yaml +++ b/esphome/esp-masterbathtowelrail.yaml @@ -1,15 +1,19 @@ -############################################# -############################################# -# MASTER BATHROOM HEATED TOWEL RAIL -# Controlled by a Sonoff Basic -# +#:########################################################################################:# +# TITLE: MASTER BATHROOM HEATED TOWEL RAIL +# zorruno.com layout v1.0 2026 +#:########################################################################################:# +# VERSIONS: # V2.2 2026-01-30 Added Morning/Evening Timer enable switches (gate timer windows) # V2.1 2025-06-12 Added select and button to chose modes, added countdown & startup to boost # V2.0 2025-06-05 YAML Tidyups # V1.1 2025-04-12 Fixes to timers and offline modes # V1.0 2025-02-14 Initial Version -# -# INSTRUCTIONS +#:########################################################################################:# +# HARDWARE: +# Controlled by a Sonoff Basic +# pinout/schematic: https://devices.esphome.io/devices/sonoff-basic-r4-v1.0/ +#:########################################################################################:# +# OPERATION NOTES: # - It allows the device to work in a standalone timer style operation # - The timer has a morning and evening time (but no weekday/weekend settings) # - Morning Timer Enable / Evening Timer Enable switches gate their timer windows (default ON and restored on reboot) @@ -23,8 +27,8 @@ # - TIMER mode will always be switched on after BOOST mode is complete # - Home Assistant entities are set so that BOOST mode can be pressed with a button and other modes selectable with a dropdown # - If you need it ON continuously with no MQTT, toggle power ON/OFF 4 times within 30 seconds (with ~2 secs in between to allow it to boot) -# -# MQTT Commands +#:########################################################################################:# +# MQTT COMMANDS: # Values will be set in place on the update_interval time, not immediately # Use 00:00 in 24hr format for time setting. (Note there is no weekday/weekend setting) # mqtt_timer_topic/morning-on/06:00 : Time device will go on @@ -42,14 +46,25 @@ # 1 = ON # 2 = TIMER # 3 = BOOST -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - The towel rail will stick to its assigned schedule (and should remember on reboot) +# - Shedule times and on/off switching can still occur via MQTT +# - Other switches such as the IR Heater/Fan combo can still command the towel rail +# b) HA/MQTT OFFLINE +# With no automation controllers, the HTR will still remember its timing functions, and will +# turn on once or twice per day. If internet/wifi is still available, timing will be accurate. +# c) Internet/Wifi OFFLINE +# The HTR will still come on once or twice per day (depending on previous settings) however +# timing will likely shift. To make timing more accurate, it can be powered down then up at 12pm. +# Obviously this may drift again over time. +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-masterbathtowelrail" @@ -66,6 +81,10 @@ substitutions: ota_pass: !secret esp-masterbathtowelrail_ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-masterbathtowelrail_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings relay_icon: "mdi:heating-coil" log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE @@ -79,10 +98,10 @@ substitutions: evening_on_default: "1260" # Default in minutes from midnight. Default 21:00 => 1260 evening_off_default: "1439" # Default in minutes from midnight. Default 23:59 => 1439 => 1440 is midnight -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -91,6 +110,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -116,10 +136,10 @@ packages: #diag_debug: !include common/include_debug_diag_sensors.yaml #diag_resetcount: !include common/include_resetcount_diag_sensors.yaml -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" @@ -175,10 +195,11 @@ esphome: } - script.execute: evaluate_relay_state # Check what the relay should be doing straight away -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp8266: board: esp01_1m # The original sonoff basic restore_from_flash: true # restore some values on reboot @@ -189,21 +210,21 @@ preferences: mdns: disabled: true -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: level: "${log_level}" #INFO Level suggested, or DEBUG for testing baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -#################################################### -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ # Relay Switch (Sonoff Basic Relay on GPIO12) -#################################################### +#:########################################################################################:# switch: - platform: gpio name: "Towel Rail Power" @@ -239,12 +260,11 @@ switch: on_turn_off: - script.execute: evaluate_relay_state -########################################################################################## -# Global Variables for use in automations etc +#:########################################################################################:# +# GLOBAL VARIABLES: # https://esphome.io/guides/automations.html?highlight=globals#global-variables -########################################################################################## +#:########################################################################################:# globals: - # Tracks the time (in seconds from midnight) at the previous boot - id: last_boot_time_s type: int @@ -309,10 +329,10 @@ globals: restore_value: false initial_value: "0" -########################################################################################## -# Text Sensors +#:########################################################################################:# +# TEST SENSORS COMPONENT: # https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# text_sensor: ############################ @@ -514,10 +534,10 @@ text_sensor: return { std::string(buff) }; update_interval: "${update_interval}" -########################################################################################## -# NUMBER COMPONENT +#:########################################################################################:# +# NUMBER COMPONENT: # https://esphome.io/components/number/index.html -########################################################################################## +#:########################################################################################:# number: # A value for setting operation mode via HTTP - platform: template @@ -532,10 +552,10 @@ number: // x holds the incoming value (0-3) id(operation_mode) = int(x); -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: gpio pin: @@ -566,10 +586,10 @@ binary_sensor: lambda: |- return id(relay).state; -########################################################################################## -# Sensors +#:########################################################################################:# +# SENSORS COMPONENT: # https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# sensor: - platform: template name: "Timeclock: Boost Duration" @@ -616,10 +636,10 @@ sensor: // never return negative return rem > 0 ? rem : 0; -################################################################################################# -# BUTTON COMPONENT +#:###############################################################################################:# +# BUTTON COMPONENT: # https://esphome.io/components/button/index.html -################################################################################################# +#:###############################################################################################:# button: - platform: template name: "Boost now" @@ -654,10 +674,10 @@ button: - switch.turn_on: evening_timer_enable - script.execute: evaluate_relay_state -################################################################################################# -# SELECT COMPONENT +#:###############################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -################################################################################################# +#:###############################################################################################:# select: - platform: template name: "Operation Mode" @@ -690,10 +710,10 @@ select: } - script.execute: evaluate_relay_state -################################################################################################# -# SCRIPT COMPONENT +#:###############################################################################################:# +# SCRIPT COMPONENT: # https://esphome.io/components/script.html -################################################################################################# +#:###############################################################################################:# # Script: evaluate and drive the relay script: - id: evaluate_relay_state @@ -741,10 +761,10 @@ script: else id(relay).turn_off(); } -################################################################################################# -# INTERVAL COMPONENT +#:###############################################################################################:# +# INTERVAL COMPONENT: # https://esphome.io/components/interval.html -################################################################################################# +#:###############################################################################################:# # Interval: bumps time (even if no SNTP), then calls the script to evaluate relay state interval: - interval: "1min" diff --git a/esphome/esp-occupancyoffice.yaml b/esphome/esp-occupancyoffice.yaml index 48f9864..fae09da 100644 --- a/esphome/esp-occupancyoffice.yaml +++ b/esphome/esp-occupancyoffice.yaml @@ -1,46 +1,85 @@ -############################################# -############################################# -# HiLink LD1125H mmWave sensor, with BME280 Temp/Hum/Pres Sensor on an ESP32 -# https://zorruno.com/2024/mmwave-occupancy-with-esp32-ld1125h/ -# -# https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/tree/main -# https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/blob/main/LD1125H/ESP32-LD1125H-Complete.yaml +#:########################################################################################:# +# TITLE: OFFICE OCCUPANCY AND ENVIRONMENT +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-occupancyoffice.yaml +#:########################################################################################:# +# VERSIONS: +# v1.0 2026-02-25 Updated yaml to zorruno layout V1.1 +#:########################################################################################:# +# HARDWARE: +# - D1 Mini ESP32 (ESP32) +# - HiLink LD1125H mmWave sensor (UART @ 115200) +# - BME280 Temp/Humidity/Pressure sensor (I2C, addr 0x76) +# - Optional: Bluetooth Proxy / BLE tracker enabled # -# mth1: 0 to 2.8m sensitive -# mth2: 2.8 to 8m sensitive -# mth3: above 8m sensitive -# rmax: max distance -# Clearance Time: Mov/Occ to Clearance waiting time -# Movement Time: Mov to Occ waiting time -# -############################################# -############################################# +# References: +# - https://zorruno.com/2024/mmwave-occupancy-with-esp32-ld1125h/ +# - https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/tree/main +# - https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/blob/main/LD1125H/ESP32-LD1125H-Complete.yaml +#:########################################################################################:# +# OPERATION NOTES: +# - LD1125H tuning parameters: +# - mth1: 0 to 2.8m sensitive +# - mth2: 2.8 to 8m sensitive +# - mth3: above 8m sensitive +# - rmax: max distance +# - Clearance Time: Mov/Occ to Clearance waiting time +# - Movement Time: Mov to Occ waiting time +# - On boot, this device pushes mth1/mth2/mth3/rmax values to the LD1125H via UART. +# - Uses the ssieb "serial" external component to read UART lines and parse "mov/occ" lines. +# - Publishes a text occupancy state (Movement/Occupancy/Clearance) and binary sensors for: +# - mmWave Occupancy or Movement (occupancy) +# - mmWave Movement (motion) +# - BLE scanning is started/stopped based on HA API client connection (reduces BLE load when unused). +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device continues running mmWave logic and environment sensors. +# - MQTT still functions; HA entities will update again when HA returns. +# b) MQTT OFFLINE (or broker unreachable) +# - Device continues running locally and via HA API (if HA is reachable). +# - MQTT-based integrations/updates will not function until MQTT returns. +# c) Entire WiFi/Network OFFLINE +# - Device continues running locally, but HA/MQTT integration is unavailable. +# - Accurate time is NOT needed (SNTP not needed): logic uses relative time (time since boot), +# but timing resets on reboot. +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: + # Device Naming device_name: "esp-occupancyoffice" friendly_name: "Office Occupancy & Environment" - description_comment: "D1 Mini ESP32 with LD1125H mmWave and environment sensors for downstairs office" - api_key: !secret esp-occupancyoffice_api_key #unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-occupancyoffice_ota_pass #unfortunately you can't use substitutions inside secrets names + description_comment: "D1 Mini ESP32 with LD1125H mmWave and environment sensors for downstairs office (Layout V1.1)" + device_area: "Office" + + # Project Naming + project_name: "HiLink.LD1125H Office Occupancy" + project_version: "v1.0" + + # Passwords & Secrets (unfortunately you can't use substitutions inside secrets names) + api_key: !secret esp-occupancyoffice_api_key + ota_pass: !secret esp-occupancyoffice_ota_pass static_ip_address: !secret esp-occupancyoffice_ip - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - device_area: "Office" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - ############################################# - # SPECIFIC PROJECT VARIABLE SUBSTITUTIONS - ############################################# - # - # + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} -########################################################################################## + # Device Settings + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # general sensor update interval + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -49,416 +88,395 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" - - #### HOME ASSISTANT API (choose encryption or no encryption options) #### - common_api: !include - file: common/api_common.yaml - #file: common/api_common_noencryption.yaml - vars: - local_api_key: "${api_key}" + local_current_ip_address: "${current_ip_address}" #### MQTT #### common_mqtt: !include file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: - name: ${device_name} - friendly_name: ${friendly_name} - comment: ${description_comment} #appears on the esphome page in HA - min_version: 2024.6.0 + name: "${device_name}" + friendly_name: "${friendly_name}" + comment: "${description_comment}" area: "${device_area}" + min_version: 2024.6.0 + project: + name: "${project_name}" + version: "${project_version}" platformio_options: build_flags: - - "-Os" # optimize for size - - "-Wl,--gc-sections" # drop unused code/data - - "-fno-exceptions" # strip C++ exceptions - #- "-fno-rtti" # strip C++ RTTI + - "-Os" + - "-Wl,--gc-sections" + - "-fno-exceptions" + # - "-fno-rtti" + on_boot: - priority: -200 then: - uart.write: - id: LD1125H_UART_BUS + id: ld1125h_uart_bus data: !lambda |- - std::string th1st = "mth1=" + str_sprintf("%.0f", id(LD1125H_mth1).state) + "\r\n"; + std::string th1st = "mth1=" + str_sprintf("%.0f", id(ld1125h_mth1).state) + "\r\n"; return std::vector(th1st.begin(), th1st.end()); - uart.write: - id: LD1125H_UART_BUS + id: ld1125h_uart_bus data: !lambda |- - std::string th2st = "mth2=" + str_sprintf("%.0f", id(LD1125H_mth2).state) + "\r\n"; + std::string th2st = "mth2=" + str_sprintf("%.0f", id(ld1125h_mth2).state) + "\r\n"; return std::vector(th2st.begin(), th2st.end()); - uart.write: - id: LD1125H_UART_BUS + id: ld1125h_uart_bus data: !lambda |- - std::string th3st = "mth3=" + str_sprintf("%.0f", id(LD1125H_mth3).state) + "\r\n"; + std::string th3st = "mth3=" + str_sprintf("%.0f", id(ld1125h_mth3).state) + "\r\n"; return std::vector(th3st.begin(), th3st.end()); - uart.write: - id: LD1125H_UART_BUS + id: ld1125h_uart_bus data: !lambda |- - std::string rmaxst = "rmax=" + str_sprintf("%.1f", id(LD1125H_rmax).state) + "\r\n"; + std::string rmaxst = "rmax=" + str_sprintf("%.1f", id(ld1125h_rmax).state) + "\r\n"; return std::vector(rmaxst.begin(), rmaxst.end()); -############################################# -# ESP Platform and Framework +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK # https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# esp32: board: esp32dev framework: - #type: arduino - type: esp-idf #Suggest using the ESP-IDF Framework. Changing from arduino to esp-idf needs a cabled download to change partitions - version: recommended #recommended, latest or dev + # type: arduino + type: esp-idf + version: recommended -############################################# -# ESPHome external or custom components to use +#:########################################################################################:# +# EXTERNAL COMPONENTS # https://esphome.io/components/external_components.html -# https://github.com/ssieb/esphome_components/tree/master/components/serial -############################################# +#:########################################################################################:# external_components: - source: type: git - url: https://github.com/ssieb/custom_components #Thanks for @ssieb components. - components: [ serial ] #text_sensor that reads lines for a uart. Also, a sensor that reads single binary values from the uart. + url: https://github.com/ssieb/custom_components + components: [ serial ] -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: ${log_level} #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 -############################################# -# Enable the Home Assistant API +#:########################################################################################:# +# API (Home Assistant) # https://esphome.io/components/api.html -############################################# +#:########################################################################################:# api: encryption: - key: ${api_key} - #key: "puCd6EGmFp3hU56N8dOo5u17bXwDr0aVRWiDoNdPDoE=" + key: "${api_key}" on_client_connected: - esp32_ble_tracker.start_scan: - continuous: true + continuous: true on_client_disconnected: - esp32_ble_tracker.stop_scan: - - -############################################# -# i2c bus +#:########################################################################################:# +# I2C BUS (BME280) # https://esphome.io/components/i2c.html -# 10, 50, 100, 200, 800 are possible settings -# for frequency, 50kHz is default -############################################# +#:########################################################################################:# i2c: sda: GPIO19 scl: GPIO21 - scan: True #look for devices on boot up and report + scan: true frequency: 50kHz -############################################# -# UART Serial -# hardware on EPS32, but software, and can be glitchy on ESP8266 +#:########################################################################################:# +# UART (LD1125H) # https://esphome.io/components/uart.html -############################################# +#:########################################################################################:# uart: - id: LD1125H_UART_BUS - rx_pin: GPIO16 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang - tx_pin: GPIO17 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang + id: ld1125h_uart_bus + rx_pin: GPIO16 + tx_pin: GPIO17 baud_rate: 115200 data_bits: 8 stop_bits: 1 parity: NONE -############################################# -# Bluetooth +#:########################################################################################:# +# BLUETOOTH PROXY / BLE TRACKER # https://esphome.io/components/bluetooth_proxy.html # https://esphome.io/components/esp32_ble_tracker.html -# Remember that this takes a LOT of processing. On the -# ESP32, enable the IDF framework, and disable the -# Web server component. Changing to the IDF framework -# needs to be via cable not OTA to change the -# partition setup. -############################################# +#:########################################################################################:# bluetooth_proxy: active: true cache_services: true esp32_ble_tracker: - scan_parameters: - continuous: false + scan_parameters: + continuous: false -############################################# -# Global Variables for use in automations etc -# https://esphome.io/guides/automations.html?highlight=globals#global-variables -############################################# +#:########################################################################################:# +# GLOBALS +# https://esphome.io/components/globals.html +#:########################################################################################:# globals: - - id: LD1125H_Last_Time + - id: ld1125h_last_time type: time_t - restore_value: no - #initial_value: time(NULL) - #initial_value: !lambda 'return ::time(nullptr);' + restore_value: false initial_value: "0" - - id: LD1125H_Last_Mov_Time + + - id: ld1125h_last_mov_time type: time_t - restore_value: no - #initial_value: time(NULL) - #initial_value: !lambda 'return ::time(nullptr);' + restore_value: false initial_value: "0" - - id: LD1125H_Clearence_Status + + - id: ld1125h_clearance_status type: bool - restore_value: no + restore_value: false initial_value: "false" -############################################# -# General esp status LED +#:########################################################################################:# +# STATUS LED # https://esphome.io/components/status_led.html -############################################# +#:########################################################################################:# status_led: pin: - number: GPIO2 #ESP32 Onboard LED - ignore_strapping_warning: True #https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins + number: GPIO2 + ignore_strapping_warning: true inverted: false -############################################# -# Interval Automations -# https://esphome.io/guides/automations.html -############################################# +#:########################################################################################:# +# INTERVAL (Clearance scan) +# https://esphome.io/components/interval.html +#:########################################################################################:# interval: - - interval: 1s # Clearance Scan Time + - interval: 1s setup_priority: -200 then: - lambda: |- - // Use the global C time() function (::time(nullptr)) - if ((::time(nullptr) - id(LD1125H_Last_Time)) > id(LD1125H_Clear_Time).state) { - if ((id(LD1125H_Clearence_Status) == false) || - (id(LD1125H_Occupancy).state != "Clearance")) { - id(LD1125H_Occupancy).publish_state("Clearance"); - id(LD1125H_Clearence_Status) = true; + if ((::time(nullptr) - id(ld1125h_last_time)) > id(ld1125h_clear_time).state) { + if ((id(ld1125h_clearance_status) == false) || + (id(ld1125h_occupancy).state != "Clearance")) { + id(ld1125h_occupancy).publish_state("Clearance"); + id(ld1125h_clearance_status) = true; } - if (id(LD1125H_MovOcc_Binary).state == true) { - id(LD1125H_MovOcc_Binary).publish_state(false); + if (id(ld1125h_movocc_binary).state == true) { + id(ld1125h_movocc_binary).publish_state(false); } - if (id(LD1125H_Mov_Binary).state == true) { - id(LD1125H_Mov_Binary).publish_state(false); + if (id(ld1125h_mov_binary).state == true) { + id(ld1125h_mov_binary).publish_state(false); } - // Update the last-seen timestamp - id(LD1125H_Last_Time) = ::time(nullptr); + id(ld1125h_last_time) = ::time(nullptr); } -############################################# -# Number Sensors (custom component) -# refer https://github.com/ssieb/esphome_components/tree/master/components/serial -############################################# +#:########################################################################################:# +# NUMBER (LD1125H controls) +# https://esphome.io/components/number/ +#:########################################################################################:# number: - platform: template - name: "0-2.8m Sensitivity" # mth1 is 0~2.8m Sensitivity. - id: LD1125H_mth1 + name: "0-2.8m Sensitivity" + id: ld1125h_mth1 icon: "mdi:cogs" optimistic: true - restore_value: true #If you don't want to store the setting at ESP, set it to false. - initial_value: "60.0" #Default mth1 Setting + restore_value: true + initial_value: "60.0" min_value: 10.0 max_value: 600.0 step: 5.0 set_action: - then: - - uart.write: - id: LD1125H_UART_BUS - data: !lambda |- - std::string th1st = "mth1=" + str_sprintf("%.0f",x) +"\r\n"; - return std::vector(th1st.begin(), th1st.end()); + - uart.write: + id: ld1125h_uart_bus + data: !lambda |- + std::string th1st = "mth1=" + str_sprintf("%.0f", x) + "\r\n"; + return std::vector(th1st.begin(), th1st.end()); + - platform: template - name: "2.8-8m Sensitivity" # mth2 is 2.8~8m Sensitivity. - id: LD1125H_mth2 + name: "2.8-8m Sensitivity" + id: ld1125h_mth2 icon: "mdi:cogs" optimistic: true - restore_value: true # If you don't want to store the setting at ESP, set it to false. - initial_value: "30" # Default mth2 Setting + restore_value: true + initial_value: "30" min_value: 5 max_value: 300 step: 5 set_action: - then: - - uart.write: - id: LD1125H_UART_BUS - data: !lambda |- - std::string th2st = "mth2=" + str_sprintf("%.0f",x) +"\r\n"; - return std::vector(th2st.begin(), th2st.end()); + - uart.write: + id: ld1125h_uart_bus + data: !lambda |- + std::string th2st = "mth2=" + str_sprintf("%.0f", x) + "\r\n"; + return std::vector(th2st.begin(), th2st.end()); + - platform: template - name: "8m+ Sensitivity" # mth3 is above 8m Sensitivity. - id: LD1125H_mth3 + name: "8m+ Sensitivity" + id: ld1125h_mth3 icon: "mdi:cogs" optimistic: true - restore_value: true # If you don't want to store the setting at ESP, set it to false. - initial_value: "20" # Default mth3 Setting + restore_value: true + initial_value: "20" min_value: 5 max_value: 200 step: 5 set_action: - then: - - uart.write: - id: LD1125H_UART_BUS - data: !lambda |- - std::string th3st = "mth3=" + str_sprintf("%.0f",x) +"\r\n"; - return std::vector(th3st.begin(), th3st.end()); + - uart.write: + id: ld1125h_uart_bus + data: !lambda |- + std::string th3st = "mth3=" + str_sprintf("%.0f", x) + "\r\n"; + return std::vector(th3st.begin(), th3st.end()); + - platform: template - name: "Max Detection (m)" # rmax is max detection distance. - id: LD1125H_rmax + name: "Max Detection (m)" + id: ld1125h_rmax icon: "mdi:cogs" optimistic: true - restore_value: true #If you don't want to store the setting at ESP, set it to false. - initial_value: "8" #Default rmax Setting + restore_value: true + initial_value: "8" min_value: 0.4 max_value: 12 step: 0.1 set_action: - then: - - uart.write: - id: LD1125H_UART_BUS - data: !lambda |- - std::string rmaxst = "rmax=" + str_sprintf("%.1f",x) +"\r\n"; - return std::vector(rmaxst.begin(), rmaxst.end()); + - uart.write: + id: ld1125h_uart_bus + data: !lambda |- + std::string rmaxst = "rmax=" + str_sprintf("%.1f", x) + "\r\n"; + return std::vector(rmaxst.begin(), rmaxst.end()); + - platform: template name: "Clearence Time (s)" - id: LD1125H_Clear_Time + id: ld1125h_clear_time icon: "mdi:cogs" optimistic: true - restore_value: true #If you don't want to store the setting at ESP, set it to false. - initial_value: "5" #LD1125H Mov/Occ > Clearence Time Here + restore_value: true + initial_value: "5" min_value: 0.5 max_value: 20 step: 0.5 + - platform: template name: "Movement Time (s)" - id: LD1125H_Mov_Time + id: ld1125h_mov_time icon: "mdi:cogs" optimistic: true - restore_value: true #If you don't want to store the setting at ESP, set it to false. - initial_value: "1" #LD1125H Mov > Occ Time Here + restore_value: true + initial_value: "1" min_value: 0.5 max_value: 10 step: 0.5 -############################################# -# General Sensors -# https://esphome.io/components/sensor/index.html -############################################# +#:########################################################################################:# +# SENSOR +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: bme280_i2c temperature: name: "Temperature" - accuracy_decimals: 1 + accuracy_decimals: 1 oversampling: 2x pressure: name: "Pressure" oversampling: 2x humidity: name: "Humidity" - accuracy_decimals: 1 + accuracy_decimals: 1 oversampling: 2x address: 0x76 - update_interval: ${update_interval} + update_interval: "${update_interval}" - platform: template name: "mmWave Distance" - id: LD1125H_Distance + id: ld1125h_distance icon: "mdi:signal-distance-variant" unit_of_measurement: "m" accuracy_decimals: 2 - filters: # Use Fliter To Debounce - - sliding_window_moving_average: - window_size: 8 - send_every: 2 - - heartbeat: 0.2s + filters: + - sliding_window_moving_average: + window_size: 8 + send_every: 2 + - heartbeat: 0.2s -############################################# -# Text Sensors -# refer https://esphome.io/components/text_sensor/index.html -############################################# +#:########################################################################################:# +# TEXT SENSOR +# https://esphome.io/components/text_sensor/ +#:########################################################################################:# text_sensor: - platform: serial - uart_id: LD1125H_UART_BUS - name: ${friendly_name} LD1125H UART Text - id: LD1125H_UART_Text + uart_id: ld1125h_uart_bus + name: "${friendly_name} LD1125H UART Text" + id: ld1125h_uart_text icon: "mdi:format-text" - internal: True + internal: true on_value: lambda: |- - if (id(LD1125H_UART_Text).state.substr(0,3) == "occ") { - id(LD1125H_Distance).publish_state( - atof(id(LD1125H_UART_Text).state.substr(9).c_str()) + if (id(ld1125h_uart_text).state.substr(0, 3) == "occ") { + id(ld1125h_distance).publish_state( + atof(id(ld1125h_uart_text).state.substr(9).c_str()) ); - if ((::time(nullptr) - id(LD1125H_Last_Mov_Time)) > - id(LD1125H_Mov_Time).state) { - id(LD1125H_Occupancy).publish_state("Occupancy"); - if (id(LD1125H_MovOcc_Binary).state == false) { - id(LD1125H_MovOcc_Binary).publish_state(true); + if ((::time(nullptr) - id(ld1125h_last_mov_time)) > + id(ld1125h_mov_time).state) { + id(ld1125h_occupancy).publish_state("Occupancy"); + if (id(ld1125h_movocc_binary).state == false) { + id(ld1125h_movocc_binary).publish_state(true); } - if (id(LD1125H_Mov_Binary).state == true) { - id(LD1125H_Mov_Binary).publish_state(false); + if (id(ld1125h_mov_binary).state == true) { + id(ld1125h_mov_binary).publish_state(false); } } - if (id(LD1125H_MovOcc_Binary).state == false) { - id(LD1125H_MovOcc_Binary).publish_state(true); + if (id(ld1125h_movocc_binary).state == false) { + id(ld1125h_movocc_binary).publish_state(true); } - // Update both last-movement and last-anything timestamps - id(LD1125H_Last_Time) = ::time(nullptr); - if (id(LD1125H_Clearence_Status) == true) { - id(LD1125H_Clearence_Status) = false; + id(ld1125h_last_time) = ::time(nullptr); + if (id(ld1125h_clearance_status) == true) { + id(ld1125h_clearance_status) = false; } } - else if (id(LD1125H_UART_Text).state.substr(0,3) == "mov") { - id(LD1125H_Distance).publish_state( - atof(id(LD1125H_UART_Text).state.substr(9).c_str()) + else if (id(ld1125h_uart_text).state.substr(0, 3) == "mov") { + id(ld1125h_distance).publish_state( + atof(id(ld1125h_uart_text).state.substr(9).c_str()) ); - id(LD1125H_Occupancy).publish_state("Movement"); - if (id(LD1125H_MovOcc_Binary).state == false) { - id(LD1125H_MovOcc_Binary).publish_state(true); + id(ld1125h_occupancy).publish_state("Movement"); + if (id(ld1125h_movocc_binary).state == false) { + id(ld1125h_movocc_binary).publish_state(true); } - if (id(LD1125H_Mov_Binary).state == false) { - id(LD1125H_Mov_Binary).publish_state(true); + if (id(ld1125h_mov_binary).state == false) { + id(ld1125h_mov_binary).publish_state(true); } - // Update both movement-specific and general timestamps - id(LD1125H_Last_Mov_Time) = ::time(nullptr); - id(LD1125H_Last_Time) = ::time(nullptr); - if (id(LD1125H_Clearence_Status) == true) { - id(LD1125H_Clearence_Status) = false; + id(ld1125h_last_mov_time) = ::time(nullptr); + id(ld1125h_last_time) = ::time(nullptr); + if (id(ld1125h_clearance_status) == true) { + id(ld1125h_clearance_status) = false; } } + - platform: template name: "mmWave Occupancy" - id: LD1125H_Occupancy + id: ld1125h_occupancy icon: "mdi:motion-sensor" -############################################# -# Binary Sensors -# https://esphome.io/components/binary_sensor/index.html -############################################# +#:########################################################################################:# +# BINARY SENSOR +# https://esphome.io/components/binary_sensor/ +#:########################################################################################:# binary_sensor: - platform: template name: "mmWave Occupancy or Movement" - id: LD1125H_MovOcc_Binary + id: ld1125h_movocc_binary device_class: occupancy + - platform: template name: "mmWave Movement" - id: LD1125H_Mov_Binary - device_class: motion \ No newline at end of file + id: ld1125h_mov_binary + device_class: motion \ No newline at end of file diff --git a/esphome/esp-occupancystair.yaml b/esphome/esp-occupancystair.yaml index f3d36cc..ebdcb21 100644 --- a/esphome/esp-occupancystair.yaml +++ b/esphome/esp-occupancystair.yaml @@ -1,58 +1,96 @@ -########################################################################################## -########################################################################################## -# HiLink LD2410 mmWave sensor, with BME280 Temp/Hum/Pres Sensor and PIR on an ESP32 -# VERSION +#:########################################################################################:# +# TITLE: STAIR OCCUPANCY AND UNDERHOUSE ENVIRONMENT +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-occupancystair.yaml +#:########################################################################################:# +# VERSIONS: +# 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 # V2.0 2025-06-05 YAML Tidyups +#:########################################################################################:# +# HARDWARE: +# D1 Mini ESP32 with: +# - HiLink LD2410 mmWave presence sensor (UART) +# - BME280 Temp/Humidity/Pressure sensor (I2C) +# - Generic PIR sensor (GPIO) # -# https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/tree/main -# https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/blob/main/LD1125H/ESP32-LD1125H-Complete.yaml +# References: +# - https://esphome.io/components/sensor/ld2410.html +# - https://www.simplysmart.house/blog/presence-detection-ld2410-home-assistant +# - https://github.com/patrick3399/Hi-Link_mmWave_Radar_ESPHome/tree/main +#:########################################################################################:# +# OPERATION NOTES: +# - Provides mmWave presence (moving/still) plus PIR motion. +# - Provides environment sensors (BME280). +# - When mmWave presence/moving target or PIR triggers, a script publishes MQTT commands to a remote +# light controller (e.g. stair footer lights) for a configurable auto-on duration. +# - Auto control can be enabled/disabled with "Stair Footer Lights Auto". +# - Auto duration is controlled by "Stair Footer Lights Auto Time" (seconds). +# - LD2410 exposes configuration entities (numbers/selects/switches/buttons/text sensors). +#:########################################################################################:# +# MQTT COMMANDS: +# This device publishes MQTT commands to a remote device: +# - Topic: ${mqtt_remote_device1_command_topic} +# - Payloads: ${mqtt_remote_device_command_ON}, ${mqtt_remote_device_command_OFF} # -# https://esphome.io/components/sensor/ld2410.html -# https://www.simplysmart.house/blog/presence-detection-ld2410-home-assistant -# -# The B and C versions of this device can use Bluetooth, but we are not using it here. -########################################################################################## -########################################################################################## +# Example (as configured by substitutions): +# - ${mqtt_command_main_topic}/stair-footerlights -> ON, OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - mmWave/PIR and BME280 sensing continues locally. +# - Remote light control via MQTT publish continues (auto script still publishes). +# - HA entities are unavailable until HA returns. +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Sensing continues and HA API entities remain available. +# - Remote light control will NOT work (MQTT publishes fail while MQTT is down). +# c) Entire WiFi/Network OFFLINE +# - Sensing continues locally, but no HA API and no MQTT remote control. +# - SNTP is not needed (no timeclocks used). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-occupancystair" friendly_name: "Stair Occupancy and Underhouse Environment" - description_comment: "D1 Mini ESP32 with LD2410 mmWave for internal stairwell and environment sensors for under house" - device_area: "Underhouse" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "D1 Mini ESP32 with LD2410 mmWave for internal stairwell and environment sensors for under house (Layout V1.1)" + device_area: "Underhouse" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Generic.ESP32" # Project Details - project_version: "v2.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Generic.ESP32" + project_version: "v2.2" # 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 + api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-occupancystair_ip mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - #relay_icon: "mdi:lightbulb-group" - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc - + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc + # 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}/state" mqtt_remote_device_command_ON: "ON" mqtt_remote_device_command_OFF: "OFF" - -######################################################################################### + +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -61,6 +99,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -74,163 +113,102 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome CORE CONFIGURATION +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" # appears on the esphome page in HA + area: "${device_area}" min_version: 2024.6.0 - area: "${device_area}" - #on_boot: # Initial Setting, will remember previous values (if set) - #priority: -200 - #then: -########################################################################################## -# ESP PLATFORM AND FRAMEWORK -# https://esphome.io/components/esp8266.html +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: # https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# esp32: board: esp32dev framework: - type: esp-idf # "esp-idf" OR "arduino". Suggested ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. - version: recommended # recommended, latest or dev + type: esp-idf # "esp-idf" OR "arduino" + version: recommended -########################################################################################## -# GLOBAL VARIABLES +#:########################################################################################:# +# GLOBAL VARIABLES: # https://esphome.io/components/globals.html -########################################################################################## +#:########################################################################################:# globals: - id: stair_footer_auto_default_s type: int - restore_value: yes - initial_value: '20' + restore_value: true + initial_value: "20" -########################################################################################## -# i2c BUS COMPONENT +#:########################################################################################:# +# I2C BUS: # https://esphome.io/components/i2c.html -########################################################################################## +#:########################################################################################:# i2c: sda: GPIO19 scl: GPIO21 - scan: True - frequency: 100kHz #10, 50, 100, 200, 800 are possible settings, 100kHz was reliable for me + scan: true + frequency: 100kHz -########################################################################################## -# LOGGER COMPONENT +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -# Logs all log messages through the serial port and through MQTT topics. -########################################################################################## +#:########################################################################################:# logger: - level: INFO # INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 -########################################################################################## -# BLUETOOTH -# Proxy https://esphome.io/components/bluetooth_proxy.html -# BLE https://esphome.io/components/esp32_ble_tracker.html -# Remember that this takes a LOT of processing. On the -# ESP32, enable the IDF framework, and disable the -# Web server component. Changing to the IDF framework -# needs to be via cable not OTA to change the -# partition setup. -########################################################################################## -#bluetooth_proxy: - -#esp32_ble_tracker: - -########################################################################################## -# UART BUS -# hardware on EPS32, but software (and can be glitchy) on ESP8266 +#:########################################################################################:# +# UART: # https://esphome.io/components/uart.html -########################################################################################## +#:########################################################################################:# uart: id: ld2410_uart - rx_pin: GPIO16 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang - tx_pin: GPIO17 #For ESP32, you can use any pin, Recommend Use UART_2, Don't use UART_0, It might Cause Boot Fail or System Hang - baud_rate: 256000 # default for LD2410 is 25600, 8, 0, NONE + rx_pin: GPIO16 + tx_pin: GPIO17 + baud_rate: 256000 data_bits: 8 stop_bits: 1 parity: NONE -######################################################################################### -# STATUS LED +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -######################################################################################### -# ESP32 D1 Mini Board: Onboard Status LED on GPIO2, active-low -######################################################################################### +#:########################################################################################:# status_led: pin: - number: GPIO2 # ESP32 Onboard LED - ignore_strapping_warning: True #https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins + number: GPIO2 + ignore_strapping_warning: true inverted: false -########################################################################################## -# LD2410 Sensors +#:########################################################################################:# +# LD2410: # https://esphome.io/components/sensor/ld2410.html -# https://www.hlktech.net/index.php?id=988 -########################################################################################## +#:########################################################################################:# ld2410: uart_id: ld2410_uart - #uart_id (Optional, ID): Manually specify the ID of the UART Component if you want to use multiple UART buses. - #throttle (Optional, int): Time in milliseconds to control the rate of data updates. Defaults to 1000ms. - #id (Optional, ID): Manually specify the ID for this LD2410 Sensor component if you need multiple components. -# light (Optional, int): When in engineering mode, indicates the light sensitivity, otherwise unknown. Value between 0 and 255 inclusive. Though it seems that the value 85 is the lowest value at complete darkness. All options from Sensor. -# moving_distance (Optional, int): Distance in cm of detected moving target. All options from Sensor. -# still_distance (Optional, int): Distance in cm of detected still target. All options from Sensor. -# moving_energy (Optional, int): Energy for moving target. Value between 0 and 100 inclusive. All options from Sensor. -# still_energy (Optional, int): Energy for still target. Value between 0 and 100 inclusive. All options from Sensor. -# detection_distance (Optional, int): Distance in cm of target. All options from Sensor. -# gX (Optional): Energies for the Xth gate (X => 0 to 8). - # move_energy (Optional, int): When in engineering mode, the move energy of the gate, otherwise unknown. Value between 0 and 100 inclusive. All options from Sensor. - #still_energy (Optional, int): When in engineering mode, the still energy of the gate, otherwise unknown. Value between 0 and 100 inclusive. All options from Sensor. -#ld2410_id (Optional, ID): Manually specify the ID for the LD2410 Sensor component if you are using multiple components. - - -########################################################################################## -# NUMBER COMPONENT +#:########################################################################################:# +# NUMBER COMPONENT: # https://esphome.io/components/number/ -########################################################################################## -#The ld2410 number values for setting thresholds -# timeout: 5s -# max_move_distance: 2.25m -# max_still_distance: 2.25m -# g0_move_threshold: 40 # 0m / 0' -# g0_still_threshold: 10 # 0m / 0' -# g1_move_threshold: 40 # 0 - 0.75m / 0 - 2.46' -# g1_still_threshold: 10 # 0 - 0.75m / 0 - 2.46' -# g2_move_threshold: 40 # 0.75 - 1.5m / 2.46' - 4.92' -# g2_still_threshold: 10 # 0.75 - 1.5m / 2.46' - 4.92' -# g3_move_threshold: 40 # 1.5 - 2.25m / 4.92' - 7.38' -# g3_still_threshold: 10 # 1.5 - 2.25m / 4.92' - 7.38' -# g4_move_threshold: 40 # 2.25 - 3m' / 7.38' - 9.84' -# g4_still_threshold: 40 # 2.25 - 3m' / 7.38' - 9.84' -# g5_move_threshold: 40 # 3 - 3.75 / 9.84' - 12.30' -# g5_still_threshold: 40 # 3 - 3.75 / 9.84' - 12.30' -# g6_move_threshold: 30 # 3.75 - 4.5m / 12.30' - 14.76' -# g6_still_threshold: 15 # 3.75 - 4.5m / 12.30' - 14.76' -# g7_move_threshold: 30 # 4.5 - 5.25m / 14.76' - 17.22' -# g7_still_threshold: 15 # 4.5 - 5.25m / 14.76' - 17.22' -# g8_move_threshold: 30 # 5.25 - 6m / 17.22' - 19.68' -# g8_still_threshold: 15 # 5.25 - 6m / 17.22' - 19.68' +#:########################################################################################:# number: - platform: ld2410 timeout: @@ -290,7 +268,7 @@ number: - platform: template id: stair_footer_auto_time_s name: "Stair Footer Lights Auto Time" - unit_of_measurement: s + unit_of_measurement: "s" min_value: 10 max_value: 300 step: 1 @@ -298,26 +276,13 @@ number: restore_value: true initial_value: 20 -######################################################################################### -# SELECT COMPONENT +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -######################################################################################### -# LD2410 SELECT -# distance_resolution (Optional): Control the gates distance resolution. Can be 0.75m or 0.2m. -# Defaults to 0.75m. All options from Select. -# baud_rate (Optional): Control the serial port baud rate. Defaults to 256000. Once changed, -# all sensors will stop working until a fresh install with an updated UART Component -# configuration. All options from Select. -# light_function (Optional): If set, will affect the OUT pin value, based on light -# threshold. Can be off, low or above. Defaults to off. All options from Select. -# out_pin_level (Optional): Control OUT pin away value. Can be low or high. Defaults -# to low. All options from Select. -# ld2410_id (Optional, ID): Manually specify the ID for the LD2410 Sensor component -# if you are using multiple components. -######################################################################################### +#:########################################################################################:# select: - platform: ld2410 - distance_resolution: + distance_resolution: name: "${friendly_name} LD2140 Distance Resolution" baud_rate: name: "${friendly_name} LD2140 Baud Rate" @@ -326,28 +291,26 @@ select: out_pin_level: name: "${friendly_name} LD2140 Out Pin Level" -########################################################################################## -# SENSOR COMPONENT +#:########################################################################################:# +# SENSOR COMPONENT: # https://esphome.io/components/sensor/ -########################################################################################## +#:########################################################################################:# sensor: - platform: bme280_i2c temperature: name: "Temperature" - accuracy_decimals: 1 + accuracy_decimals: 1 oversampling: 2x pressure: name: "Pressure" oversampling: 2x humidity: name: "Humidity" - accuracy_decimals: 1 + accuracy_decimals: 1 oversampling: 2x address: 0x76 - update_interval: "${update_interval}" + update_interval: "${update_interval}" - # The ld2410 sensor values - # https://esphome.io/components/sensor/ld2410/#sensor - platform: ld2410 light: name: "Light" @@ -407,20 +370,16 @@ sensor: still_energy: name: "g8 still energy" -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## -# The ld2410 switch allows you to control your LD2410 Sensor. -# Bluetooth switch is only useful of you have a B or C model -########################################################################################## +#:########################################################################################:# switch: - # https://esphome.io/components/sensor/ld2410/#switch - platform: ld2410 engineering_mode: name: "${friendly_name} LD2140 Engineering Mode" #bluetooth: - #name: "${friendly_name} LD2140 Control Bluetooth" + # name: "${friendly_name} LD2140 Control Bluetooth" - platform: template id: stair_footer_auto_enabled @@ -428,13 +387,11 @@ switch: optimistic: true restore_mode: RESTORE_DEFAULT_ON -######################################################################################### -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -######################################################################################### +#:########################################################################################:# binary_sensor: - # The ld2410 binary sensors to get presence notification - # https://esphome.io/components/sensor/ld2410/#binary-sensor - platform: ld2410 has_target: name: "mmWave Presence" @@ -458,8 +415,7 @@ binary_sensor: name: "LD2140 Out Pin Presence Status" entity_category: diagnostic -# Generic PIR Sensor -# https://devices.esphome.io/devices/Generic-PIR + # Generic PIR Sensor (GPIO13) - platform: gpio pin: number: GPIO13 @@ -478,12 +434,10 @@ binary_sensor: then: - script.execute: stair_footer_auto_script -################################################################################################# -# BUTTON COMPONENT +#:########################################################################################:# +# BUTTON COMPONENT: # https://esphome.io/components/button/index.html -################################################################################################# -# The ld2410 button allows resetting -################################################################################################# +#:########################################################################################:# button: - platform: ld2410 factory_reset: @@ -493,27 +447,22 @@ button: query_params: name: "Query Parameters" -################################################################################################# -# TEXT SENSOR COMPONENT +#:########################################################################################:# +# TEXT SENSOR COMPONENT: # https://esphome.io/components/text_sensor/ -################################################################################################# +#:########################################################################################:# text_sensor: - # The ld2410 text sensor allows you to get information about your LD2410 Sensor. - # Bluetooth sensor is only useful of you have a B or C model - # https://esphome.io/components/sensor/ld2410/#text-sensor - platform: ld2410 version: name: "${friendly_name} LD2140 Firmware Version" #mac_address: - #name: "${friendly_name} LD2140 BT MAC Address" + # name: "${friendly_name} LD2140 BT MAC Address" -########################################################################################## -# SCRIPT COMPONENT +#:########################################################################################:# +# SCRIPT COMPONENT: # https://esphome.io/components/script.html -# Scripts can be executed nearly anywhere in your device configuration with a single call. -########################################################################################## +#:########################################################################################:# script: - # Sends commands to turn on and off a remote light - id: stair_footer_auto_script mode: restart then: @@ -524,10 +473,10 @@ script: retain: false # Wait for the HA-adjustable timeout - - delay: !lambda 'return (uint32_t)(id(stair_footer_auto_time_s).state) * 1000;' + - 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 + retain: false \ No newline at end of file diff --git a/esphome/esp-officelights.yaml b/esphome/esp-officelights.yaml index 553ecd5..e50911b 100644 --- a/esphome/esp-officelights.yaml +++ b/esphome/esp-officelights.yaml @@ -1,51 +1,78 @@ -############################################# -############################################# -# OFFICE MAIN LIGHTSWITCH -# V2.0 2025-06-05 YAML Tidyups -# V1.0 2025-05-31 Initial Version -############################################# -# Zemismart KS-811 Triple push button -# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# TITLE: OFFICE MAIN LIGHTSWITCH +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officelights.yaml +#:########################################################################################:# +# VERSIONS: +# v2.1 2026-02-25 Updated yaml to zorruno layout V1.1 +# v2.0 2025-06-05 YAML Tidyups +# v1.0 2025-05-31 Initial Version +#:########################################################################################:# +# HARDWARE: +# - Zemismart KS-811 Triple push button (ESP8266) +# - Pinout/Schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/ +#:########################################################################################:# +# OPERATION NOTES: +# - Office 3-gang KS-811 (Triple) wall switch. +# - Button 1 toggles Relay 1 (Nighttime Lights) - only relay actually wired to a load. +# - Button 2 toggles Relay 2 (Daytime Lights) - virtual only (no physical load connected). +# - Button 3 toggles Relay 3 (Spare) - virtual only (no physical load connected). +# - GPIO16 does not support interrupts; polling is used for Button 1. +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, WiFi OK +# - Physical buttons still control relays locally. +# - MQTT is optional; device operates as a normal switch without HA. # -# NOTES -# - +# b) MQTT OFFLINE (or broker unreachable) +# - Physical buttons still control relays locally. +# - HA/API control (if available) still works, but no MQTT command/status. # -############################################# -############################################# +# c) Entire WiFi/Network OFFLINE +# - Physical buttons still control relays locally. +# - Accurate time is NOT needed (SNTP not needed). +#:########################################################################################:# -############################################# -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS + +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -############################################# +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-officelights" friendly_name: "Office Main Lightswitch (3)" - description_comment: "Office Main Lightswitch using a Zemismart KS-811 Triple Push Button. Bunker Light A (1), Spare A (2), Spare B (3)" - device_area: "Office" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - - # Project Naming - project_name: "Zemismart Technologies.KS-811 Triple" # Project Details - project_version: "v2.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + description_comment: "Office Main Lightswitch using a Zemismart KS-811 Triple Push Button. Bunker Light A (1), Spare A (2), Spare B (3) (Layout V1.1)" + device_area: "Office" - # Passwords - api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + # Project Naming + project_name: "Zemismart Technologies.KS-811 Triple" + project_version: "v2.1" + + # Passwords & Secrets + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-officelights_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "INFO" + update_interval: "60s" # Switch Naming - switch_1_name: "Nighttime Lights" # Only one light (Bunker Light) actually connected to this relay - switch_2_name: "Daytime Lights" # This is virtual only, no power connected to 2nd relay - switch_3_name: "Spare" # This is virtual only, no power connected to 3rd relay + switch_1_name: "Nighttime Lights" # Only one light (Bunker Light) actually connected to this relay + switch_2_name: "Daytime Lights" # Virtual only, no power connected to 2nd relay + switch_3_name: "Spare" # Virtual only, no power connected to 3rd relay -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -54,6 +81,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -67,111 +95,112 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - - #### WEB PORTAL #### - #common_webportal: !include common/webportal_common.yaml - #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -############################################# -# ESPHome +#:########################################################################################:# +# ESPHOME # https://esphome.io/components/esphome.html -############################################# +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" project: name: "${project_name}" version: "${project_version}" -# on_boot: -# priority: 200 -# then: -# - switch.turn_on: Relay_3 + #on_boot: + # priority: 200 + # then: + # - switch.turn_on: relay_3 -############################################# -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -############################################# +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp01_1m - early_pin_init: False # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True. - board_flash_mode: dout # Default is dout + early_pin_init: false + board_flash_mode: dout -############################################# -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING # https://esphome.io/components/logger.html -############################################# +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - #baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + #baud_rate: 0 id: logger_id -############################################# +#:########################################################################################:# # STATUS LED # https://esphome.io/components/status_led.html -############################################# +#:########################################################################################:# status_led: pin: number: GPIO2 - inverted: yes + inverted: true -############################################# +#:########################################################################################:# # BINARY SENSORS # https://esphome.io/components/binary_sensor/ -############################################# +#:########################################################################################:# binary_sensor: + # Button 1 (GPIO16) - polling (GPIO16 has no interrupts) - platform: gpio pin: number: GPIO16 mode: INPUT - inverted: True - use_interrupt: False # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning. + inverted: true + use_interrupt: false name: "Button 1: ${switch_1_name}" on_press: - - switch.toggle: Relay_1 + - switch.toggle: relay_1 + # Button 2 (GPIO05) - platform: gpio pin: number: GPIO05 mode: INPUT - inverted: True + inverted: true name: "Button 2: ${switch_2_name}" on_press: - - switch.toggle: Relay_2 + - switch.toggle: relay_2 + # Button 3 (GPIO4) - platform: gpio pin: number: GPIO4 mode: INPUT - inverted: True + inverted: true name: "Button 3: ${switch_3_name}" on_press: - - switch.toggle: Relay_3 + - switch.toggle: relay_3 -############################################# -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH # https://esphome.io/components/switch/ -############################################# +#:########################################################################################:# switch: + # Relay 1 (GPIO13) - platform: gpio name: "Relay 1: ${switch_1_name}" pin: GPIO13 - id: Relay_1 + id: relay_1 + + # Relay 2 (GPIO12) - platform: gpio name: "Relay 2: ${switch_2_name}" pin: GPIO12 - id: Relay_2 + id: relay_2 + + # Relay 3 (GPIO14) - platform: gpio name: "Relay 3: ${switch_3_name}" pin: GPIO14 - id: Relay_3 \ No newline at end of file + id: relay_3 \ No newline at end of file diff --git a/esphome/esp-officeusbhubpower.yaml b/esphome/esp-officeusbhubpower.yaml index 38e89a0..3d3bd85 100644 --- a/esphome/esp-officeusbhubpower.yaml +++ b/esphome/esp-officeusbhubpower.yaml @@ -1,52 +1,90 @@ -############################################# -############################################# -# OFFICE USB HUB POWER -# Controlled by a Sonoff Basic R1 -# +#:########################################################################################:# +# TITLE: OFFICE USB HUB POWER +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-officeusbhubpower.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.0 2025-06-14 Initial Version +#:########################################################################################:# +# HARDWARE: +# Sonoff Basic R1 (ESP8266) +# - Relay: GPIO12 +# - Button: GPIO03 +# - Status LED: GPIO13 (active-low on many Sonoff variants) +#:########################################################################################:# +# OPERATION NOTES: +# - Simple power control for an office USB hub power supply. +# - Local button toggles the relay. +# - MQTT control is supported for ON/OFF. +#:########################################################################################:# +# MQTT COMMANDS: +# Command (set relay): +# - ${mqtt_command_topic}/relay1/set -> ON, OFF # -########################################################################################## -########################################################################################## +# Status (published from template sensor): +# - ${mqtt_status_topic}/relay1/state -> ON, OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device remains controllable via MQTT command topic +# - Status publishes still occur via MQTT +# - HA entities unavailable until HA returns +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable from Home Assistant via API (relay/button entities) +# - MQTT commands and status publishes will not work while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available +# - Local button control continues to work +# - Accurate time is NOT needed (SNTP not needed) +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-officeusbhubpower" friendly_name: "Office USB Hub Power" - description_comment: "Office USB Hub Power Supply control in the Office (On wall) :: Sonoff Basic" - device_area: "Office" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Office USB Hub Power Supply control in the Office (On wall) :: Sonoff Basic (Layout V1.1)" + device_area: "Office" # Project Naming - project_name: "Sonoff Technologies.Sonoff Basic V1" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - - # Passwords - api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names - ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names + project_name: "Sonoff Technologies.Sonoff Basic V1" + project_version: "v1.1" + + # Passwords & Secrets (Unfortunately, you cannot use substitutions inside secret names) + api_key: !secret esp-api_key + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-officeusbhubpower_ip + + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + + # MQTT Topics mqtt_command_main_topic: !secret mqtt_command_main_topic mqtt_status_main_topic: !secret mqtt_status_main_topic + mqtt_device_name: "office-usbhub-power" + mqtt_command_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" + mqtt_status_topic: "${mqtt_status_main_topic}/${mqtt_device_name}" # Device Settings relay_icon: "mdi:generator-portable" - log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "ERROR" + update_interval: "60s" - # Device Naming + # Entity Naming relay_1_name: "USB Hub Power Supply" button_1_name: "Power Button" - # MQTT Controls - mqtt_device_name: "office-usbhub-power" - mqtt_main_topic: "${mqtt_command_main_topic}/${mqtt_device_name}" # Topic we will use to command stuff from external without HA - -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -55,6 +93,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -68,80 +107,73 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" # Appears on the esphome page in HA + comment: "${description_comment}" area: "${device_area}" -# platformio_options: -# build_flags: -# - "-Os" # optimize for size -# - "-Wl,--gc-sections" # drop unused code/data -# - "-fno-exceptions" # strip C++ exceptions -# - "-fno-rtti" # strip C++ RTTI + project: + name: "${project_name}" + version: "${project_version}" -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: True # restore some values on reboot + board: esp01_1m + restore_from_flash: true preferences: flash_write_interval: 5min mdns: - disabled: False + disabled: false -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 -########################################################################################## -# SWITCH COMPONENT -# https://esphome.io/components/switch/ -########################################################################################## -# Sonoff Basic R1 Relay Switch is GPIO12 -############################################# +#:########################################################################################:# +# SWITCH: +# Sonoff Basic R1 Relay Switch is GPIO12 +# https://esphome.io/components/switch/gpio.html +#:########################################################################################:# switch: - platform: gpio name: "${relay_1_name}" pin: GPIO12 id: relay1 restore_mode: RESTORE_DEFAULT_ON - icon: "${relay_icon}" + icon: "${relay_icon}" -########################################################################################## -# BINARY SENSORS -# https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# +# BINARY SENSORS: # Sonoff Basic R1 Button is GPIO03 -############################################# +# https://esphome.io/components/binary_sensor/gpio.html +#:########################################################################################:# binary_sensor: - - platform: gpio pin: number: GPIO03 @@ -157,51 +189,50 @@ binary_sensor: then: - lambda: |- if (id(relay1).state) { - // Relay is ON: turn it OFF id(relay1).turn_off(); } else { - // Relay is OFF: turn it ON id(relay1).turn_on(); } - - # Mimics actual relay status (but not controllable) + + # Mimics actual relay status (not directly controllable) - platform: template name: "${relay_1_name} Status" lambda: |- return id(relay1).state; on_press: - mqtt.publish: - topic: "${mqtt_topic}/relay1/state" - payload: "ON" + topic: "${mqtt_status_topic}/relay1/state" + payload: "ON" + retain: false on_release: - mqtt.publish: - topic: "${mqtt_topic}/relay1/state" - payload: "OFF" - -########################################################################################## -# STATUS LED + topic: "${mqtt_status_topic}/relay1/state" + payload: "OFF" + retain: false + +#:########################################################################################:# +# STATUS LED: +# Sonoff Basic R1 LED is GPIO13 # https://esphome.io/components/status_led.html -########################################################################################## -# Sonoff Basic R1 LED is GPIO13 -############################################# +#:########################################################################################:# status_led: pin: number: GPIO13 - inverted: yes + inverted: true -########################################################################################## -# MQTT COMMANDS -# This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# +# MQTT: +# Device-specific MQTT command triggers (in addition to common MQTT config) +# https://esphome.io/components/mqtt.html +#:########################################################################################:# mqtt: on_message: - # Relay 1 control - - topic: "${mqtt_main_topic}/relay1/set" + - topic: "${mqtt_command_topic}/relay1/set" payload: "ON" then: - switch.turn_on: relay1 - - topic: "${mqtt_main_topic}/relay1/set" + + - topic: "${mqtt_command_topic}/relay1/set" payload: "OFF" then: - - switch.turn_off: relay1 - + - switch.turn_off: relay1 \ No newline at end of file diff --git a/esphome/esp-poollightpower2.yaml b/esphome/esp-poollightpower2.yaml index 1d382bb..8ee6e6e 100644 --- a/esphome/esp-poollightpower2.yaml +++ b/esphome/esp-poollightpower2.yaml @@ -1,9 +1,13 @@ -########################################################################################## -########################################################################################## -# POOL LIGHT POWER AND TIMER 2 -# Controlled by a Athom Smart Plug V2 -# -# v4.0 2026-01-31 Added Morning/Evening Timer Enable switches (gate timer windows) +#:########################################################################################:# +# TITLE: POOL LIGHT POWER AND TIMER 2 +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-poollightpower2.yaml +#:########################################################################################:# +# VERSIONS: +# V4.1 2026-02-25 Updated yaml to zorruno layout V1.1 +# V4.0 2026-01-31 Added Morning/Evening Timer Enable switches (gate timer windows) # V3.0 2025-09-02 Pool Light mode controller fixes; Mode select forces Operation=ON; # added Mode 0=OFF; select shows OFF when relay off; enforce 7s min OFF window # V2.4 2025-06-15 Changed back to an Athom V1 (esp8266) @@ -11,74 +15,73 @@ # V2.2 2025-06-14 Fixes to offline time when sntp/network unavailable # V2.1 2025-06-12 Added select and button to chose modes, added countdown & startup to boost # V2.0 2025-06-05 YAML Tidyups -# -# INSTRUCTIONS -# - It allows the device to work in a standalone timer style operation -# - The timer has a morning and evening time (but no weekday/weekend settings) -# - Morning Timer Enable / Evening Timer Enable switches gate their timer windows (default ON and restored on reboot) -# - Pool Light Mode can be set via the "Pool Light Mode" dropdown; selecting a mode forces Operation Mode = ON, and selecting "0=OFF" turns the relay OFF and returns Operation Mode to TIMER -# - Default values are set, but changed values are remembered in flash -# - It uses SNTP for time setting (but obviously only if wifi & networking are working) -# - It will default to an internal timer if no wifi. To reset internal timer, reboot the device at 12pm (noon) -# - If on a network and there is a MQTT server, you can set the on/off times via MQTT (See below commands) -# - You can set 4 modes ON/OFF/TIMER/BOOST via MQTT. Setting BOOST gives you a oneshot operation -# - Any new timer times set via MQTT will be remembered though a reboot -# - On startup, or a reboot, the device will always turn on for the BOOST Duration (BOOST mode, default 2 hours) -# - TIMER mode will always be switched on after BOOST mode is complete -# - Home Assistant entities are set so that BOOST mode can be pressed with a button and other modes selectable with a dropdown -# - If you need it ON continuously with no MQTT, toggle power ON/OFF 4 times within 30 seconds (with ~2 secs in between to allow it to boot) -# -# MQTT Commands -# Values will be set in place on the update_interval time, not immediately -# Use 00:00 in 24hr format for time setting. (Note there is no weekday/weekend setting) -# mqtt_timer_topic/morning-on/06:00 : Time device will go on -# mqtt_timer_topic/morning-off/08:00 : Time device will go off -# mqtt_timer_topic/evening-on/09:00 : Time device will go on -# mqtt_timer_topic/evening-off/00:00 : Time device will go off -# mqtt_timer_topic/boost-time/0000 : Time in minutes device will temporarily go on for (1-1439) -# mqtt_timer_topic/operation/ON : Device permanently on -# mqtt_timer_topic/operation/OFF : Device permanently off -# mqtt_timer_topic/operation/TIMER : Device will obey timer settings -# mqtt_timer_topic/operation/BOOST : Turn on for (boost_duration) minutes then BOOST (also on startup) -# -# operation_mode: -# 0 = OFF -# 1 = ON -# 2 = TIMER -# 3 = BOOST -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# Athom Smart Plug V2 (ESP8285) - used as pool light power controller +#:########################################################################################:# +# OPERATION NOTES: +# - Standalone timer style operation with morning/evening windows (no weekday/weekend settings) +# - Morning Timer Enable / Evening Timer Enable switches gate their timer windows (default ON and restored) +# - Uses SNTP for accurate time when available; falls back to an internal timer if offline +# - To reset internal timer when offline, reboot the device at 12pm (midday) +# - Pool Light Mode can be set via the "Pool Light Mode" dropdown: +# - Selecting a mode forces Operation Mode = ON +# - Selecting "0=OFF" turns relay OFF and returns Operation Mode to TIMER +# - If on a network and MQTT is available, on/off times and modes can be set via MQTT (see MQTT COMMANDS) +#:########################################################################################:# +# MQTT COMMANDS: +# Values are applied on update_interval (not immediately). Use HH:MM (24h). +# - ${mqtt_timer_topic}/morning-on payload "06:00" +# - ${mqtt_timer_topic}/morning-off payload "08:00" +# - ${mqtt_timer_topic}/evening-on payload "21:00" +# - ${mqtt_timer_topic}/evening-off payload "00:00" +# - ${mqtt_timer_topic}/boost-time payload "0000" (minutes 1-1439) +# - ${mqtt_timer_topic}/operation payload "ON","OFF","TIMER","BOOST" +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device remains controllable via MQTT (timeclock updates and operation mode) +# - Device continues running timer/mode logic locally +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable from Home Assistant via API (selects/buttons/switches) +# - MQTT timeclock updates and mode commands will not work while MQTT is down +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available +# - Device continues operating using last saved settings +# - Loss of network will drift the timeclocks; time of day can be reset by powering off then on again at 12pm (midday) +#:########################################################################################:# - - -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-poollightpower2" friendly_name: "Pool Light Power" - description_comment: "Pool Light Power :: Athom Smart Plug Power V2" + description_comment: "Pool Light Power :: Athom Smart Plug Power V2 (Layout V1.1)" device_area: "Outside" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming project_name: "Athom Technology.Smart Plug V2" # Project Details - project_version: "v3.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_version: "v4.1" # Project version denotes release of yaml file, allowing checking of deployed vs latest version # Passwords api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-poollightpower2_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings log_level: "DEBUG" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc # Device Settings relay_icon: "mdi:power-socket-au" - current_limit : "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. + current_limit: "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. mqtt_timer_topic: "viewroad-commands/poollight-timer" # Topics you will use to change stuff boost_duration_default: "180" # Minutes to stay ON in BOOST mode before reverting to TIMER morning_on_default: "450" # Default in minutes from midnight. Default 07:30 => 450 @@ -98,10 +101,10 @@ substitutions: # Ignored modes bitmask: bit (mode_index-1). For 4 and 5 ignored -> (1<<3)|(1<<4) = 24. ignored_modes_mask: "8288" # Ignore 6(32), 7(64), 14(8192) :: 32 + 64 + 8192 = 8288 -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: ################################################## # MANDATORY packages (won't compile without them!) @@ -114,6 +117,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" ################################################## # OPTIONAL packages (comment if you don't want them) @@ -164,16 +168,16 @@ packages: relay_restore_mode: "RESTORE_DEFAULT_OFF" # matches what you already use power_plug_type: "${relay_icon}" # e.g. "mdi:power-socket-au" -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" #Appears on the esphome page in HA area: "${device_area}" - name_add_mac_suffix: False + name_add_mac_suffix: false min_version: 2024.6.0 project: name: "${project_name}" @@ -189,10 +193,10 @@ esphome: # - -fno-exceptions # - -fno-rtti -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266.html +#:########################################################################################:# esp8266: board: esp8285 restore_from_flash: true # mainly for calculating cumulative energy, but not that important here @@ -203,22 +207,22 @@ preferences: flash_write_interval: 10min mdns: - disabled: False # binary size saving + disabled: false # binary size saving -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" # INFO Level suggested, or DEBUG for testing + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) #esp8266_store_log_strings_in_flash: false #tx_buffer_size: 64 -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## +#:########################################################################################:# switch: #################################################### # Timer Enable Switches @@ -247,12 +251,11 @@ switch: on_turn_off: - script.execute: evaluate_relay_state -########################################################################################## -# Global Variables for use in automations etc -# https://esphome.io/guides/automations.html?highlight=globals#global-variables -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/components/globals.html +#:########################################################################################:# globals: - # Tracks the time (in seconds from midnight) at the previous boot - id: last_boot_time_s type: int @@ -355,7 +358,7 @@ globals: restore_value: false initial_value: "1" - # Bitmask of ignored modes (1..max_modes). Example: ignore 4 & 5 -> 24. + # Bitmask of ignored modes (1..max_modes). Example: ignore 4 and 5 -> 24. - id: ignored_mask type: int restore_value: false @@ -367,15 +370,14 @@ globals: restore_value: false initial_value: "false" -########################################################################################## -# Text Sensors +#:########################################################################################:# +# TEXT SENSOR COMPONENT: # https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# text_sensor: - -############################ -# MQTT Subscriptions -############################ + ############################ + # MQTT Subscriptions + ############################ #################################################### # Subscribe to the Morning On time, format "HH:MM" #################################################### @@ -396,6 +398,7 @@ text_sensor: } else { ESP_LOGW("timer","Invalid Morning On format: %s", x.c_str()); } + #################################################### # Morning Off time => "HH:MM" #################################################### @@ -415,6 +418,7 @@ text_sensor: } else { ESP_LOGW("timer","Invalid Morning Off format: %s", x.c_str()); } + #################################################### # Evening On time => "HH:MM" #################################################### @@ -434,6 +438,7 @@ text_sensor: } else { ESP_LOGW("timer","Invalid Evening On format: %s", x.c_str()); } + #################################################### # Evening Off time => "HH:MM" #################################################### @@ -453,6 +458,7 @@ text_sensor: } else { ESP_LOGW("timer","Invalid Evening Off format: %s", x.c_str()); } + #################################################### # Boost duration => 1 - 1439 #################################################### @@ -577,10 +583,10 @@ text_sensor: return { std::string(buff) }; update_interval: "${update_interval}" -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: template id: relay_status @@ -613,10 +619,10 @@ binary_sensor: id(last_off_ms) = millis(); if (!id(mode_changing)) id(current_mode) = 0; -########################################################################################## -# Sensors -# https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# +# SENSOR COMPONENT: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: template name: "Timeclock: Boost Duration" @@ -663,10 +669,10 @@ sensor: // never return negative return rem > 0 ? rem : 0; -################################################################################################# -# BUTTON COMPONENT +#:########################################################################################:# +# BUTTON COMPONENT: # https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# button: - platform: template name: "Boost now" @@ -701,10 +707,10 @@ button: - switch.turn_on: evening_timer_enable - script.execute: evaluate_relay_state -################################################################################################# -# SELECT COMPONENT +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -################################################################################################# +#:########################################################################################:# select: - platform: template name: "Operation Mode" @@ -725,7 +731,7 @@ select: default: return std::string("OFF"); } - # when changed in HA, set mode & re-evaluate + # when changed in HA, set mode and re-evaluate set_action: - lambda: |- if (x == "OFF") { id(operation_mode) = 0; } @@ -859,10 +865,10 @@ select: else: - script.execute: change_to_desired_mode -################################################################################################# -# SCRIPT COMPONENT +#:########################################################################################:# +# SCRIPT COMPONENT: # https://esphome.io/components/script.html -################################################################################################# +#:########################################################################################:# script: # Core: evaluate and drive the relay (with enforced min OFF window) - id: evaluate_relay_state @@ -1013,10 +1019,10 @@ script: - lambda: |- id(mode_changing) = false; -################################################################################################# -# INTERVAL COMPONENT +#:########################################################################################:# +# INTERVAL COMPONENT: # https://esphome.io/components/interval.html -################################################################################################# +#:########################################################################################:# # Interval: bumps time (even if no SNTP), then calls the script to evaluate relay state interval: - interval: "1min" @@ -1039,4 +1045,4 @@ interval: //id(mqtt_client).publish("${mqtt_timer_topic}/operation", "TIMER"); } } - - script.execute: evaluate_relay_state + - script.execute: evaluate_relay_state \ No newline at end of file diff --git a/esphome/esp-poolpumppower.yaml b/esphome/esp-poolpumppower.yaml index cfa7b5c..1193dcf 100644 --- a/esphome/esp-poolpumppower.yaml +++ b/esphome/esp-poolpumppower.yaml @@ -1,92 +1,102 @@ -########################################################################################## -########################################################################################## -# POOL PUMP POWER AND TIMER -# Controlled by a Athom Smart Plug V3 -# -# dashboard_import: -# package_import_url: github://athom-tech/esp32-configs/athom-smart-plug.yaml -# +#:########################################################################################:# +# TITLE: POOL PUMP POWER AND TIMER +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-poolpumppower.yaml +#:########################################################################################:# +# VERSIONS: +# V2.5 2026-02-25 Updated yaml to zorruno layout V1.1 # V2.4 2026-01-31 Added Morning/Evening Timer Enable switches (gate timer windows) # V2.3 2025-06-19 Minor changes to remember mode in reboot and to ensure offline functionality # V2.2 2025-06-14 Fixes to offline time when sntp/network unavailable -# V2.1 2025-06-12 Added select and button to chose modes, added countdown & startup to boost +# V2.1 2025-06-12 Added select and button to chose modes, added countdown and startup to boost # V2.0 2025-06-05 YAML Tidyups -# -# INSTRUCTIONS -# - It allows the device to work in a standalone timer style operation -# - The timer has a morning and evening time (but no weekday/weekend settings) -# - Morning Timer Enable / Evening Timer Enable switches gate their timer windows (default ON and restored on reboot) -# - Default values are set, but changed values are remembered in flash -# - It uses SNTP for time setting (but obviously only if wifi & networking are working) -# - It will default to an internal timer if no wifi. To reset internal timer, reboot the device at 12pm (noon) -# - If on a network and there is a MQTT server, you can set the on/off times via MQTT (See below commands) -# - You can set 4 modes ON/OFF/TIMER/BOOST via MQTT. Setting BOOST gives you a oneshot operation -# - Any new timer times set via MQTT will be remembered though a reboot -# - On startup, or a reboot, the device will always turn on for the BOOST Duration (BOOST mode, default 2 hours) -# - TIMER mode will always be switched on after BOOST mode is complete -# - Home Assistant entities are set so that BOOST mode can be pressed with a button and other modes selectable with a dropdown -# - If you need it ON continuously with no MQTT, toggle power ON/OFF 4 times within 30 seconds (with ~2 secs in between to allow it to boot) -# -# MQTT Commands -# Values will be set in place on the update_interval time, not immediately -# Use 00:00 in 24hr format for time setting. (Note there is no weekday/weekend setting) -# mqtt_timer_topic/morning-on/06:00 : Time device will go on -# mqtt_timer_topic/morning-off/08:00 : Time device will go off -# mqtt_timer_topic/evening-on/09:00 : Time device will go on -# mqtt_timer_topic/evening-off/00:00 : Time device will go off -# mqtt_timer_topic/boost-time/0000 : Time in minutes device will temporarily go on for (1-1439) -# mqtt_timer_topic/operation/ON : Device permanently on -# mqtt_timer_topic/operation/OFF : Device permanently off -# mqtt_timer_topic/operation/TIMER : Device will obey timer settings -# mqtt_timer_topic/operation/BOOST : Turn on for (boost_duration) minutes then BOOST (also on startup) +#:########################################################################################:# +# HARDWARE: +# - Athom Smart Plug V3 (ESP32-C3) controlling pool pump relay + power monitoring +# - dashboard_import: github://athom-tech/esp32-configs/athom-smart-plug.yaml +#:########################################################################################:# +# OPERATION NOTES: +# - Standalone timer style operation (morning and evening windows, no weekday/weekend). +# - Morning Timer Enable / Evening Timer Enable switches gate their timer windows (default ON). +# - Default values are set, but changed values are remembered in flash. +# - Uses SNTP for accurate time when WiFi/networking is available. +# - If on a network and MQTT is available, you can set on/off times and operation mode via MQTT. +# - Operation modes: OFF / ON / TIMER / BOOST. BOOST is a oneshot that reverts back to TIMER. +# - On startup or reboot, the device enters BOOST for the configured BOOST duration, then returns to TIMER. +#:########################################################################################:# +# MQTT COMMANDS: +# Values are applied on the update_interval, not instantly. +# Use 00:00 in 24hr format for time settings. +# ${mqtt_timer_topic}/morning-on payload "HH:MM" +# ${mqtt_timer_topic}/morning-off payload "HH:MM" +# ${mqtt_timer_topic}/evening-on payload "HH:MM" +# ${mqtt_timer_topic}/evening-off payload "HH:MM" +# ${mqtt_timer_topic}/boost-time payload "0".."1439" (minutes) +# ${mqtt_timer_topic}/operation payload "ON","OFF","TIMER","BOOST" # # operation_mode: # 0 = OFF # 1 = ON # 2 = TIMER # 3 = BOOST -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Timer logic continues to run on the device. +# - MQTT commands for schedule/mode updates still work. +# b) MQTT OFFLINE (or HA/MQTT OFFLINE) +# - If HA API is available, device can still be controlled from HA. +# - Without MQTT, schedule/mode changes via MQTT will not work. +# c) Entire WiFi/Network OFFLINE +# - No HA API and no MQTT control available. +# - Timer mode continues using the fallback clock. +# - Loss of network will drift the timeclocks; time of day can be reset by powering off then on again at 12pm (midday). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-poolpumppower" friendly_name: "Pool Pump Power" - description_comment: "Pool Pump Power :: Athom Smart Plug Power V3" - device_area: "Outside" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Pool Pump Power :: Athom Smart Plug Power V3 (Layout V1.1)" + device_area: "Outside" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Athom Technology.Smart Plug V3" # Project Details - project_version: "v2.4" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + project_name: "Athom Technology.Smart Plug V3" + project_version: "v2.5" # Updated yaml to zorruno layout V1.1 # Passwords api_key: !secret esp-poolpumppower_api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-poolpumppower_ota_pass # unfortunately you can't use substitutions inside secrets names static_ip_address: !secret esp-poolpumppower_ip - # Device Settings - log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "20s" # update time for for general sensors etc + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} # Device Settings + log_level: "INFO" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "20s" # update time for general sensors etc + + # Timer Settings relay_icon: "mdi:pool" - current_limit: "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. - mqtt_timer_topic: "viewroad-commands/poolpump-timer" # Topics you will use to change stuff - boost_duration_default: "60" # Minutes to stay ON in STARTUP mode before reverting to TIMER - morning_on_default: "450" # Default in minutes from midnight. Default 07:30 => 450 - morning_off_default: "450" # Default in minutes from midnight. Default 07:30 => 450 (same as ON as no need for morning schedule) - evening_on_default: "1260" # Default in minutes from midnight. Default 21:00 => 1260 - evening_off_default: "1350" # Default in minutes from midnight. Default 22:30 => 1350 => 1440 is midnight + current_limit: "10" # Current limit in amps. AU plug = 10. IL, BR, EU, UK, US plug = 16. + mqtt_timer_topic: "viewroad-commands/poolpump-timer" + boost_duration_default: "60" # minutes to stay ON in BOOST mode before reverting to TIMER + morning_on_default: "450" # 07:30 => 450 + morning_off_default: "450" # 07:30 => 450 (same as ON, no morning schedule) + evening_on_default: "1260" # 21:00 => 1260 + evening_off_default: "1350" # 22:30 => 1350 -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -95,6 +105,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -111,6 +122,7 @@ packages: #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### common_sntp: !include common/sntp_common.yaml @@ -120,20 +132,20 @@ packages: diag_debug: !include common/include_debug_diag_sensors.yaml diag_resetcount: !include common/include_resetcount_diag_sensors.yaml - # Device Specific included packages + #### Device Specific included packages #### common_athompowermonV3: !include file: common/athompowermonv3_common.yaml vars: local_current_limit: "${current_limit}" -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" #Appears on the esphome page in HA + comment: "${description_comment}" # Appears on the esphome page in HA area: "${device_area}" name_add_mac_suffix: false min_version: 2024.6.0 @@ -148,17 +160,17 @@ esphome: then: - script.execute: evaluate_relay_state -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp32/ +#:########################################################################################:# esp32: board: esp32-c3-devkitm-1 flash_size: 4MB variant: ESP32C3 framework: - type: esp-idf # "esp-idf" OR "arduino". Suggested ESP-IDF Framework, or Plug Out the UART Cable Might Cause ESP32 Hang. - version: recommended # recommended, latest or dev + type: esp-idf + version: recommended preferences: flash_write_interval: 5min @@ -166,22 +178,19 @@ preferences: esp32_improv: authorizer: none -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 -########################################################################################## -# Global Variables for use in automations etc -# https://esphome.io/guides/automations.html?highlight=globals#global-variables -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/guides/automations.html#global-variables +#:########################################################################################:# globals: - # Tracks the time (in seconds from midnight) at the previous boot - id: last_boot_time_s type: int @@ -194,31 +203,31 @@ globals: restore_value: true initial_value: "0" - # Morning On time (minutes from midnight), + # Morning On time (minutes from midnight) - id: morning_on type: int restore_value: true initial_value: "${morning_on_default}" - # Morning Off time (minutes from midnight), + # Morning Off time (minutes from midnight) - id: morning_off type: int restore_value: true initial_value: "${morning_off_default}" - # Evening On time (minutes from midnight), + # Evening On time (minutes from midnight) - id: evening_on type: int restore_value: true initial_value: "${evening_on_default}" - # Evening Off time (minutes from midnight), + # Evening Off time (minutes from midnight) - id: evening_off type: int restore_value: true initial_value: "${evening_off_default}" - # Boost Duration (minutes), + # Boost Duration (minutes) - id: boost_duration type: int restore_value: true @@ -226,10 +235,10 @@ globals: #################################################### # operation_mode: - # 0 = OFF - # 1 = ON - # 2 = TIMER - # 3 = BOOST + # 0 = OFF + # 1 = ON + # 2 = TIMER + # 3 = BOOST #################################################### - id: operation_mode type: int @@ -245,52 +254,41 @@ globals: restore_value: true initial_value: "0" -########################################################################################## -# Text Sensors +#:########################################################################################:# +# TEXT SENSOR: # https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# text_sensor: - -############################ -# MQTT Subscriptions -############################ - #################################################### - # Subscribe to the Morning On time, format "HH:MM" - # We check x.size() == 5 and x[2] == ':', - # then parse x.substr(0,2) and x.substr(3,2) - # std::string uses 'substr', not 'substring'. - #################################################### + ############################ + # MQTT Subscriptions + ############################ - platform: mqtt_subscribe name: "Morning On Time Setting" id: morning_on_topic - topic: "${mqtt_timer_topic}/morning-on" # Stored in the format HH:MM + topic: "${mqtt_timer_topic}/morning-on" internal: true on_value: then: - lambda: |- - // Expect "HH:MM" => total length = 5, with ':' if (x.size() == 5 && x[2] == ':') { - int hour = atoi(x.substr(0, 2).c_str()); // "HH" - int minute = atoi(x.substr(3, 2).c_str()); // "MM" + int hour = atoi(x.substr(0, 2).c_str()); + int minute = atoi(x.substr(3, 2).c_str()); id(morning_on) = hour * 60 + minute; ESP_LOGI("timer","Received new Morning On: %02d:%02d", hour, minute); } else { ESP_LOGW("timer","Invalid Morning On format: %s", x.c_str()); } - #################################################### - # Morning Off time => "HH:MM" - #################################################### - platform: mqtt_subscribe name: "Morning Off Time Setting" id: morning_off_topic - topic: "${mqtt_timer_topic}/morning-off" # Stored in the format HH:MM - internal: true # No need to show this in Home Assistant as there is a sensor that shows the set value + topic: "${mqtt_timer_topic}/morning-off" + internal: true on_value: then: - lambda: |- if (x.size() == 5 && x[2] == ':') { - int hour = atoi(x.substr(0, 2).c_str()); + int hour = atoi(x.substr(0, 2).c_str()); int minute = atoi(x.substr(3, 2).c_str()); id(morning_off) = hour * 60 + minute; ESP_LOGI("timer","Received new Morning Off: %02d:%02d", hour, minute); @@ -298,19 +296,16 @@ text_sensor: ESP_LOGW("timer","Invalid Morning Off format: %s", x.c_str()); } - #################################################### - # Evening On time => "HH:MM" - #################################################### - platform: mqtt_subscribe name: "Evening On Time Setting" id: evening_on_topic - topic: "${mqtt_timer_topic}/evening-on" # Stored in the format HH:MM - internal: true # No need to show this in Home Assistant as there is a sensor that shows the set value + topic: "${mqtt_timer_topic}/evening-on" + internal: true on_value: then: - lambda: |- if (x.size() == 5 && x[2] == ':') { - int hour = atoi(x.substr(0, 2).c_str()); + int hour = atoi(x.substr(0, 2).c_str()); int minute = atoi(x.substr(3, 2).c_str()); id(evening_on) = hour * 60 + minute; ESP_LOGI("timer","Received new Evening On: %02d:%02d", hour, minute); @@ -318,19 +313,16 @@ text_sensor: ESP_LOGW("timer","Invalid Evening On format: %s", x.c_str()); } - #################################################### - # Evening Off time => "HH:MM" - #################################################### - platform: mqtt_subscribe name: "Evening Off Time Setting" id: evening_off_topic - topic: "${mqtt_timer_topic}/evening-off" # Stored in the format HH:MM - internal: true # No need to show this in Home Assistant as there is a sensor that shows the set value + topic: "${mqtt_timer_topic}/evening-off" + internal: true on_value: then: - lambda: |- if (x.size() == 5 && x[2] == ':') { - int hour = atoi(x.substr(0, 2).c_str()); + int hour = atoi(x.substr(0, 2).c_str()); int minute = atoi(x.substr(3, 2).c_str()); id(evening_off) = hour * 60 + minute; ESP_LOGI("timer","Received new Evening Off: %02d:%02d", hour, minute); @@ -338,37 +330,26 @@ text_sensor: ESP_LOGW("timer","Invalid Evening Off format: %s", x.c_str()); } - #################################################### - # Boost duration => 1 - 1439 - #################################################### - platform: mqtt_subscribe name: "Boost Duration" id: boost_time_topic - topic: "${mqtt_timer_topic}/boost-time" # Stored as an integer from 1-1439 - internal: true # No need to show this in Home Assistant as there is a sensor that shows the set value + topic: "${mqtt_timer_topic}/boost-time" + internal: true on_value: then: - lambda: |- - // parse as integer char *endptr; long v = strtol(x.c_str(), &endptr, 10); - - // invalid if nothing parsed, trailing chars, or out of 0-1439 if (endptr == x.c_str() || *endptr != '\0' || v < 0 || v > 1439) { ESP_LOGE("boost_time", "Invalid boost_time '%s'", x.c_str()); } else { - id(boost_duration) = static_cast(v); + id(boost_duration) = (int) v; } - #################################################### - # Subscribe to operation mode: - # OFF, ON, TIMER, BOOST - # We do case-insensitive compare using strcasecmp - #################################################### - platform: mqtt_subscribe id: timer_operation_mode_topic topic: "${mqtt_timer_topic}/operation" - internal: true # No need to show this in Home Assistant as there is a sensor that shows the set value + internal: true on_value: then: - lambda: |- @@ -390,13 +371,9 @@ text_sensor: } - script.execute: evaluate_relay_state - ###################################################### - # Expose the current operation mode (OFF, ON, TIMER, BOOST) - ###################################################### - platform: template name: "Operation Mode State" lambda: |- - // 0=OFF, 1=ON, 2=TIMER, 3=BOOST switch (id(operation_mode)) { case 0: return {"OFF"}; case 1: return {"ON"}; @@ -406,9 +383,6 @@ text_sensor: } update_interval: 5s - ###################################################### - # Expose the "Morning On" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Morning On Time" lambda: |- @@ -419,9 +393,6 @@ text_sensor: return { std::string(buff) }; update_interval: "${update_interval}" - ###################################################### - # Expose the "Morning Off" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Morning Off Time" lambda: |- @@ -432,9 +403,6 @@ text_sensor: return { std::string(buff) }; update_interval: "${update_interval}" - ###################################################### - # Expose the "Evening On" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Evening On Time" lambda: |- @@ -445,9 +413,6 @@ text_sensor: return { std::string(buff) }; update_interval: "${update_interval}" - ###################################################### - # Expose the "Evening Off" time as a text (HH:MM) - ###################################################### - platform: template name: "Timeclock: Evening Off Time" lambda: |- @@ -458,10 +423,10 @@ text_sensor: return { std::string(buff) }; update_interval: "${update_interval}" -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## +#:########################################################################################:# binary_sensor: - platform: gpio pin: @@ -478,11 +443,9 @@ binary_sensor: then: - lambda: |- if (id(relay).state) { - // Relay is ON: turn it OFF and set mode to 2 (TIMER) id(relay).turn_off(); id(operation_mode) = 2; } else { - // Relay is OFF: turn it ON and set mode to 3 (BOOST) id(relay).turn_on(); id(operation_mode) = 3; } @@ -492,16 +455,16 @@ binary_sensor: lambda: |- return id(relay).state; -########################################################################################## -# Sensors -# https://esphome.io/components/text_sensor/index.html -########################################################################################## +#:########################################################################################:# +# SENSORS: +# https://esphome.io/components/sensor/ +#:########################################################################################:# sensor: - platform: template name: "Timeclock: Boost Duration" id: boost_duration_time unit_of_measurement: "mins" - accuracy_decimals: "0" + accuracy_decimals: 0 update_interval: "${update_interval}" lambda: |- return id(boost_duration); @@ -510,30 +473,24 @@ sensor: name: "Mins from Midnight" id: mins_from_midnight unit_of_measurement: "mins" - accuracy_decimals: "0" + accuracy_decimals: 0 update_interval: "${update_interval}" - internal: true # No need to show this in Home Assistant + internal: true lambda: |- return id(current_mins); - # A value in mins if a timer is running showing how many mins left - platform: template name: "Timer Minutes Remaining" id: timer_minutes_remaining - unit_of_measurement: "Mins" + unit_of_measurement: "mins" update_interval: 5s - accuracy_decimals: "0" + accuracy_decimals: 0 lambda: |- - // always zero if relay is off - if (!id(relay).state) { - return 0; - } + if (!id(relay).state) return 0; int rem = 0; - // only calculate for mode 2 (scheduled) or mode 3 (BOOST) if (id(operation_mode) == 2) { - // Only report remaining time for the currently-active enabled window if (id(morning_timer_enable).state && id(current_mins) >= id(morning_on) && id(current_mins) < id(morning_off)) { rem = id(morning_off) - id(current_mins); @@ -547,26 +504,21 @@ sensor: rem = id(boost_duration) - id(boost_timer); } - // never return negative return rem > 0 ? rem : 0; -################################################################################################# -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -################################################################################################# +#:########################################################################################:# switch: - platform: gpio name: "Power Output" pin: GPIO5 id: relay - restore_mode: RESTORE_DEFAULT_OFF # Ensures the relay is restored (or off) at boot - #internal: true # Hides the switch from Home Assistant + restore_mode: RESTORE_DEFAULT_OFF icon: "${relay_icon}" - ################################################################################################# - # TIMER ENABLE SWITCHES (gate the schedule windows) - # These default ON, and restore as ON at reboot (unless changed). - ################################################################################################# + # Timer Enable Switches (gate schedule windows) - platform: template name: "Morning Timer Enable" id: morning_timer_enable @@ -591,21 +543,19 @@ switch: on_turn_off: - script.execute: evaluate_relay_state -################################################################################################# -# BUTTON COMPONENT +#:########################################################################################:# +# BUTTON COMPONENT: # https://esphome.io/components/button/index.html -################################################################################################# +#:########################################################################################:# button: - platform: template name: "Boost now" id: boost_button icon: "mdi:play-circle-outline" on_press: - # 1) reset BOOST timer and set mode - lambda: |- id(boost_timer) = 0; id(operation_mode) = 3; - # 2) immediately re-evaluate relay state - script.execute: evaluate_relay_state - platform: template @@ -614,23 +564,23 @@ button: icon: "mdi:restore" on_press: - lambda: |- - // Restore all timing globals to their YAML defaults id(morning_on) = ${morning_on_default}; id(morning_off) = ${morning_off_default}; id(evening_on) = ${evening_on_default}; id(evening_off) = ${evening_off_default}; id(boost_duration) = ${boost_duration_default}; - // Reset mode to TIMER and clear any running boost id(operation_mode) = 2; id(boost_timer) = 0; ESP_LOGI("timer","Default timer settings applied"); + - switch.turn_on: morning_timer_enable + - switch.turn_on: evening_timer_enable - script.execute: evaluate_relay_state -################################################################################################# -# SELECT COMPONENT +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -################################################################################################# +#:########################################################################################:# select: - platform: template name: "Operation Mode" @@ -641,8 +591,6 @@ select: - "ON" - "TIMER" - "BOOST" - - # show the current mode lambda: |- switch (id(operation_mode)) { case 1: return std::string("ON"); @@ -650,80 +598,69 @@ select: case 3: return std::string("BOOST"); default: return std::string("OFF"); } - - # when changed in HA, set mode & re-evaluate set_action: - lambda: |- if (x == "OFF") { id(operation_mode) = 0; } else if (x == "ON") { id(operation_mode) = 1; } else if (x == "TIMER") { id(operation_mode) = 2; } - else { // BOOST + else { id(boost_timer) = 0; id(operation_mode) = 3; } - script.execute: evaluate_relay_state -################################################################################################# -# SCRIPT COMPONENT +#:########################################################################################:# +# SCRIPT COMPONENT: # https://esphome.io/components/script.html -################################################################################################# -# Script: evaluate and drive the relay +#:########################################################################################:# script: - id: evaluate_relay_state then: - lambda: |- int mode = id(operation_mode); - // BOOST just forces the relay on if (mode == 3) { id(relay).turn_on(); return; } - // OFF -> always off if (mode == 0) { id(relay).turn_off(); return; } - // ON -> always on if (mode == 1) { id(relay).turn_on(); return; } // TIMER -> follow schedule windows (gated by enable switches) - { - bool should_on = false; + bool should_on = false; - // Morning window only applies if Morning Timer Enable is ON - if (id(morning_timer_enable).state) { - if (id(current_mins) >= id(morning_on) && id(current_mins) < id(morning_off)) { - should_on = true; - } + if (id(morning_timer_enable).state) { + if (id(current_mins) >= id(morning_on) && id(current_mins) < id(morning_off)) { + should_on = true; } - - // Evening window only applies if Evening Timer Enable is ON - if (id(evening_timer_enable).state) { - if (id(current_mins) >= id(evening_on) && id(current_mins) < id(evening_off)) { - should_on = true; - } - } - - if (should_on) id(relay).turn_on(); - else id(relay).turn_off(); } -################################################################################################# -# INTERVAL COMPONENT + if (id(evening_timer_enable).state) { + if (id(current_mins) >= id(evening_on) && id(current_mins) < id(evening_off)) { + should_on = true; + } + } + + if (should_on) id(relay).turn_on(); + else id(relay).turn_off(); + +#:########################################################################################:# +# INTERVAL COMPONENT: # https://esphome.io/components/interval.html -################################################################################################# -# Interval: bumps time (even if no SNTP), then calls the script to evaluate relay state +#:########################################################################################:# interval: - interval: "1min" then: - lambda: |- - // - update current_mins via SNTP or fallback + // update current_mins via SNTP or fallback if (!id(sntp_time).now().is_valid()) { id(current_mins)++; if (id(current_mins) >= 1440) id(current_mins) = 0; @@ -732,12 +669,11 @@ interval: id(current_mins) = now.hour * 60 + now.minute; } - // - if in BOOST, advance boost_timer and expire when done + // BOOST timer handling if (id(operation_mode) == 3) { id(boost_timer)++; if (id(boost_timer) >= id(boost_duration)) { id(operation_mode) = 2; - //id(mqtt_client).publish("${mqtt_timer_topic}/operation", "TIMER"); } } - - script.execute: evaluate_relay_state + - script.execute: evaluate_relay_state \ No newline at end of file diff --git a/esphome/esp-rocktumbler.yaml b/esphome/esp-rocktumbler.yaml index 4983cdf..b47c9d3 100644 --- a/esphome/esp-rocktumbler.yaml +++ b/esphome/esp-rocktumbler.yaml @@ -1,55 +1,82 @@ -########################################################################################## -########################################################################################## -# ROCK TUMBLER POWER MONITOR -# -# Controlled by a Athom Smart Plug V1 -# package_import_url: github://athom-tech/athom-configs/athom-smart-plug.yaml -# +#:########################################################################################:# +# TITLE: ROCK TUMBLER POWER MONITOR +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-rocktumbler.yaml +#:########################################################################################:# +# VERSIONS: +# V1.4 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.3 2025-08-27 Changed to Athom V2 # V1.2 2025-06-15 Changed to Athom V1 # V1.1 2025-06-12 Tidyups and packages added -# -########################################################################################## -########################################################################################## +#:########################################################################################:# +# HARDWARE: +# - Athom Smart Plug V2 (ESP8285) with power monitoring + relay +# - Reference config: github://athom-tech/athom-configs/athom-smart-plug.yaml +#:########################################################################################:# +# OPERATION NOTES: +# - This device provides power monitoring (via common Athom V2 package) and a controllable relay. +# - "Power On State" select controls what the relay does after reboot: +# - Always Off +# - Always On +# - Restore Previous State +# - Power monitoring sensor update interval is set via substitutions. +#:########################################################################################:# +# MQTT COMMANDS: +# - None device-specific in this YAML (uses common_mqtt package for standard device MQTT support). +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device continues operating and can be controlled via MQTT (if your common_mqtt exposes it). +# - Power monitoring continues locally and publishes via MQTT if configured. +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable via Home Assistant API. +# - MQTT publishing/commands will fail while MQTT is down. +# c) Entire WiFi/Network OFFLINE +# - Device continues operating locally (relay + power monitoring). +# - SNTP is not needed (no timeclocks used in this YAML). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-rocktumbler" friendly_name: "Rock Tumbler Power" - description_comment: "Rock Tumbler Power :: Athom Smart Plug Power V2" - device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - - # Project Naming - project_name: "Athom Technology.Smart Plug V2" # Project Details - project_version: "v1.3" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + description_comment: "Rock Tumbler Power :: Athom Smart Plug Power V2 (Layout V1.1)" + device_area: "Laundry" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. - # Passwords (unfortunately you can't use substitutions inside secrets names) + # Project Naming + project_name: "Athom Technology.Smart Plug V2" + project_version: "v1.4" # Updated yaml to zorruno layout V1.1 + + # Passwords (unfortunately you cannot use substitutions inside secrets names) api_key: !secret esp-api_key - ota_pass: !secret esp-ota_pass + ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-rocktumbler_ip + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device General Settings - log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + log_level: "NONE" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE update_interval: "60s" # update time for for general sensors etc - # Device Specific Settings - # Athom Power Monitor Plug V2 - relay_icon: "mdi:power-socket-au" + # Device Specific Settings (Athom Power Monitor Plug V2) + relay_icon: "mdi:power-socket-au" current_limit: "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16. sensor_update_interval: "10s" relay_restore_mode: RESTORE_DEFAULT_ON hide_energy_sensor: "true" -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## -# Comment some of these out where not needed, eg MQTT, Web portal, SNTP, General Sensors -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -58,6 +85,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -71,21 +99,20 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml - + #### SNTP (Only use if you want/need accurate timeclocks) #### - common_sntp: !include common/sntp_common.yaml + common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 - # Device Specific included packages - # Athom Power Monitor Plug + #### Device Specific included packages: Athom Power Monitor Plug V2 #### common_athompowermonV2: !include file: common/athompowermonv2_common.yaml vars: @@ -96,47 +123,46 @@ packages: power_plug_type: "${relay_icon}" hide_energy_sensor: "${hide_energy_sensor}" -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" - comment: "${description_comment}" #Appears on the esphome page in HA - area: "${device_area}" + comment: "${description_comment}" # Appears on the esphome page in HA + area: "${device_area}" name_add_mac_suffix: false min_version: 2024.6.0 project: name: "${project_name}" version: "${project_version}" on_boot: - - priority: 600 - then: - - select.set_index: - id: power_mode - index: !lambda |- - return id(restore_mode)-1; - - lambda: |- - switch(id(restore_mode)) - { - case 1:{ - id(relay).turn_off(); - break; - } - case 2:{ - id(relay).turn_on(); - break; - } - default:{ - break; - } - } + priority: 600 + then: + - select.set_index: + id: power_mode + index: !lambda |- + return id(restore_mode) - 1; + - lambda: |- + switch (id(restore_mode)) { + case 1: { + id(relay).turn_off(); + break; + } + case 2: { + id(relay).turn_on(); + break; + } + default: { + break; + } + } -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +#:########################################################################################:# esp8266: board: esp8285 restore_from_flash: true # mainly for calculating cumulative energy, but not that important here @@ -148,40 +174,40 @@ preferences: mdns: disabled: false -########################################################################################## -# ESPHome LOGGING +#:########################################################################################:# +# LOGGING: ESPHome Logging Enable # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" - baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) + level: "${log_level}" + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) -########################################################################################## -# GLOBAL VARIABLES -# https://esphome.io/guides/automations.html?highlight=globals#global-variables -########################################################################################## +#:########################################################################################:# +# GLOBAL VARIABLES: +# https://esphome.io/guides/automations.html#global-variables +#:########################################################################################:# globals: - # 0 = Always_Off. 1 = Restore_Power_Off. 2 = Always_On. + # 0 = Always_Off, 1 = Restore_Power_Off, 2 = Always_On - id: restore_mode type: int restore_value: yes initial_value: "2" -########################################################################################## -# SELECT COMPONENT +#:########################################################################################:# +# SELECT COMPONENT: # https://esphome.io/components/select/index.html -########################################################################################## +#:########################################################################################:# select: - platform: template name: "Power On State" - id: "power_mode" + id: power_mode optimistic: true icon: mdi:electric-switch options: - - Always Off - - Always On - - Restore Previous State + - "Always Off" + - "Always On" + - "Restore Previous State" on_value: then: - lambda: |- - id(restore_mode)=i+1; \ No newline at end of file + id(restore_mode) = i + 1; \ No newline at end of file diff --git a/esphome/esp-underhouselights.yaml b/esphome/esp-underhouselights.yaml index c0bf0b7..9fde97b 100644 --- a/esphome/esp-underhouselights.yaml +++ b/esphome/esp-underhouselights.yaml @@ -1,29 +1,66 @@ -############################################# -############################################# -# UNDERHOUSE LIGHTS -# Controlled by a Sonoff 4Ch R2 -# https://github.com/jvyoralek/homeassistant-config/blob/master/esphome/sonoff-4ch.yaml -# +#:########################################################################################:# +# TITLE: UNDERHOUSE LIGHTS +# zorruno.com layout v1.1 2026 +#:########################################################################################:# +# REPO: +# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-underhouselights.yaml +#:########################################################################################:# +# VERSIONS: +# V1.1 2026-02-25 Updated yaml to zorruno layout V1.1 # V1.0 2025-06-18 Initial Version +#:########################################################################################:# +# HARDWARE: +# Controlled by a Sonoff 4Ch R2 +# Reference YAML: https://github.com/jvyoralek/homeassistant-config/blob/master/esphome/sonoff-4ch.yaml # -########################################################################################## -########################################################################################## +# GPIO (Sonoff 4Ch R2): +# - Relays: GPIO12, GPIO05, GPIO04, GPIO15 +# - Buttons: GPIO00, GPIO09, GPIO10, GPIO14 +# - Status LED: GPIO13 +# - Extra "Remote Switch" inputs used here: GPIO03, GPIO02 +#:########################################################################################:# +# OPERATION NOTES: +# - 4-channel relay controller for underhouse lighting circuits. +# - Local buttons toggle each relay (button1..button4). +# - Two extra GPIO inputs act as "remote switches" that toggle relay1 and relay2. +# - MQTT local command topics allow ON/OFF control per relay (see MQTT COMMANDS). +#:########################################################################################:# +# MQTT COMMANDS: +# Relay control (local MQTT): +# - ${mqtt_local_command_topic}/relay1/set -> ON, OFF +# - ${mqtt_local_command_topic}/relay2/set -> ON, OFF +# - ${mqtt_local_command_topic}/relay3/set -> ON, OFF +# - ${mqtt_local_command_topic}/relay4/set -> ON, OFF +#:########################################################################################:# +# OFFLINE NOTES: +# a) Home Assistant OFFLINE, but Network and MQTT ONLINE +# - Device remains controllable via MQTT local command topics. +# - Local buttons and remote switch inputs continue to toggle relays. +# b) MQTT OFFLINE (but WiFi/Network and HA API ONLINE) +# - Device remains controllable via Home Assistant API. +# - MQTT local commands will not work while MQTT is down. +# - Local buttons and remote switch inputs continue to toggle relays. +# c) Entire WiFi/Network OFFLINE +# - Local buttons and remote switch inputs continue to toggle relays. +# - No HA API or MQTT control available. +# - SNTP is not needed (no timeclocks used). +#:########################################################################################:# -########################################################################################## -# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +#:########################################################################################:# +# SUBSTITUTIONS: Specific device variable substitutions # If NOT using a secrets file, just replace these with the passwords etc (in quotes) -########################################################################################## +#:########################################################################################:# substitutions: # Device Naming device_name: "esp-underhouselights" friendly_name: "Underhouse Lights" - description_comment: "Underhouse Lights Control :: Sonoff 4Ch R2" - device_area: "Underhouse" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + description_comment: "Underhouse Lights Control :: Sonoff 4Ch R2 (Layout V1.1)" + device_area: "Underhouse" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. # Project Naming - project_name: "Sonoff Technologies.Sonoff 4Ch R2" # Project Details - project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version - + project_name: "Sonoff Technologies.Sonoff 4Ch R2" # Project Details + project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + # Passwords api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names @@ -31,9 +68,13 @@ substitutions: mqtt_local_command_main_topic: !secret mqtt_command_main_topic mqtt_local_status_main_topic: !secret mqtt_status_main_topic + # If we are changing IP addresses, you must update the current IP address here, otherwise it remains + # Don't forget to switch it back when changed. + current_ip_address: ${static_ip_address} + # Device Settings - log_level: "ERROR" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE - update_interval: "60s" # update time for for general sensors etc + log_level: "ERROR" # NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE + update_interval: "60s" # update time for general sensors etc # MQTT Controls mqtt_device_name: "underhouse-lights-control" @@ -43,21 +84,24 @@ substitutions: # Switch Naming switch_1_name: "Underhouse Entrance Lights" button_1_name: "Button 1" - relay_1_icon: "mdi:lightbulb" + relay_1_icon: "mdi:lightbulb" + switch_2_name: "Underhouse Storage Lights" button_2_name: "Button 2" - relay_2_icon: "mdi:lightbulb" + relay_2_icon: "mdi:lightbulb" + switch_3_name: "Spare 3" button_3_name: "Button 3" - relay_3_icon: "mdi:lightbulb" + relay_3_icon: "mdi:lightbulb" + switch_4_name: "Spare 4" button_4_name: "Button 4" - relay_4_icon: "mdi:lightbulb" + relay_4_icon: "mdi:lightbulb" -########################################################################################## +#:########################################################################################:# # PACKAGES: Included Common Packages # https://esphome.io/components/packages.html -########################################################################################## +#:########################################################################################:# packages: #### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode #### common_wifi: !include @@ -66,6 +110,7 @@ packages: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_ota_pass: "${ota_pass}" + local_current_ip_address: "${current_ip_address}" #### HOME ASSISTANT API (choose encryption or no encryption options) #### common_api: !include @@ -79,93 +124,86 @@ packages: file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" - + #### WEB PORTAL #### #common_webportal: !include common/webportal_common.yaml + #### SNTP (Only use if you want/need accurate timeclocks) #### - #common_sntp: !include common/sntp_common.yaml + #common_sntp: !include common/sntp_common.yaml #### DIAGNOSTICS Sensors #### - diag_basic: !include common/include_basic_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 + diag_basic: !include common/include_basic_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 -########################################################################################## -# ESPHome +#:########################################################################################:# +# ESPHOME: # https://esphome.io/components/esphome.html -########################################################################################## +#:########################################################################################:# esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" # Appears on the esphome page in HA area: "${device_area}" -# platformio_options: -# build_flags: -# - "-Os" # optimize for size -# - "-Wl,--gc-sections" # drop unused code/data -# - "-fno-exceptions" # strip C++ exceptions -# - "-fno-rtti" # strip C++ RTTI - -########################################################################################## -# ESP Platform and Framework -# https://esphome.io/components/esp32.html -########################################################################################## +#:########################################################################################:# +# ESP PLATFORM AND FRAMEWORK: +# https://esphome.io/components/esp8266/ +#:########################################################################################:# esp8266: - board: esp01_1m # The original sonoff basic - restore_from_flash: True # restore some values on reboot + board: esp01_1m + restore_from_flash: true preferences: flash_write_interval: 5min mdns: - disabled: False + disabled: false -########################################################################################## -# ESPHome Logging Enable +#:########################################################################################:# +# LOGGING: # https://esphome.io/components/logger.html -########################################################################################## +#:########################################################################################:# logger: - level: "${log_level}" #INFO Level suggested, or DEBUG for testing - baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM) - #esp8266_store_log_strings_in_flash: false - #tx_buffer_size: 64 + level: "${log_level}" + baud_rate: 0 # set to 0 for no logging via UART, needed if you are using it for other serial things -########################################################################################## -# SWITCH COMPONENT +#:########################################################################################:# +# SWITCH COMPONENT: # https://esphome.io/components/switch/ -########################################################################################## -# Sonoff 4Ch R2 Relays are GPIO12,05,04,15 -############################################# +# Sonoff 4Ch R2 Relays are GPIO12, GPIO05, GPIO04, GPIO15 +#:########################################################################################:# switch: - platform: gpio id: relay1 name: "${switch_1_name}" pin: GPIO12 - icon: "${relay_1_icon}" + icon: "${relay_1_icon}" + - platform: gpio id: relay2 name: "${switch_2_name}" pin: GPIO5 - icon: "${relay_2_icon}" + icon: "${relay_2_icon}" + - platform: gpio - id: relay3 + id: relay3 name: "${switch_3_name}" pin: GPIO4 - icon: "${relay_3_icon}" + icon: "${relay_3_icon}" + - platform: gpio id: relay4 name: "${switch_4_name}" pin: GPIO15 - icon: "${relay_4_icon}" + icon: "${relay_4_icon}" -########################################################################################## -# BINARY SENSORS +#:########################################################################################:# +# BINARY SENSORS: # https://esphome.io/components/binary_sensor/ -########################################################################################## -# Sonoff 4Ch R2 Buttons are GPIO00,09,10,14 -############################################# +# Sonoff 4Ch R2 Buttons are GPIO00, GPIO09, GPIO10, GPIO14 +#:########################################################################################:# binary_sensor: - platform: gpio id: button1 @@ -173,40 +211,44 @@ binary_sensor: pin: number: GPIO0 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay1 + - switch.toggle: relay1 + - platform: gpio id: button2 name: "${button_2_name}" pin: number: GPIO9 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay2 + - switch.toggle: relay2 + - platform: gpio id: button3 name: "${button_3_name}" pin: number: GPIO10 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay3 + - switch.toggle: relay3 + - platform: gpio id: button4 name: "${button_4_name}" pin: number: GPIO14 mode: INPUT_PULLUP - inverted: True + inverted: true on_press: - - switch.toggle: relay4 + - switch.toggle: relay4 + # Extra remote switch input -> toggles relay 1 - platform: gpio pin: - number: GPIO03 + number: GPIO3 mode: INPUT_PULLUP inverted: true name: "${switch_1_name} Remote Switch" @@ -219,15 +261,15 @@ binary_sensor: then: - lambda: |- if (id(relay1).state) { - // Relay is ON: turn it OFF id(relay1).turn_off(); } else { - // Relay is OFF: turn it ON id(relay1).turn_on(); } + + # Extra remote switch input -> toggles relay 2 - platform: gpio pin: - number: GPIO02 + number: GPIO2 mode: INPUT_PULLUP inverted: true name: "${switch_2_name} Remote Switch" @@ -240,28 +282,24 @@ binary_sensor: then: - lambda: |- if (id(relay2).state) { - // Relay is ON: turn it OFF id(relay2).turn_off(); } else { - // Relay is OFF: turn it ON id(relay2).turn_on(); } - -########################################################################################## -# STATUS LED + +#:########################################################################################:# +# STATUS LED: # https://esphome.io/components/status_led.html -########################################################################################## -# Sonoff Basic R1 LED is GPIO13 -############################################# +#:########################################################################################:# status_led: pin: number: GPIO13 - inverted: yes + inverted: true -########################################################################################## -# MQTT COMMANDS +#:########################################################################################:# +# MQTT: # This adds device-specific MQTT command triggers to the common MQTT configuration. -########################################################################################## +#:########################################################################################:# mqtt: on_message: # Relay 1 control @@ -273,6 +311,7 @@ mqtt: payload: "OFF" then: - switch.turn_off: relay1 + # Relay 2 control - topic: "${mqtt_local_command_topic}/relay2/set" payload: "ON" @@ -282,6 +321,7 @@ mqtt: payload: "OFF" then: - switch.turn_off: relay2 + # Relay 3 control - topic: "${mqtt_local_command_topic}/relay3/set" payload: "ON" @@ -290,8 +330,9 @@ mqtt: - topic: "${mqtt_local_command_topic}/relay3/set" payload: "OFF" then: - - switch.turn_off: relay3 - # Relay 4 control + - switch.turn_off: relay3 + + # Relay 4 control - topic: "${mqtt_local_command_topic}/relay4/set" payload: "ON" then: @@ -299,6 +340,4 @@ mqtt: - topic: "${mqtt_local_command_topic}/relay4/set" payload: "OFF" then: - - switch.turn_off: relay4 - - + - switch.turn_off: relay4 \ No newline at end of file