yaml layout updates to v1.1 and minor fixes

This commit is contained in:
root
2026-03-04 23:41:30 +13:00
parent a8d2927274
commit 2649a33051
10 changed files with 724 additions and 342 deletions
+1 -1
View File
@@ -1 +1 @@
{"pid": 68, "version": 1, "ha_version": "2026.2.3", "start_ts": 1771822737.408799}
{"pid": 67, "version": 1, "ha_version": "2026.2.3", "start_ts": 1772599646.9007783}
+22 -20
View File
@@ -1,9 +1,13 @@
#:########################################################################################:#
# TITLE: ARCADE CABINET 1 POWER (ATHOM SMART PLUG V1)
# zorruno.com layout v1.0 2026
# zorruno.com layout v1.1 2026
#:########################################################################################:#
# REPO:
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-arcademachine1.yaml
#:########################################################################################:#
# VERSIONS:
# V1.0 Unknown date - Initial Version (date not present in source header)
# v1.1 2026-03-04 Updated yaml to zorruno layout V1.1
# v1.0 Unknown date - Initial Version (date not present in source header)
#:########################################################################################:#
# HARDWARE:
# - Athom Smart Plug Power V1 (ESP8285 / ESP8266 family)
@@ -15,10 +19,20 @@
# - Local power button toggles relay state
#:########################################################################################:#
# MQTT COMMANDS:
#
# - None device-specific in this YAML (uses common MQTT package for base connectivity).
#:########################################################################################:#
# OFFLINE NOTES:
# a) Home Assistant OFFLINE, WiFi OK
# - Local button still toggles the relay.
# - Power monitoring continues locally; HA updates resume when HA returns.
#
# b) MQTT OFFLINE (or broker unreachable)
# - Local button and HA API (if HA reachable) still operate the relay.
# - MQTT state/telemetry (from common packages) will not publish until MQTT returns.
#
# c) Entire WiFi/Network OFFLINE
# - Local button still toggles the relay.
# - Accurate time is NOT needed for operation (no schedules). SNTP not needed.
#:########################################################################################:#
@@ -30,12 +44,12 @@ 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 (Layout V1.0)"
description_comment: "MAME Arcade 1 (Defender) machine power :: Athom Smart Plug Power V1 (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 V1" # Project Details
project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
project_name: "Athom Technology.Smart Plug V1"
project_version: "v1.1"
# Passwords
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -47,10 +61,9 @@ substitutions:
current_ip_address: ${static_ip_address}
# Device 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: "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.
@@ -106,11 +119,6 @@ packages:
common_general_sensors: !include
file: common/sensors_common.yaml
#### DEBUGGING Sensors ####
# A count of various resets
#common_resetcount_debugging: !include
# file: common/resetcount_common.yaml
# Device Specific included packages
common_athompowermonV1: !include
file: common/athompowermonv1_common.yaml
@@ -142,8 +150,6 @@ esphome:
esp8266:
board: esp8285
restore_from_flash: true # mainly for calculating cumulative energy, but not that important here
#framework:
# version: 2.7.4
#:########################################################################################:#
@@ -167,10 +173,8 @@ mdns:
# https://esphome.io/components/logger.html
#:########################################################################################:#
logger:
level: "${log_level}" # INFO Level suggested, or DEBUG for testing
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
#:########################################################################################:#
@@ -193,10 +197,8 @@ binary_sensor:
then:
- lambda: |-
if (id(relay).state) {
// Relay is ON: turn it OFF
id(relay).turn_off();
} else {
// Relay is OFF: turn it ON
id(relay).turn_on();
}
+24 -4
View File
@@ -1,12 +1,16 @@
#:########################################################################################:#
# TITLE: CEILING FAN - BEDROOM 2
# zorruno.com layout v1.0 2026
# zorruno.com layout v1.1 2026
#:########################################################################################:#
# REPO:
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm2ceilingfan.yaml
#:########################################################################################:#
# VERSIONS:
# V1.1 2026-03-04 Updated yaml to zorruno layout V1.1
# V1.0 2025-07-21 First Setup (and replacement of Tasmota)
#:########################################################################################:#
# HARDWARE:
# Controlled by a Sonoff iFan02 (3-speed fan + 1x light relay)
# - 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
@@ -36,8 +40,10 @@
# - 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)
# - Accurate time is NOT needed (SNTP not required) for core operation (no schedules/timeclocks used)
#:########################################################################################:#
#:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -46,12 +52,12 @@ substitutions:
# Device Naming
device_name: "esp-bedrm2ceilingfan"
friendly_name: "Bedroom 2 Ceiling Fan"
description_comment: "3 Speed Overhead Ceiling Fan Bedroom 2 :: Sonoff iFan02 (Layout V1.0)"
description_comment: "3 Speed Overhead Ceiling Fan Bedroom 2 :: Sonoff iFan02 (Layout V1.1)"
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
project_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords and Secrets
api_key: !secret esp-api_key
@@ -79,6 +85,7 @@ substitutions:
switch_3_name: "Fan 3 Relay"
switch_4_name: "Fan 4 Relay"
#:########################################################################################:#
# PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html
@@ -118,6 +125,7 @@ packages:
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
@@ -141,6 +149,7 @@ esphome:
# - "-fno-exceptions" # strip C++ exceptions
# - "-fno-rtti" # strip C++ RTTI
#:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266/
@@ -156,6 +165,7 @@ preferences:
mdns:
disabled: true # Disabling will make the build file smaller (and it is still available via static IP)
#:########################################################################################:#
# GLOBAL VARIABLES:
# https://esphome.io/guides/automations.html#global-variables
@@ -166,6 +176,7 @@ globals:
restore_value: true
initial_value: "0"
#:########################################################################################:#
# LOGGING: ESPHome Logging Enable
# https://esphome.io/components/logger.html
@@ -174,6 +185,7 @@ logger:
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)
@@ -191,6 +203,7 @@ uart:
# NOTE: If no frames appear at either 9600 or 19200, try moving rx_pin to GPIO13 and reflash:
# rx_pin: GPIO13
#:########################################################################################:#
# INTERVAL COMPONENT:
# https://esphome.io/components/interval.html
@@ -222,6 +235,7 @@ interval:
frame.clear();
}
#:########################################################################################:#
# TEXT SENSORS COMPONENT:
# https://esphome.io/components/text_sensor/index.html
@@ -232,6 +246,7 @@ text_sensor:
name: "iFan02 Remote Last Frame"
update_interval: never
#:########################################################################################:#
# MQTT:
# This adds device-specific MQTT command triggers to the common MQTT configuration.
@@ -282,6 +297,7 @@ mqtt:
id: ifan02_fan
speed: !lambda "return id(speed_value);"
#:########################################################################################:#
# SWITCH COMPONENT:
# https://esphome.io/components/switch/
@@ -311,6 +327,7 @@ switch:
restore_mode: RESTORE_DEFAULT_OFF
internal: true
#:########################################################################################:#
# SELECT COMPONENT:
# https://esphome.io/components/select/index.html
@@ -375,6 +392,7 @@ select:
id: ifan02_fan
speed: 3
#:########################################################################################:#
# OUTPUT COMPONENT:
# https://esphome.io/components/output/
@@ -412,6 +430,7 @@ output:
id(fan4sw).turn_on();
}
#:########################################################################################:#
# LIGHT COMPONENT:
# https://esphome.io/components/light/
@@ -432,6 +451,7 @@ light:
topic: "${mqtt_local_status_topic}/light/state"
payload: "OFF"
#:########################################################################################:#
# FAN COMPONENT:
# https://esphome.io/components/fan/index.html
+21 -7
View File
@@ -1,13 +1,17 @@
#:########################################################################################:#
# TITLE: BEDROOM 2 FAN SWITCH (WALL SWITCH)
# zorruno.com layout v1.0 2026
# zorruno.com layout v1.1 2026
#:########################################################################################:#
# REPO:
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm2fanswitch.yaml
#:########################################################################################:#
# VERSIONS:
# V1.1 2026-03-04 Updated yaml to zorruno layout V1.1
# 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/
# - 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
@@ -40,8 +44,10 @@
# - 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)
# - Accurate time is NOT needed (SNTP not required) for core operation (no time-of-day schedules)
#:########################################################################################:#
#:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -50,12 +56,12 @@ 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) (Layout V1.0)"
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.1)"
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
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
@@ -87,6 +93,7 @@ substitutions:
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
@@ -126,6 +133,7 @@ packages:
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
@@ -145,6 +153,7 @@ esphome:
# - "-fno-exceptions" # strip C++ exceptions
# - "-fno-rtti" # strip C++ RTTI
#:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266/
@@ -155,6 +164,7 @@ esp8266:
early_pin_init: false # Recommended false where switches are involved. Defaults to true.
board_flash_mode: dout # Default is dout
#:########################################################################################:#
# LOGGING: ESPHome Logging Enable
# https://esphome.io/components/logger.html
@@ -165,6 +175,7 @@ logger:
#esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64
#:########################################################################################:#
# STATUS LED:
# https://esphome.io/components/status_led.html
@@ -172,9 +183,10 @@ logger:
#:########################################################################################:#
status_led:
pin:
number: GPIO02
number: GPIO2
inverted: true
#:########################################################################################:#
# BINARY SENSORS:
# https://esphome.io/components/binary_sensor/
@@ -195,7 +207,7 @@ binary_sensor:
- platform: gpio
pin:
number: GPIO05
number: GPIO5
mode: INPUT
inverted: true
name: "Button 2: ${switch_2_name}"
@@ -215,6 +227,7 @@ binary_sensor:
topic: "${mqtt_remote_device_command_topic}"
payload: "${mqtt_remote_device_command3}"
#:########################################################################################:#
# SWITCH COMPONENT:
# https://esphome.io/components/switch/
@@ -236,6 +249,7 @@ switch:
pin: GPIO14
id: Relay_3
#:########################################################################################:#
# MQTT:
# Subscribe to fan speed state and mirror it to relay indicator pattern
+19 -7
View File
@@ -1,13 +1,17 @@
#:########################################################################################:#
# TITLE: BEDROOM 2 LIGHTSWITCH
# zorruno.com layout v1.0 2026
# zorruno.com layout v1.1 2026
#:########################################################################################:#
# REPO:
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-bedrm2lights.yaml
#:########################################################################################:#
# VERSIONS:
# V3.6 2026-03-04 Updated yaml to zorruno layout V1.1
# V3.5 2025-07-24 YAML tidyups
#:########################################################################################:#
# HARDWARE:
# Zemismart KS-811 Double push button (KS-811-2)
# pinout/schematic: https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/
# - 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
@@ -30,8 +34,10 @@
# 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
# - Accurate time is NOT needed (SNTP not required) for core operation (no time-of-day schedules)
#:########################################################################################:#
#:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -40,12 +46,12 @@ substitutions:
# 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) (Layout V1.0)"
description_comment: "Bedroom 2 Main Lightswitch using a Zemismart KS-811 Double Push Button. Main Lights (1), Desk Lights (2) (Layout V1.1)"
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_version: "v3.6" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
# Passwords and Secrets
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
@@ -64,6 +70,7 @@ substitutions:
switch_1_name: "Main Lights"
switch_2_name: "Desk Lights"
#:########################################################################################:#
# PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html
@@ -103,6 +110,7 @@ packages:
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
@@ -120,16 +128,17 @@ esphome:
# then:
# - switch.turn_on: Relay_2
#:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266/
# https://esphome.io/components/esp32/
#:########################################################################################:#
esp8266:
board: esp01_1m
early_pin_init: false # Recommended false where switches are involved. Defaults to true.
board_flash_mode: dout # Default is dout
#:########################################################################################:#
# LOGGING: ESPHome Logging Enable
# https://esphome.io/components/logger.html
@@ -140,6 +149,7 @@ logger:
#esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64
#:########################################################################################:#
# STATUS LED:
# https://esphome.io/components/status_led.html
@@ -149,6 +159,7 @@ status_led:
number: GPIO2
inverted: true
#:########################################################################################:#
# BINARY SENSORS:
# https://esphome.io/components/binary_sensor/
@@ -167,7 +178,7 @@ binary_sensor:
- platform: gpio
pin:
number: GPIO05
number: GPIO5
mode: INPUT
inverted: true
name: "Button 2: ${switch_2_name}"
@@ -184,6 +195,7 @@ binary_sensor:
# on_press:
# - switch.toggle: Relay_3
#:########################################################################################:#
# SWITCH COMPONENT:
# https://esphome.io/components/switch/
+458 -136
View File
@@ -6,6 +6,10 @@
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-garagedbcontrols.yaml
#:########################################################################################:#
# VERSIONS:
# v1.2 2026-03-03 EV monitoring updated to match Device A:
# - Rolling average EV power (default 5 min @ 10s)
# - EV charging binary sensor (threshold configurable)
# - EV totals and energy summaries (today/yesterday/month/year)
# v1.1 2026-02-25 Updated yaml to zorruno layout V1.1
# v1.0 2025-10-23 Initial Version
#:########################################################################################:#
@@ -22,36 +26,27 @@
# 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}
# - EV charger monitoring (2 Wh per pulse on GPIO2):
# - Lifetime total energy (kWh) from persisted absolute pulse total.
# - Rolling average power (default 5 min) to reduce spiky readings at low load.
# - Charging binary sensor based on averaged power threshold.
# - Energy summaries: today, yesterday, this month, last month, this year, last year.
#:########################################################################################:#
# 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.
#
# - Device continues relay/button operation and continues pulse counting locally.
# - API/MQTT publishing will fail until HA (and/or broker) is back.
# 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.
#
# - Relays/buttons still operate locally and via HA API (if HA is available).
# - MQTT state publishing depends on broker.
# 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.
# - 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)
#:########################################################################################:#
#:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
#:########################################################################################:#
substitutions:
# Device Naming
@@ -62,7 +57,7 @@ substitutions:
# Project Naming
project_name: "Sonoff Technologies.Sonoff 4Ch R2"
project_version: "v1.1"
project_version: "v1.2"
# Passwords & Secrets
api_key: !secret esp-api_key
@@ -77,8 +72,12 @@ substitutions:
log_level: "ERROR"
update_interval: "60s"
# Globals persistence tuning (gentler on flash)
globals_save_interval_slow: "10min"
globals_save_interval_pulses: "2min"
# I/O Naming
switch_1_name: "Small EV Charger"
switch_1_name: "16A Wallcharger Operation"
button_1_name: "Button 1"
relay_1_icon: "mdi:power-socket-au"
@@ -94,15 +93,43 @@ substitutions:
button_4_name: "Button 4"
relay_4_icon: "mdi:toggle-switch"
# 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"
########################################################################################
# EV Pulse Settings (Device A logic)
########################################################################################
ev_pulse_wh: "2.0" # Each pulse is 2Wh
ev_pulse_filter_ms: "10ms" # Debounce / filter
ev_pulse_pin_mode: "INPUT_PULLUP"
# EV Charging Detection (Averaged power + binary sensor)
# Minimum EV charging power threshold (W) for binary sensor
ev_charging_min_power_w: "200"
# 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: "15" # 5 min @ 10s = 30 samples
ev_power_avg_buffer_size: "60" # ring buffer >= window_samples (180 @ 10s = 30 minutes)
# Rollover check interval (time-valid day/month/year updates)
rollover_check_interval: "30s"
# Names - EV Wallcharger (Device B)
ev_charger_name: "16A Wallcharger"
ev_power_name: "${ev_charger_name} Power"
ev_charging_name: "${ev_charger_name} Charging"
ev_total_energy_name: "${ev_charger_name} Total Energy"
ev_today_name: "${ev_charger_name} Energy Today"
ev_yesterday_name: "${ev_charger_name} Energy Yesterday"
ev_month_name: "${ev_charger_name} Energy This Month"
ev_last_month_name: "${ev_charger_name} Energy Last Month"
ev_year_name: "${ev_charger_name} Energy This Year"
ev_last_year_name: "${ev_charger_name} Energy Last Year"
#:########################################################################################:#
# PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html
#:########################################################################################:#
packages:
#### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode ####
@@ -114,10 +141,9 @@ packages:
local_ota_pass: "${ota_pass}"
local_current_ip_address: "${current_ip_address}"
#### HOME ASSISTANT API (choose encryption or no encryption options) ####
#### HOME ASSISTANT API ####
common_api: !include
file: common/api_common.yaml
#file: common/api_common_noencryption.yaml
vars:
local_api_key: "${api_key}"
@@ -127,18 +153,15 @@ packages:
vars:
local_device_name: "${device_name}"
#### SNTP (Only use if you want/need accurate timeclocks) ####
#### SNTP ####
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}"
@@ -148,20 +171,15 @@ esphome:
project:
name: "${project_name}"
version: "${project_version}"
# On boot, initialise the window start so the first publish isn't huge
on_boot:
priority: -10
priority: -100
then:
- lambda: |-
if (isfinite(id(ev_energy_total_kwh).state)) {
id(ev_last_total_kwh) = id(ev_energy_total_kwh).state;
} else {
id(ev_last_total_kwh) = 0.0f;
}
- script.execute: init_ev_history_arrays
- delay: 3s
- script.execute: ev_rollover_check
#:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK
# https://esphome.io/components/esp8266.html
#:########################################################################################:#
esp8266:
board: esp8285
@@ -175,7 +193,6 @@ mdns:
#:########################################################################################:#
# LOGGING
# https://esphome.io/components/logger.html
#:########################################################################################:#
logger:
level: "${log_level}"
@@ -183,7 +200,6 @@ logger:
#:########################################################################################:#
# STATUS LED
# https://esphome.io/components/status_led.html
#:########################################################################################:#
status_led:
pin:
@@ -191,30 +207,93 @@ status_led:
inverted: yes
#:########################################################################################:#
# GLOBALS
# https://esphome.io/components/globals.html
# GLOBALS (EV totals + rollovers + rolling average history)
#:########################################################################################:#
globals:
# Store the last published total (kWh) for 60s delta windowing
- id: ev_last_total_kwh
# Date tracking for rollovers (restored)
- id: g_last_day
type: int
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "0"
- id: g_last_month
type: int
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "0"
- id: g_last_year
type: int
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "0"
# EV baseline totals for period calculations (restored)
- id: g_ev_day_start_kwh
type: float
restore_value: true
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "-1.0"
- id: g_ev_month_start_kwh
type: float
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "-1.0"
- id: g_ev_year_start_kwh
type: float
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "-1.0"
# EV stored prior periods (restored)
- id: g_ev_yesterday_kwh
type: float
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "0.0"
- id: g_ev_last_month_kwh
type: float
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "0.0"
- id: g_ev_last_year_kwh
type: float
restore_value: yes
update_interval: ${globals_save_interval_slow}
initial_value: "0.0"
- id: ev_energy_yesterday_kwh
# EV pulse accumulation (persisted across reboots) (restored)
- id: g_ev_pulses_total_abs
type: uint32_t
restore_value: yes
update_interval: ${globals_save_interval_pulses}
initial_value: "0"
- id: g_ev_pulses_raw_last
type: uint32_t
restore_value: yes
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: true
restore_value: no
initial_value: "0.0"
# Track last day-of-year we snapped so it only happens once per day
- id: ev_last_snapshot_doy
# 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: "-1"
initial_value: "0"
- id: g_ev_pulses_hist_count
type: int
restore_value: no
initial_value: "0"
#:########################################################################################:#
# SWITCHES
# https://esphome.io/components/switch/
#:########################################################################################:#
switch:
# Sonoff 4Ch R2 Relays are GPIO12, GPIO5, GPIO4, GPIO15
@@ -248,7 +327,6 @@ switch:
#:########################################################################################:#
# BINARY SENSORS
# https://esphome.io/components/binary_sensor/
#:########################################################################################:#
binary_sensor:
# Sonoff 4Ch R2 Buttons are GPIO0, GPIO9, GPIO10, GPIO14
@@ -292,133 +370,377 @@ binary_sensor:
on_press:
- switch.toggle: relay4
# EV charging detection (Device A logic: averaged power threshold)
- 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
# https://esphome.io/components/sensor/
#:########################################################################################:#
sensor:
########################################################################################
# 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
# EV WALLCHARGER PULSE ENERGY (GPIO2)
########################################################################################
- platform: pulse_meter
id: ev_pulse_pm
- platform: pulse_counter
id: ev_pulse_rate_ppm
internal: true
pin:
number: GPIO2
mode: INPUT_PULLUP # GPIO2 must be HIGH at boot
mode: ${ev_pulse_pin_mode} # GPIO2 must be HIGH at boot
inverted: false
name: "${switch_1_name} Power Now"
update_interval: ${ev_power_avg_sample_interval}
internal_filter: ${ev_pulse_filter_ms}
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;
- platform: template
name: "${ev_power_name}"
id: ev_power_avg_w
unit_of_measurement: "W"
device_class: power
state_class: measurement
accuracy_decimals: 0
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
total:
id: ev_energy_total_kwh
name: "${switch_1_name} Energy Cumulative Total"
unit_of_measurement: "kWh"
device_class: energy
state_class: total_increasing
accuracy_decimals: 1
filters:
# kWh per pulse (2.0 Wh = 0.002 kWh)
- multiply: 0.002
update_interval: "${ev_power_avg_sample_interval}"
lambda: |-
return id(g_ev_power_avg_w);
- platform: template
id: ev_power_avg_1h
name: "${switch_1_name} Power (1h avg)"
unit_of_measurement: "W"
device_class: power
state_class: measurement
accuracy_decimals: 1
update_interval: 10s
name: "${ev_total_energy_name}"
id: ev_total_energy_kwh
unit_of_measurement: "kWh"
device_class: energy
state_class: total_increasing
accuracy_decimals: 3
update_interval: ${ev_power_avg_sample_interval}
lambda: |-
return id(ev_pulse_pm).state;
filters:
- sliding_window_moving_average:
window_size: 360 # 10 s * 360 ≈ 1 hour
send_every: 6 # update HA once per minute
return ((float) id(g_ev_pulses_total_abs)) * (${ev_pulse_wh} / 1000.0f);
- platform: total_daily_energy
- platform: template
name: "${ev_today_name}"
id: ev_energy_today_kwh
name: "${switch_1_name} Energy Today"
power_id: ev_pulse_pm
unit_of_measurement: "kWh"
device_class: energy
state_class: total
accuracy_decimals: 1
filters:
# total_daily_energy outputs Wh; convert to kWh
- multiply: 0.001
accuracy_decimals: 3
update_interval: 60s
lambda: |-
const float total = id(ev_total_energy_kwh).state;
if (isnan(total) || id(g_ev_day_start_kwh) < 0.0f) return NAN;
float v = total - id(g_ev_day_start_kwh);
if (v < 0.0f) v = 0.0f;
return v;
- platform: template
id: ev_energy_yesterday_sensor
name: "${switch_1_name} Energy Yesterday"
name: "${ev_yesterday_name}"
id: ev_energy_yesterday_kwh
unit_of_measurement: "kWh"
device_class: energy
state_class: total
accuracy_decimals: 1
update_interval: 30s
accuracy_decimals: 3
update_interval: 10min
lambda: |-
return id(ev_energy_yesterday_kwh);
return id(g_ev_yesterday_kwh);
- platform: template
name: "${ev_month_name}"
id: ev_energy_this_month_kwh
unit_of_measurement: "kWh"
device_class: energy
state_class: total
accuracy_decimals: 3
update_interval: 10min
lambda: |-
const float total = id(ev_total_energy_kwh).state;
if (isnan(total) || id(g_ev_month_start_kwh) < 0.0f) return NAN;
float v = total - id(g_ev_month_start_kwh);
if (v < 0.0f) v = 0.0f;
return v;
- platform: template
name: "${ev_last_month_name}"
id: ev_energy_last_month_kwh
unit_of_measurement: "kWh"
device_class: energy
state_class: total
accuracy_decimals: 3
update_interval: 30min
lambda: |-
return id(g_ev_last_month_kwh);
- platform: template
name: "${ev_year_name}"
id: ev_energy_this_year_kwh
unit_of_measurement: "kWh"
device_class: energy
state_class: total
accuracy_decimals: 3
update_interval: 30min
lambda: |-
const float total = id(ev_total_energy_kwh).state;
if (isnan(total) || id(g_ev_year_start_kwh) < 0.0f) return NAN;
float v = total - id(g_ev_year_start_kwh);
if (v < 0.0f) v = 0.0f;
return v;
- platform: template
name: "${ev_last_year_name}"
id: ev_energy_last_year_kwh
unit_of_measurement: "kWh"
device_class: energy
state_class: total
accuracy_decimals: 3
update_interval: 60min
lambda: |-
return id(g_ev_last_year_kwh);
########################################################################################
# DHT SENSOR (GPIO3)
# NOTE: GPIO3 is UART RX on ESP8266; logger baud_rate=0 avoids conflicts.
########################################################################################
- platform: dht
pin: GPIO3
update_interval: 60s
update_interval: ${update_interval}
temperature:
name: "${friendly_name} Temperature"
unit_of_measurement: "°C"
accuracy_decimals: 1
humidity:
name: "${friendly_name} Humidity"
unit_of_measurement: "%"
accuracy_decimals: 0
#:########################################################################################:#
# INTERVALS
# https://esphome.io/components/interval.html
# INTERVALS (EV rolling average + rollover checks)
#:########################################################################################:#
interval:
# Teleperiod = 60s: publish JSON and advance the window
- interval: 60s
- interval: "${rollover_check_interval}"
then:
- mqtt.publish:
topic: "${ev_tasmota_tele_topic}"
qos: 0
retain: false
payload: !lambda |-
float current = id(ev_energy_total_kwh).state;
if (!isfinite(current)) current = id(ev_last_total_kwh);
- script.execute: ev_rollover_check
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;
- interval: "${ev_power_avg_sample_interval}"
then:
- script.execute: ev_power_avg_update
id(ev_last_total_kwh) = current;
#:########################################################################################:#
# SCRIPTS (EV)
#:########################################################################################:#
script:
# Initialize EV pulse history buffer so rolling average starts stable after boot
- id: init_ev_history_arrays
mode: queued
then:
- lambda: |-
const int ev_buf = ${ev_power_avg_buffer_size};
const uint32_t p0 = id(g_ev_pulses_total_abs);
char buf[64];
snprintf(buf, sizeof(buf), "{\"EVChargerWhCount\":%.3f}", delta_wh);
return std::string(buf);
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;
# YESTERDAY ENERGY snapshot (once per day at 23:59, when time is valid)
- interval: 60s
# 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 EV totals
- id: ev_rollover_check
mode: restart
then:
- lambda: |-
auto now = id(sntp_time).now();
if (!now.is_valid()) return;
if (now.hour != 23 || now.minute != 59) return;
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;
if (!now.is_valid()) {
return;
}
id(ev_last_snapshot_doy) = now.day_of_year;
const int d = now.day_of_month;
const int m = now.month;
const int y = now.year;
const float ev_total = id(ev_total_energy_kwh).state;
// Initialize date markers on first valid time
if (id(g_last_year) == 0) {
id(g_last_day) = d;
id(g_last_month) = m;
id(g_last_year) = y;
if (!isnan(ev_total)) {
id(g_ev_day_start_kwh) = ev_total;
id(g_ev_month_start_kwh) = ev_total;
id(g_ev_year_start_kwh) = ev_total;
}
return;
}
// Protect against meter reset / wrap (total < baseline)
if (!isnan(ev_total)) {
if (id(g_ev_day_start_kwh) < 0.0f) id(g_ev_day_start_kwh) = ev_total;
if (id(g_ev_month_start_kwh) < 0.0f) id(g_ev_month_start_kwh) = ev_total;
if (id(g_ev_year_start_kwh) < 0.0f) id(g_ev_year_start_kwh) = ev_total;
if (ev_total < id(g_ev_day_start_kwh)) id(g_ev_day_start_kwh) = ev_total;
if (ev_total < id(g_ev_month_start_kwh)) id(g_ev_month_start_kwh) = ev_total;
if (ev_total < id(g_ev_year_start_kwh)) id(g_ev_year_start_kwh) = ev_total;
}
// YEAR rollover
if (y != id(g_last_year)) {
if (!isnan(ev_total) && id(g_ev_year_start_kwh) >= 0.0f) {
float ykwh = ev_total - id(g_ev_year_start_kwh);
if (ykwh < 0.0f) ykwh = 0.0f;
id(g_ev_last_year_kwh) = ykwh;
id(g_ev_year_start_kwh) = ev_total;
}
id(g_last_year) = y;
}
// MONTH rollover
if (m != id(g_last_month)) {
if (!isnan(ev_total) && id(g_ev_month_start_kwh) >= 0.0f) {
float mkwh = ev_total - id(g_ev_month_start_kwh);
if (mkwh < 0.0f) mkwh = 0.0f;
id(g_ev_last_month_kwh) = mkwh;
id(g_ev_month_start_kwh) = ev_total;
}
id(g_last_month) = m;
}
// DAY rollover
if (d != id(g_last_day)) {
if (!isnan(ev_total) && id(g_ev_day_start_kwh) >= 0.0f) {
float dkwh = ev_total - id(g_ev_day_start_kwh);
if (dkwh < 0.0f) dkwh = 0.0f;
id(g_ev_yesterday_kwh) = dkwh;
id(g_ev_day_start_kwh) = ev_total;
}
id(g_last_day) = d;
}
#:########################################################################################:#
# ROLLBACK COPY (v1.1) - PREVIOUS EV SECTION (pulse_meter + daily snapshot + mqtt window)
# NOTE: Commented out. Kept for quick revert if needed.
#:########################################################################################:#
#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"
#
# - id: ev_last_snapshot_doy
# type: int
# restore_value: no
# initial_value: "-1"
#
#sensor:
# - platform: pulse_meter
# id: ev_pulse_pm
# pin:
# number: GPIO2
# mode: INPUT_PULLUP
# inverted: false
# name: "${switch_1_name} Power Now"
# unit_of_measurement: "W"
# accuracy_decimals: 0
# internal_filter: ${ev_pulse_filter}
# timeout: ${ev_pulse_timeout}
# filters:
# - multiply: 120.0
# total:
# id: ev_energy_total_kwh
# name: "${switch_1_name} Energy Cumulative Total"
# unit_of_measurement: "kWh"
# accuracy_decimals: 1
# filters:
# - multiply: 0.002
#
#interval:
# - interval: 60s
# then:
# - mqtt.publish:
# topic: "${ev_tasmota_tele_topic}"
# qos: 0
# retain: false
# payload: !lambda |-
# float current = id(ev_energy_total_kwh).state;
# if (!isfinite(current)) current = id(ev_last_total_kwh);
# 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;
# id(ev_last_total_kwh) = current;
# char buf[64];
# snprintf(buf, sizeof(buf), "{\"EVChargerWhCount\":%.3f}", delta_wh);
# return std::string(buf);
#
# - interval: 60s
# then:
# - lambda: |-
# auto now = id(sntp_time).now();
# if (!now.is_valid()) return;
# if (now.hour != 23 || now.minute != 59) return;
# 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;
+20 -23
View File
@@ -1,15 +1,19 @@
#:########################################################################################:#
# TITLE: 6 CHANNEL LOUNGE DMX MAINS DIMMER
# zorruno.com layout v1.0 2026
# zorruno.com layout v1.1 2026
#:########################################################################################:#
# REPO:
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-lounge6chdimmer.yaml
#:########################################################################################:#
# VERSIONS:
# V1.2 2026-03-04 Updated yaml to zorruno layout V1.1
# 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
# Controller: https://www.aliexpress.com/item/32838426377.html
# - RS-485 TTL converter (MAX485 style)
# RS-485 TTL converter: https://www.aliexpress.com/item/1005005737922222.html
#
@@ -49,14 +53,20 @@
# https://github.com/andyboeh/esphome-dmx512
#:########################################################################################:#
# MQTT COMMANDS:
#
# - None (DMX is driven by HA light entities).
#:########################################################################################:#
# 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)
# a) Home Assistant OFFLINE (WiFi + network still online):
# - Device continues DMX output at last set levels (dimmers remember output).
#
# b) MQTT OFFLINE (or HA/MQTT offline):
# - No MQTT dependency for operation; last levels remain active.
#
# c) Entire WiFi/Network OFFLINE:
# - Accurate time is not needed (SNTP not needed; no schedules/timeclocks).
# - Wall switch power-cycling restores dimmer module output state (modules remember).
#:########################################################################################:#
#:########################################################################################:#
# SUBSTITUTIONS: Specific device variable substitutions
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
@@ -65,20 +75,19 @@ substitutions:
# 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 (Layout V1.0)"
description_comment: "Lounge 6 Channel Mains Lighting Dimmer (3 x 2 channel modules) controlled using DMX512 protocol with a D1 Mini Pro (Layout V1.1)"
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_version: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
project_version: "v1.2" # 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-lounge6chdimmer_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.
# Layout v1.1 requirement
current_ip_address: ${static_ip_address}
# Device Settings
@@ -110,7 +119,6 @@ substitutions:
gamma_output_5: "2.2"
gamma_output_6: "2.2"
#:########################################################################################:#
# PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html
@@ -151,7 +159,6 @@ packages:
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
@@ -175,7 +182,6 @@ esphome:
id(dmx_ch5_sensor).publish_state(0);
id(dmx_ch6_sensor).publish_state(0);
#:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp8266/
@@ -186,7 +192,6 @@ esp8266:
board_flash_mode: dout # Default is dout
restore_from_flash: true # restore some values on reboot
#:########################################################################################:#
# MDNS:
# https://esphome.io/components/mdns.html
@@ -194,7 +199,6 @@ esp8266:
mdns:
disabled: false # Disabling will make the build file smaller (and it is still available via static IP)
#:########################################################################################:#
# LOGGING: ESPHome Logging Enable
# https://esphome.io/components/logger.html
@@ -205,7 +209,6 @@ logger:
#esp8266_store_log_strings_in_flash: false
#tx_buffer_size: 64
#:########################################################################################:#
# STATUS LED:
# https://esphome.io/components/status_led.html
@@ -215,7 +218,6 @@ logger:
# number: GPIO2
# inverted: true
#:########################################################################################:#
# UART COMPONENT:
# https://esphome.io/components/uart/
@@ -231,7 +233,6 @@ uart:
allow_other_uses: true # For ESPHome >= 2023.12.0
stop_bits: 2
#:########################################################################################:#
# LIGHT COMPONENT:
# https://esphome.io/components/light/
@@ -285,7 +286,6 @@ light:
gamma_correct: "${gamma_output_6}"
restore_mode: RESTORE_DEFAULT_OFF
#:########################################################################################:#
# SENSOR COMPONENT:
# https://esphome.io/components/sensor/
@@ -382,7 +382,6 @@ sensor:
min_value: 0
max_value: 255
#:########################################################################################:#
# EXTERNAL COMPONENTS:
# https://github.com/andyboeh/esphome-dmx512
@@ -390,7 +389,6 @@ sensor:
external_components:
- source: github://andyboeh/esphome-dmx512
#:########################################################################################:#
# DMX512 COMPONENT:
# https://github.com/andyboeh/esphome-dmx512
@@ -409,7 +407,6 @@ dmx512:
#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/
+87 -72
View File
@@ -1,18 +1,23 @@
##########################################################################################
#:########################################################################################:#
# TITLE: MAIN BATHROOM FAN/HEAT COMBO SWITCH
##########################################################################################
# zorruno.com layout v1.1 2026
#:########################################################################################:#
# REPO:
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-mainbathfancombo.yaml
#:########################################################################################:#
# VERSIONS:
# V1.6 2026-03-04 Updated yaml to zorruno layout V1.1; adjusted Button 2 click timing for towel rail MQTT reliability
# 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)
# V1.2 2026-02-18 Stop delayed-off countdown when Relay_1 turns OFF
# 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/
##########################################################################################
# - Zemismart KS-811 Double Push Button
# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/
#:########################################################################################:#
# 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)
@@ -26,7 +31,7 @@
# 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.
@@ -36,22 +41,24 @@
# 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.
##########################################################################################
# - Accurate time is NOT needed (SNTP not required) for core operation (no time-of-day schedules)
#:########################################################################################:#
##########################################################################################
# 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-mainbathfancombo"
friendly_name: "Main Bathroom Fan-Heat Combo Switch (2)"
description_comment: "Main Bathroom Fan/Heat Switch using a Zemismart KS-811 Double Push Button. Extract Fan (1), IR heater (2)"
description_comment: "Main Bathroom Fan/Heat Switch using a Zemismart KS-811 Double Push Button. Extract Fan (1), IR heater (2) (Layout V1.1)"
device_area: "Main Bathroom" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant.
# Project Naming
project_name: "Zemismart Technologies.KS-811-2 (Double)" # Project Details
project_version: "v1.5" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
project_version: "v1.6" # 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.
@@ -81,10 +88,11 @@ substitutions:
mqtt_remote_device1_command_topic: "${mqtt_command_main_topic}/${mqtt_remote_device1_name}"
mqtt_remote_device1_command1: "BOOST"
##########################################################################################
#:########################################################################################:#
# PACKAGES: Included Common Packages
# https://esphome.io/components/packages.html
##########################################################################################
#:########################################################################################:#
packages:
#### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode ####
common_wifi: !include
@@ -114,20 +122,21 @@ packages:
#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}
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}"
@@ -156,29 +165,32 @@ esphome:
- lambda: |-
id(relay2_forced_relay1) = false;
##########################################################################################
# ESP PLATFORM AND FRAMEWORK
#:########################################################################################:#
# ESP PLATFORM AND FRAMEWORK:
# https://esphome.io/components/esp32.html
##########################################################################################
#:########################################################################################:#
esp8266:
board: esp01_1m
early_pin_init: false # Recommended false where switches are involved.
board_flash_mode: dout # Default is dout
##########################################################################################
# LOGGING
#:########################################################################################:#
# LOGGING:
# https://esphome.io/components/logger.html
##########################################################################################
#:########################################################################################:#
logger:
level: "${log_level}" # INFO Level suggested, or DEBUG for testing
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
##########################################################################################
# GLOBAL VARIABLES
#:########################################################################################:#
# GLOBAL VARIABLES:
# https://esphome.io/guides/automations.html?highlight=globals#global-variables
##########################################################################################
#:########################################################################################:#
globals:
# Tracks if Relay_2 forced Relay_1 ON (so we can decide if Relay_1 should turn OFF when Relay_2 turns OFF)
- id: relay2_forced_relay1
@@ -213,20 +225,21 @@ globals:
restore_value: no
initial_value: "0"
##########################################################################################
# STATUS LED
#:########################################################################################:#
# STATUS LED:
# https://esphome.io/components/status_led.html
##########################################################################################
#:########################################################################################:#
# Status LED for KS-811 is gpio2
##########################################################################################
status_led:
pin:
number: GPIO2
inverted: yes
##########################################################################################
# SENSORS
##########################################################################################
#:########################################################################################:#
# SENSORS:
#:########################################################################################:#
sensor:
- platform: template
name: "${entity_prefix} Fan Remaining Minutes"
@@ -253,10 +266,11 @@ text_sensor:
snprintf(buf, sizeof(buf), "%d:%02d", m, s);
return std::string(buf);
##########################################################################################
# MQTT COMMANDS
#:########################################################################################:#
# MQTT: Device-specific MQTT command triggers
# This adds device-specific MQTT command triggers to the common MQTT configuration.
##########################################################################################
#:########################################################################################:#
mqtt:
on_message:
# Fan control: ON / OFF / 1..60 minutes (timer only if fan already ON)
@@ -307,9 +321,10 @@ mqtt:
ESP_LOGW("mqtt", "Ignoring payload '%s' on %s", p.c_str(), "${mqtt_local_command1_topic}");
}
##########################################################################################
# SCRIPTS
##########################################################################################
#:########################################################################################:#
# SCRIPTS:
#:########################################################################################:#
script:
# Starts/restarts mm:ss countdown, and optionally turns fan ON (used for MQTT ON / auto-start)
- id: relay_1_delayed_off
@@ -344,12 +359,12 @@ script:
then:
- switch.turn_on: Relay_1
##########################################################################################
# BINARY SENSORS
#:########################################################################################:#
# BINARY SENSORS:
# https://esphome.io/components/binary_sensor/
##########################################################################################
#:########################################################################################:#
# Buttons for KS-811-2 are GPIO16, GPIO05
##########################################################################################
binary_sensor:
- platform: gpio
pin:
@@ -359,7 +374,7 @@ binary_sensor:
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only suppresses a warning.
name: "Button 1: Extract Fan"
on_press:
- switch.toggle: "Relay_1"
- switch.toggle: Relay_1
- platform: gpio
pin:
@@ -372,30 +387,30 @@ binary_sensor:
- delayed_off: 20ms
on_multi_click:
# -- Single click: one quick press & release --
# Double click: easier to hit; also prevents single-click heater toggle from stealing the first click
- timing:
- ON for at most 400ms
- OFF for at least 200ms
then:
- switch.toggle: "Relay_2"
# -- Double click: two quick presses/releases --
- timing:
- ON for at most 400ms
- OFF for at most 400ms
- ON for at most 400ms
- OFF for at least 200ms
- ON for at most 500ms
- OFF for at most 900ms
- ON for at most 500ms
- OFF for at least 250ms
then:
- mqtt.publish:
topic: "${mqtt_remote_device1_command_topic}"
payload: "${mqtt_remote_device1_command1}"
##########################################################################################
# SWITCH COMPONENT
# Single click: delayed recognition so a (slower) double-click still works reliably
- timing:
- ON for at most 600ms
- OFF for at least 1200ms
then:
- switch.toggle: Relay_2
#:########################################################################################:#
# SWITCH COMPONENT:
# https://esphome.io/components/switch/
##########################################################################################
#:########################################################################################:#
# Relays for KS-811-2 are GPIO13, GPIO12
##########################################################################################
switch:
- platform: gpio
name: "Relay 1: Extract Fan"
@@ -478,12 +493,12 @@ switch:
then:
- switch.turn_off: Relay_1
##########################################################################################
# INTERVAL COMPONENT
#:########################################################################################:#
# INTERVAL COMPONENT:
# https://esphome.io/components/interval/
##########################################################################################
#:########################################################################################:#
# Assurance: if Relay_2 (Heater) is ever on, check that Relay_1 (Fan) is on also
##########################################################################################
interval:
- interval: 1s
then:
+13 -12
View File
@@ -145,15 +145,16 @@ substitutions:
mains_daily_min_365_name: "Main Power Daily Energy Min (365d)"
# 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"
ev_month_name: "EV Wallcharger Energy This Month"
ev_last_month_name: "EV Wallcharger Energy Last Month"
ev_year_name: "EV Wallcharger Energy This Year"
ev_last_year_name: "EV Wallcharger Energy Last Year"
ev_charger_name: "32A Wallcharger"
ev_power_name: "${ev_charger_name} Power"
ev_charging_name: "${ev_charger_name} Charging"
ev_total_energy_name: "${ev_charger_name} Total Energy"
ev_today_name: "${ev_charger_name} Energy Today"
ev_yesterday_name: "${ev_charger_name} Energy Yesterday"
ev_month_name: "${ev_charger_name} Energy This Month"
ev_last_month_name: "${ev_charger_name} Energy Last Month"
ev_year_name: "${ev_charger_name} Energy This Year"
ev_last_year_name: "${ev_charger_name} Energy Last Year"
# Names - Environment
temp_name: "Main Power Monitor Temperature"
@@ -1252,9 +1253,9 @@ script:
#:########################################################################################:#
# SWITCHES:
#:########################################################################################:#
switch:
- platform: restart
name: "Main Power Monitor Restart"
#switch:
# - platform: restart
# name: "Main Power Monitor Restart"
#:########################################################################################:#
# ROLLBACK COPY (v1.1) - EV POWER SECTION (for quick revert)
+58 -59
View File
@@ -1,25 +1,25 @@
mqtt:
sensor:
- unique_id: 32a_ev_wallcharger_power
name: "32A EV Wallcharger Power"
device_class: power
unit_of_measurement: kW
state_topic: "stat/tasmo-wemosd1-7280-powermon-1/EnergyMeterCount"
value_template: "{{ value_json.EVChargerWhCount * 2 * 60 / 1000 }}"
- unique_id: 16a_ev_wallcharger_power
name: "16A EV Wallcharger Power"
device_class: power
unit_of_measurement: kW
state_topic: "stat/tasmo-s4chan-7594-garage-1/EnergyMeterCount"
value_template: "{{ value_json.EVChargerWhCount * 2 * 60 / 1000 }}"
#mqtt:
# sensor:
# - unique_id: 32a_ev_wallcharger_power
# name: "32A EV Wallcharger Power"
# device_class: power
# unit_of_measurement: kW
# state_topic: "stat/tasmo-wemosd1-7280-powermon-1/EnergyMeterCount"
# value_template: "{{ value_json.EVChargerWhCount * 2 * 60 / 1000 }}"
# - unique_id: 16a_ev_wallcharger_power
# name: "16A EV Wallcharger Power"
# device_class: power
# unit_of_measurement: kW
# state_topic: "stat/tasmo-s4chan-7594-garage-1/EnergyMeterCount"
# value_template: "{{ value_json.EVChargerWhCount * 2 * 60 / 1000 }}"
# Use the Riemann sum integral to calculate energy in kWh
# from the contimuous power measuring sensors
sensor:
- platform: integration
unique_id: 32a_ev_wallcharger_power_total
name: "32A EV Wallcharger Power Total"
source: sensor.32a_ev_wallcharger_power
name: "EV 32A Wallcharger Power Total (Integral)"
source: sensor.main_house_3_phase_power_monitor_32a_wallcharger_power
#device_class: energy
#unit_of_measurement: Wh
#unit_time: h
@@ -27,22 +27,22 @@ sensor:
round: 0 # Only need 0 decimals accuracy
- platform: integration
unique_id: 16a_ev_wallcharger_power_total
name: "16A EV Wallcharger Power Total"
source: sensor.16a_ev_wallcharger_power
name: "EV 16A EV Wallcharger Power Total (Integral)"
source: sensor.garage_db_control_16a_wallcharger_power
#device_class: energy
#unit_of_measurement: Wh
#unit_time: h
#unit_prefix: k
round: 0
- platform: filter
name: "32A EV Charger Power 1m Avg"
unique_id: ev_charger_32a_power_1m_avg
entity_id: sensor.main_house_3_phase_power_monitor_ev_wallcharger_power
filters:
- filter: time_simple_moving_average
window_size: "00:01"
precision: 3
# - platform: filter
# name: "32A EV Charger Power 1m Avg"
# unique_id: ev_charger_32a_power_1m_avg
# entity_id: sensor.main_house_3_phase_power_monitor_ev_wallcharger_power
# filters:
# - filter: time_simple_moving_average
# window_size: "00:01"
# precision: 3
input_select:
leaf_ev_charging_mode:
@@ -71,36 +71,35 @@ automation:
"1hr top-up now":"boost", "Charge now until full":"now-full", "Stop charging now":"stop" } %} {% set dta = trigger.to_state.state %}
{{ mapping[dta] }}
'
template:
- trigger:
- platform: time_pattern
seconds: "/10"
- platform: homeassistant
event: start
binary_sensor:
- name: "32A EV Charger Charging"
unique_id: ev_charger_32a_charging
icon: mdi:car-electric
state: >-
{{ states('sensor.32a_ev_charger_power_1m_avg') | float(0) > 0.1 }}
delay_on:
seconds: 60
delay_off:
seconds: 60
- name: "16A EV Charger Charging"
unique_id: ev_charger_16a_charging
icon: mdi:car-electric
state: >-
{{ (states('sensor.16a_ev_wallcharger_power') | float(0)) > 0.1 }}
delay_on:
seconds: 60
delay_off:
seconds: 60
- binary_sensor:
- name: 32A EV Charger Charging UI
unique_id: ev_charger_charging_ui
state: "{{ is_state('sensor.32a_ev_charger_charging', 'on') }}"
icon: mdi:car-electric
#template:
# - trigger:
# - platform: time_pattern
# seconds: "/10"
# - platform: homeassistant
# event: start
# binary_sensor:
# - name: "32A EV Charger Charging"
# unique_id: ev_charger_32a_charging
# icon: mdi:car-electric
# state: >-
# {{ states('sensor.32a_ev_charger_power_1m_avg') | float(0) > 0.1 }}
# delay_on:
# seconds: 60
# delay_off:
# seconds: 60
#
# - name: "16A EV Charger Charging"
# unique_id: ev_charger_16a_charging
# icon: mdi:car-electric
# state: >-
# {{ (states('sensor.16a_ev_wallcharger_power') | float(0)) > 0.1 }}
# delay_on:
# seconds: 60
# delay_off:
# seconds: 60
#
# - binary_sensor:
# - name: 32A EV Charger Charging UI
# unique_id: ev_charger_charging_ui
# state: "{{ is_state('sensor.32a_ev_charger_charging', 'on') }}"
# icon: mdi:car-electric