diff --git a/esphome/esp-maindishwasherspower.yaml b/esphome/archive/esp-maindishwasherspower.yaml similarity index 100% rename from esphome/esp-maindishwasherspower.yaml rename to esphome/archive/esp-maindishwasherspower.yaml diff --git a/esphome/esp-poollightspower.yaml b/esphome/archive/esp-poollightspower.yaml similarity index 99% rename from esphome/esp-poollightspower.yaml rename to esphome/archive/esp-poollightspower.yaml index da2b9de..3857574 100644 --- a/esphome/esp-poollightspower.yaml +++ b/esphome/archive/esp-poollightspower.yaml @@ -97,8 +97,8 @@ packages: file: common/api_common.yaml vars: local_api_key: "${api_key}" - #common_webportal: !include - # file: common/webportal_common.yaml + common_webportal: !include + file: common/webportal_common.yaml common_mqtt: !include file: common/mqtt_common.yaml vars: diff --git a/esphome/common/network_common.yaml b/esphome/common/network_common.yaml index 5395de0..7e8523c 100644 --- a/esphome/common/network_common.yaml +++ b/esphome/common/network_common.yaml @@ -27,7 +27,7 @@ substitutions: static_ip_dns2: !secret ha_wifi_dns2 # Network reconnect every x hours to ensure best access point - base_interval_hours: "6" # Base interval in hours + base_interval_hours: "23" # Base interval in hours random_offset_max_minutes: "59" # Max random offset in minutes ############################################# diff --git a/esphome/esp-6buttontest-pmb.yaml b/esphome/esp-6buttontest-pmb.yaml new file mode 100644 index 0000000..1fb697d --- /dev/null +++ b/esphome/esp-6buttontest-pmb.yaml @@ -0,0 +1,430 @@ +########################################################################################## +########################################################################################## +# PMB Electronics 6 Button ESP32 Switch +# V1.0 2025-08-04 Initial Version +########################################################################################## +# PMB Details Page https://rcbeacon.com/blog/?p=5488 +# NOTES +# 1. To Flash via ESPHome, you likely have to connect to the computer, start the flash +# process then hold down the I00 button. I think GPIO12 is preventing the flash process +# 2. OTA flash to an Existing Tasmota device is likely a bit hard with and ESP32 as they +# expect a signed Tasmota binary... and partition layout needs to be fixed anyway +# +# +########################################################################################## +########################################################################################## + +########################################################################################## +# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS +# If NOT using a secrets file, just replace "!secret my_key" with the password etc (in quotes) +########################################################################################## +substitutions: + # Device Naming + device_name: "esp-6buttontest-pmb" #the filename should be the device_name.yaml + friendly_name: "PMB Light Switch Test" + description_comment: "Multi Button Wallswitch in standard AU/NZ flush size. 5 Buttons with LEDs and one Knob" + device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant. + + # 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-6buttontest-pmb_ip + + # 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 + pwm_freq: "1000Hz" + ledc_bits: "12" + + # Switch Naming + switch_1_name: "Red" + switch_2_name: "White" + switch_3_name: "Green" + switch_4_name: "Orange" + switch_5_name: "Blue" + switch_5b_name: "Blue (Double)" + switch_5c_name: "Blue (Hold)" + # switch_6_name: "Spare" + variable_1_name: "Dimmer" + variable_1_full_scale: "3.14" # ADC reading when at 100% (adjust after calibration) + variable_1_min_scale: "0.14" # volts at ADC for 0% (adjust after calibration) + +########################################################################################## +# PACKAGES: Included Common Packages +# https://esphome.io/components/packages.html +########################################################################################## +packages: + 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}" + common_api: !include + file: common/api_common.yaml + vars: + local_api_key: "${api_key}" + #common_webportal: !include + # file: common/webportal_common.yaml + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + common_sntp: !include + file: common/sntp_common.yaml + common_general_sensors: !include + file: common/sensors_common.yaml + vars: + local_friendly_name: "${friendly_name}" + local_update_interval: "${update_interval}" + +############################################# +# 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} + +########################################################################################## +# ESP Platform and Framework +# https://esphome.io/components/esp32.html +########################################################################################## +# Suggest using ESP-IDF Framework. Changes might need need to be cable flashed here to +# reset the partitioning +########################################################################################## +esp32: + board: esp32dev + framework: + type: esp-idf # "esp-idf" OR "arduino". + version: recommended # recommended, latest or dev + +preferences: + flash_write_interval: 5min # not too important but anything written for reboot mem will wear the flash + +############################################# +# ESPHome Logging Enable +# https://esphome.io/components/logger.html +############################################# +logger: + level: ${log_level} #INFO Level suggested, or DEBUG for testing + +########################################################################################## +# STATUS LED +# https://esphome.io/components/status_led.html +########################################################################################## +# This is usually the blue LED on the ESP32 Dev board +# Status_LED can show ESPHome errors and warnings +########################################################################################## +status_led: + pin: + number: GPIO2 + inverted: yes + +########################################################################################## +# BINARY SENSORS +# https://esphome.io/components/binary_sensor/ +########################################################################################## +# These are the input buttons on GPIO. +# No "mode: INPUT_PULLUP" needed as they have external pullups +# Switches pull to GND so "inverted:true" for espHome to report ON when pressed. +# They will toggle the virtual relays when pressed (the vrelays will toggle the LEDs) +########################################################################################## +binary_sensor: + - platform: gpio + pin: + number: GPIO19 + mode: INPUT + inverted: true + name: "Button 1: ${switch_1_name}" + filters: + - delayed_on: 50ms + - delayed_off: 50ms + on_press: + - switch.toggle: vrelay_1 + + - platform: gpio + pin: + number: GPIO35 + mode: INPUT + inverted: true + name: "Button 2: ${switch_2_name}" + filters: + - delayed_on: 50ms + - delayed_off: 50ms + on_press: + - switch.toggle: vrelay_2 + + - platform: gpio + pin: + number: GPIO05 + mode: INPUT + inverted: true + name: "Button 3: ${switch_3_name}" + filters: + - delayed_on: 50ms + - delayed_off: 50ms + on_press: + - switch.toggle: vrelay_3 + + - platform: gpio + pin: + number: GPIO33 + mode: INPUT + inverted: true + name: "Button 4: ${switch_4_name}" + filters: + - delayed_on: 50ms + - delayed_off: 50ms + on_press: + - switch.toggle: vrelay_4 + + - platform: gpio + pin: + number: GPIO16 + mode: INPUT + inverted: true + name: "Button 5: ${switch_5_name}" + # No delayed_on/off here to allow accurate multi-click timing + on_multi_click: + # Double click first + - timing: + - ON for 50ms to 500ms + - OFF for 50ms to 500ms + - ON for 50ms to 500ms + then: + - switch.toggle: vrelay_5b + + # Hold + - timing: + - ON for at least 2s + then: + - switch.toggle: vrelay_5c + + # Single click + - timing: + - ON for 50ms to 500ms + - OFF for at least 300ms + then: + - switch.toggle: vrelay_5 + + #- platform: gpio + # pin: + # number: GPIO12 + # mode: INPUT + # inverted: true + # name: "Button 6: ${switch_6_name}" + # filters: + # - delayed_on: 50ms + # - delayed_off: 50ms + # on_press: + # - switch.toggle: vrelay_6 + +########################################################################################## +# 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 +# We could change frequency: "100Hz" and/or resolution: "12", but these are the default. +########################################################################################## +output: + - platform: ledc + id: led1_output + pin: GPIO21 + frequency: ${pwm_freq} + - platform: ledc + id: led2_output + pin: GPIO25 + frequency: ${pwm_freq} + - platform: ledc + id: led3_output + pin: GPIO18 + frequency: ${pwm_freq} + - platform: ledc + id: led4_output + pin: GPIO26 + frequency: ${pwm_freq} + - platform: ledc + id: led5_output + pin: GPIO17 + frequency: ${pwm_freq} + +########################################################################################## +# LIGHT COMPONENT +# https://esphome.io/components/light/index.html +########################################################################################## +# We are just going to use simple monochromatic component as only one colour to PWM control +# This doesn't actually do anything by itself, you need to tied it to an OUTPUT component. +########################################################################################## +light: + - platform: monochromatic + id: led1 + output: led1_output + name: "LED 1: ${switch_1_name}" + - platform: monochromatic + id: led2 + output: led2_output + name: "LED 2: ${switch_2_name}" + - platform: monochromatic + id: led3 + output: led3_output + name: "LED 3: ${switch_3_name}" + - platform: monochromatic + id: led4 + output: led4_output + name: "LED 4: ${switch_4_name}" + - platform: monochromatic + id: led5 + output: led5_output + name: "LED 5: ${switch_5_name}" + effects: + - strobe: + name: "Pulse 0.5s" + colors: + - state: ON + brightness: 100% + duration: 500ms + - state: OFF + duration: 500ms + +########################################################################################## +# SWITCH COMPONENT +# https://esphome.io/components/switch/ +########################################################################################## +# Normally SWITCH would be for things like a relay output and turning that on and off. +# We are using it for virtual relays, that show up in Home Assistant etc, and toggling +# them along with the LEDs when the buttons are pressed. +# Separating them from the LEDs as outputs means we can do thinks like light blinking etc +# but still leave the switch outputs toggled on or off. +########################################################################################## +switch: + - platform: template + name: "Output 1: ${switch_1_name}" + id: vrelay_1 + restore_mode: RESTORE_DEFAULT_OFF + turn_on_action: + - light.turn_on: led1 + turn_off_action: + - light.turn_off: led1 + + - platform: template + name: "Output 2: ${switch_2_name}" + id: vrelay_2 + restore_mode: RESTORE_DEFAULT_OFF + turn_on_action: + - light.turn_on: led2 + turn_off_action: + - light.turn_off: led2 + + - platform: template + name: "Output 3: ${switch_3_name}" + id: vrelay_3 + restore_mode: RESTORE_DEFAULT_OFF + turn_on_action: + - light.turn_on: led3 + turn_off_action: + - light.turn_off: led3 + + - platform: template + name: "Output 4: ${switch_4_name}" + id: vrelay_4 + restore_mode: RESTORE_DEFAULT_OFF + turn_on_action: + - light.turn_on: led4 + turn_off_action: + - light.turn_off: led4 + + - platform: template + name: "Output 5: ${switch_5_name}" + id: vrelay_5 + restore_mode: RESTORE_DEFAULT_OFF + turn_on_action: + - light.turn_on: led5 + turn_off_action: + - light.turn_off: led5 + + - platform: template + name: "Output 5B: ${switch_5b_name}" + id: vrelay_5b + restore_mode: RESTORE_DEFAULT_OFF + turn_on_action: + - logger.log: "vrelay_5b ON" + turn_off_action: + - logger.log: "vrelay_5b OFF" + + - platform: template + name: "Output 5C: ${switch_5c_name}" + id: vrelay_5c + restore_mode: RESTORE_DEFAULT_OFF + turn_on_action: + - light.turn_on: + id: led1 + effect: "Pulse 0.5s" + turn_off_action: + - light.turn_off: led1 + + #- platform: template + # name: "Output 6: ${switch_6_name}" + # id: vrelay_6 + # restore_mode: RESTORE_DEFAULT_OFF + # optimistic: false + # turn_on_action: + # - light.turn_on: led6 + # turn_off_action: + # - light.turn_off: led6 + + + +sensor: + # Raw ADC reading from GPIO36 + - platform: adc + pin: GPIO36 + id: dimmer_raw + name: "Dimmer Raw" + attenuation: 11db + update_interval: 0.5s + on_value: + then: + - lambda: |- + // Convert raw ADC (x) to volts + float volts = x; + + // Apply min/max calibration + float min_v = ${variable_1_min_scale}; + float max_v = ${variable_1_full_scale}; + + // Calculate percentage between min and max + float pct = ((volts - min_v) / (max_v - min_v)) * 100.0; + + // Clamp result between 0 and 100 + if (pct > 100.0) pct = 100.0; + if (pct < 0.0) pct = 0.0; + + // Publish to percentage sensor + id(dimmer_percent).publish_state(pct); + + # Percentage sensor derived from raw ADC + - platform: template + id: dimmer_percent + name: "${variable_1_name}" + unit_of_measurement: "%" + accuracy_decimals: 0 + + # External supply voltage from GPIO39 + - platform: adc + pin: GPIO39 + name: "External Supply Voltage" + id: supply_voltage + attenuation: 11db # Up to ~3.9V at ADC pin + update_interval: 2s + filters: + - calibrate_linear: + # Format: raw_value -> real_voltage_at_pin + - 0.80 -> 3.20 # Example: ADC reads 0.80 when pin is actually 3.20V + - 0.90 -> 3.60 # Example: ADC reads 0.90 when pin is actually 3.60V + - 1.00 -> 4.00 # Example: ADC reads 1.00 when pin is actually 4.00V + - multiply: 4.00 # Voltage divider ratio + unit_of_measurement: "V" \ No newline at end of file diff --git a/esphome/esp-bedrm2ceilingfan.yaml b/esphome/esp-bedrm2ceilingfan.yaml index 9ecb9bf..cf10a8e 100644 --- a/esphome/esp-bedrm2ceilingfan.yaml +++ b/esphome/esp-bedrm2ceilingfan.yaml @@ -103,13 +103,13 @@ esphome: 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 + #- 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));' diff --git a/esphome/esp-downstbedrm1lights.yaml b/esphome/esp-downstbedrm1lights.yaml index 432c8fa..289385e 100644 --- a/esphome/esp-downstbedrm1lights.yaml +++ b/esphome/esp-downstbedrm1lights.yaml @@ -122,7 +122,7 @@ logger: ######################################################################################### status_led: pin: - number: GPIO2 + number: GPIO02 inverted: yes ######################################################################################### diff --git a/esphome/esp-downstbedrm2lights.yaml b/esphome/esp-downstbedrm2lights.yaml index 92f491a..1de3f39 100644 --- a/esphome/esp-downstbedrm2lights.yaml +++ b/esphome/esp-downstbedrm2lights.yaml @@ -122,7 +122,7 @@ logger: ######################################################################################### status_led: pin: - number: GPIO2 + number: GPIO02 inverted: yes ######################################################################################### @@ -134,7 +134,7 @@ binary_sensor: # it is a single button KS-811 in which case it is GPIO00 - platform: gpio pin: - number: GPIO00 + number: GPIO0 mode: INPUT inverted: True name: "Button 1: ${switch_1_name}" @@ -166,10 +166,10 @@ binary_sensor: # https://esphome.io/components/switch/ ######################################################################################### switch: -# GPIO13 for KS-811 first button +# GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GIPO12 - platform: gpio name: "Relay 1: ${switch_1_name}" - pin: GPIO13 + pin: GPIO12 id: Relay_1 # GPIO12 for second relay (only for KS-811-2 Double or -3 Triple) diff --git a/esphome/esp-downstloungeentry.yaml b/esphome/esp-downstloungeentry.yaml new file mode 100644 index 0000000..632bf7d --- /dev/null +++ b/esphome/esp-downstloungeentry.yaml @@ -0,0 +1,224 @@ +########################################################################################## +########################################################################################## +# 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/ +# +# NOTES +# - +# +########################################################################################## +########################################################################################## + +########################################################################################## +# 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-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. + + # 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 + + # 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-downstloungeentry_ip + mqtt_command_main_topic: !secret mqtt_local_command_main_topic + mqtt_status_main_topic: !secret mqtt_local_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 + + # 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 + + # 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_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 +########################################################################################## +packages: + 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}" + common_api: !include + file: common/api_common.yaml + vars: + local_api_key: "${api_key}" + #common_webportal: !include + # file: common/webportal_common.yaml + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + common_sntp: !include + file: common/sntp_common.yaml + common_general_sensors: !include + file: common/sensors_common.yaml + vars: + local_friendly_name: "${friendly_name}" + local_update_interval: "${update_interval}" + +######################################################################################### +# 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}" + #on_boot: + # priority: 200 + # then: + # - switch.turn_on: Relay_2 + +######################################################################################### +# ESP Platform and Framework +# https://esphome.io/components/esp32.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 + +######################################################################################### +# 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 + +########################################################################################## +# MQTT COMMANDS +# This adds device-specific MQTT command triggers to the common MQTT configuration. +########################################################################################## +mqtt: + on_message: + - 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 + 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 + 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 + - platform: gpio + pin: + number: GPIO0 + mode: INPUT + inverted: True + name: "Button 1: ${switch_1_name}" + on_press: + - mqtt.publish: + topic: "${mqtt_remote_device_command_topic}" + payload: !lambda |- + if (id(Relay_1).state) { + return "${mqtt_remote_device_command_off}"; + } else { + 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 +# https://esphome.io/components/switch/ +######################################################################################### +switch: +# 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 + + diff --git a/esphome/esp-downstloungemain.yaml b/esphome/esp-downstloungemain.yaml new file mode 100644 index 0000000..4931de4 --- /dev/null +++ b/esphome/esp-downstloungemain.yaml @@ -0,0 +1,221 @@ +########################################################################################## +########################################################################################## +# 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/ +# +# NOTES +# - +# +########################################################################################## +########################################################################################## + +########################################################################################## +# 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-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. + + # 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 + + # 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-downstloungemain_ip + mqtt_command_main_topic: !secret mqtt_local_command_main_topic + mqtt_status_main_topic: !secret mqtt_local_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 + + # 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 REMOTE Controls + + # Switch/Relay/Button Naming & Icons + #relay_icon: "mdi:lightbulb-group" + 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: + 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}" + common_api: !include + file: common/api_common.yaml + vars: + local_api_key: "${api_key}" + #common_webportal: !include + # file: common/webportal_common.yaml + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + common_sntp: !include + file: common/sntp_common.yaml + common_general_sensors: !include + file: common/sensors_common.yaml + vars: + local_friendly_name: "${friendly_name}" + local_update_interval: "${update_interval}" + +######################################################################################### +# 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}" + #on_boot: + # priority: 200 + # then: + # - switch.turn_on: Relay_2 + +######################################################################################### +# ESP Platform and Framework +# https://esphome.io/components/esp32.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 + +######################################################################################### +# 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 + +########################################################################################## +# MQTT COMMANDS +# This adds device-specific MQTT command triggers to the common MQTT configuration. +########################################################################################## +mqtt: + on_message: + # Light control + - topic: "${mqtt_local_command_topic}/light1/set" + payload: "On" + then: + - switch.turn_on: Relay_1 + - topic: "${mqtt_local_command_topic}/light1/set" + payload: "Off" + 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 a single button KS-811 in which case it is GPIO00 + - platform: gpio + pin: + number: GPIO16 + mode: INPUT + inverted: True + 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}"; + # } + +# 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 +# https://esphome.io/components/switch/ +######################################################################################### +switch: +# GPIO13 for KS-811 first button UNLESS it is KS-811-1 then it is GIPO12 + - platform: gpio + name: "Relay 1: ${switch_1_name}" + pin: GPIO13 + id: Relay_1 + # publish status updates when the light turns on/off: + on_turn_on: + - mqtt.publish: + topic: "${mqtt_local_status_topic}/light1/state" + payload: "On" + on_turn_off: + - mqtt.publish: + topic: "${mqtt_local_status_topic}/light1/state" + payload: "Off" + + +# 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 + + diff --git a/esphome/esp-downstloungeoutside.yaml b/esphome/esp-downstloungeoutside.yaml new file mode 100644 index 0000000..6668ec4 --- /dev/null +++ b/esphome/esp-downstloungeoutside.yaml @@ -0,0 +1,187 @@ +########################################################################################## +########################################################################################## +# 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/ +# +# NOTES +# - +# +########################################################################################## +########################################################################################## + +########################################################################################## +# 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-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. + + # 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 + + # 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-downstloungeoutside_ip + #mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic + #mqtt_local_status_main_topic: !secret mqtt_local_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 + + # 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: "Outside Lights" + switch_2_name: "Spare" + #switch_3_name: "Nil" + +######################################################################################### +# PACKAGES: Included Common Packages +# https://esphome.io/components/packages.html +########################################################################################## +packages: + 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}" + common_api: !include + file: common/api_common.yaml + vars: + local_api_key: "${api_key}" + #common_webportal: !include + # file: common/webportal_common.yaml + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + common_sntp: !include + file: common/sntp_common.yaml + common_general_sensors: !include + file: common/sensors_common.yaml + vars: + local_friendly_name: "${friendly_name}" + local_update_interval: "${update_interval}" + +######################################################################################### +# 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}" + #on_boot: + # priority: 200 + # then: + # - switch.turn_on: Relay_2 + +######################################################################################### +# ESP Platform and Framework +# https://esphome.io/components/esp32.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 + +######################################################################################### +# 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 + +######################################################################################### +# 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: +# GPIO16 for KS-811 first button UNLESS +# it is a single button KS-811 in which case it is GPIO00 + - platform: gpio + pin: + number: GPIO16 + mode: INPUT + inverted: True + 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) + - 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 +# https://esphome.io/components/switch/ +######################################################################################### +switch: +# GPIO13 for KS-811 first button + - 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) + - 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 + + diff --git a/esphome/esp-maindishwasherpower.yaml b/esphome/esp-maindishwasherpower.yaml new file mode 100644 index 0000000..6be2108 --- /dev/null +++ b/esphome/esp-maindishwasherpower.yaml @@ -0,0 +1,166 @@ +########################################################################################## +########################################################################################## +# MAIN DISHWASHER POWER +# Controlled by a Athom Smart Plug V3 +# package_import_url: github://athom-tech/athom-configs/athom-smart-plug.yaml +# +# V3.4 2025-07-30 Changed to Athom V3 +# V1.1 2025-06-12 package added for energy entities +# V1.0 2025-06-10 YAML Tidyups +# +########################################################################################## +########################################################################################## + +########################################################################################## +# 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-maindishwasherpower" + friendly_name: "Main Dishwasher Power" + description_comment: "Main Dishwasher Power Monitor :: Athom Smart Plug Power Monitor V3" + device_area: "Kitchen" # 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: "v1.1" # Project V denotes release of yaml file, allowing checking of deployed vs latest version + + # Passwords + api_key: !secret esp-maindishwasherpower_api_key # unfortunately you can't use substitutions inside secrets names + ota_pass: !secret esp-maindishwasherpower_ota_pass # unfortunately you can't use substitutions inside secrets names + static_ip_address: !secret esp-maindishwasherpower_ip + + # 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 + + # Device Settings + relay_icon: "mdi:dishwasher" + 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: + 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}" + common_api: !include + file: common/api_common.yaml + vars: + local_api_key: "${api_key}" + #common_webportal: !include + # file: common/webportal_common.yaml + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + common_sntp: !include + file: common/sntp_common.yaml + common_general_sensors: !include + file: common/sensors_common.yaml + vars: + local_friendly_name: "${friendly_name}" + local_update_interval: "${update_interval}" + + # Device Specific included packages + common_athompowermonV3: !include + file: common/athompowermonv3_common.yaml + vars: + local_current_limit: "${current_limit}" + +########################################################################################## +# 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 + min_version: 2024.6.0 + project: + name: "${project_name}" + version: "${project_version}" + platformio_options: + board_build.mcu: esp32c3 + board_build.variant: esp32c3 + board_build.flash_mode: dio + on_boot: + priority: 200 + then: + - switch.turn_on: "relay" + +########################################################################################## +# ESP Platform and Framework +# https://esphome.io/components/esp32.html +########################################################################################## +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 + +preferences: + flash_write_interval: 5min + +esp32_improv: + authorizer: none + +########################################################################################## +# ESPHome 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 + +########################################################################################## +# BINARY SENSORS +# https://esphome.io/components/binary_sensor/ +########################################################################################## +binary_sensor: + - platform: gpio + pin: + number: GPIO03 + mode: INPUT_PULLUP + inverted: true + name: "Power Button" + id: power_button + filters: + - delayed_on: 20ms + on_click: + - min_length: 20ms + max_length: 500ms + then: + - switch.toggle: + id: relay + + - platform: template + name: "Relay Status" + lambda: |- + return id(relay).state; + +################################################################################################# +# SWITCH COMPONENT +# https://esphome.io/components/switch/ +################################################################################################# +switch: + - platform: gpio + name: "Power Output" + pin: GPIO05 + id: relay + restore_mode: RESTORE_DEFAULT_ON # Ensures the relay is restored (or off) at boot + #internal: true # Hides the switch from Home Assistant + icon: "${relay_icon}" + diff --git a/esphome/esp-poollightpower.yaml b/esphome/esp-poollightpower.yaml new file mode 100644 index 0000000..a28e3d9 --- /dev/null +++ b/esphome/esp-poollightpower.yaml @@ -0,0 +1,693 @@ +########################################################################################## +########################################################################################## +# POOL LIGHT POWER AND TIMER +# Controlled by a Athom Smart Plug V1 +# +# dashboard_import: +# package_import_url: github://athom-tech/esp32-configs/athom-smart-plug.yaml +# +# V2.4 2025-06-15 Changed back to an Athom V1 (esp8266) +# V2.3 2025-06-15 Changed to an Athom V3 (esp32) +# 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) +# - 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 +# +########################################################################################## +########################################################################################## + + +########################################################################################## +# 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-poollightpower" + friendly_name: "Pool Light Power" + description_comment: "Pool Light Power :: Athom Smart Plug Power V1" + device_area: "Outside" # 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: "v2.4" # 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 + static_ip_address: !secret esp-poollightpower_ip + + # Device Settings + log_level: "INFO" # Define logging level: 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. + 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 + 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: "1140" # Default in minutes from midnight. Default 19:00 => 1140 + evening_off_default: "1350" # Default in minutes from midnight. Default 22:30 => 1350 => 1440 is midnight + +########################################################################################## +# PACKAGES: Included Common Packages +# https://esphome.io/components/packages.html +########################################################################################## +packages: + 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}" + common_api: !include + file: common/api_common.yaml + vars: + local_api_key: "${api_key}" + #common_webportal: !include + # file: common/webportal_common.yaml + common_mqtt: !include + file: common/mqtt_common.yaml + vars: + local_device_name: "${device_name}" + common_sntp: !include + file: common/sntp_common.yaml + common_general_sensors: !include + file: common/sensors_common.yaml + vars: + local_friendly_name: "${friendly_name}" + local_update_interval: "${update_interval}" + + # Device Specific included packages + common_athompowermonV1: !include + file: common/athompowermonv1_common.yaml + vars: + local_friendly_name: "${friendly_name}" + local_current_limit: "${current_limit}" + +########################################################################################## +# 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 + min_version: 2024.6.0 + project: + name: "${project_name}" + version: "${project_version}" + +########################################################################################## +# ESP Platform and Framework +# https://esphome.io/components/esp32.html +########################################################################################## +esp8266: + board: esp8285 + restore_from_flash: true # mainly for calculating cumulative energy, but not that important here + +preferences: + flash_write_interval: 10min + +mdns: + disabled: false + +########################################################################################## +# 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 + +########################################################################################## +# Global Variables for use in automations etc +# 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 + restore_value: true + initial_value: "0" + + # Counts how many consecutive boots have occurred (within X seconds) + - id: boot_count + type: int + restore_value: true + initial_value: "0" + + # 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), + - id: morning_off + type: int + restore_value: true + initial_value: "${morning_off_default}" + + # 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), + - id: evening_off + type: int + restore_value: true + initial_value: "${evening_off_default}" + + # Boost Duration (minutes), + - id: boost_duration + type: int + restore_value: true + initial_value: "${boost_duration_default}" + + #################################################### + # operation_mode: + # 0 = OFF + # 1 = ON + # 2 = TIMER + # 3 = BOOST + #################################################### + - id: operation_mode + type: int + restore_value: true + initial_value: "2" + + #################################################### + # current_mins is set if SNTP is invalid. + # We assume user powers on the device at 12:00 noon + # => 12 * 60 = 720 minutes from midnight. + #################################################### + - id: current_mins + type: int + restore_value: true + initial_value: "720" # 720 is 12:00 Noon + + #################################################### + # boost_timer: counts minutes in BOOST mode + # After 'boost_duration' minutes, revert to TIMER. + #################################################### + - id: boost_timer + type: int + restore_value: true + initial_value: "0" + +########################################################################################## +# Text Sensors +# 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'. + #################################################### + - platform: mqtt_subscribe + name: "Morning On Time Setting" + id: morning_on_topic + topic: "${mqtt_timer_topic}/morning-on" # Stored in the format HH:MM + 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" + 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 + on_value: + then: + - lambda: |- + if (x.size() == 5 && x[2] == ':') { + 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); + } else { + 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 + on_value: + then: + - lambda: |- + if (x.size() == 5 && x[2] == ':') { + 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); + } else { + 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 + on_value: + then: + - lambda: |- + if (x.size() == 5 && x[2] == ':') { + 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); + } else { + 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 + 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); + } + + #################################################### + # Subscribe to operation mode: + # OFF, ON, TIMER, BOOST + # We do case-insensitive compare using strcasecmp + # (Requires typically included in ESPHome) + #################################################### + # MQTT subscription: set mode, then immediately re-evaluate relay + - 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 + on_value: + then: + - lambda: |- + if (strcasecmp(x.c_str(), "TIMER") == 0) { + id(operation_mode) = 2; + ESP_LOGI("timer","Operation mode set to TIMER"); + } else if (strcasecmp(x.c_str(), "ON") == 0) { + id(operation_mode) = 1; + ESP_LOGI("timer","Operation mode set to ON"); + } else if (strcasecmp(x.c_str(), "OFF") == 0) { + id(operation_mode) = 0; + ESP_LOGI("timer","Operation mode set to OFF"); + } else if (strcasecmp(x.c_str(), "BOOST") == 0) { + id(operation_mode) = 3; + id(boost_timer) = 0; + ESP_LOGI("timer","Operation mode set to BOOST"); + } else { + ESP_LOGW("timer","Invalid operation mode: %s", x.c_str()); + } + - 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"}; + case 2: return {"TIMER"}; + case 3: return {"BOOST"}; + default: return {"UNKNOWN"}; + } + 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 buffer size to 8 just to be safe + // 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 buffer size to 8 just to be safe + // 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 buffer size to 8 just to be safe + // 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 +# https://esphome.io/components/binary_sensor/ +########################################################################################## +binary_sensor: + - platform: gpio + pin: + number: GPIO03 + mode: INPUT_PULLUP + inverted: true + name: "Power Button" + id: power_button + filters: + - delayed_on: 20ms + on_click: + - min_length: 20ms + max_length: 500ms + 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; + } + + - platform: template + name: "Relay Status" + lambda: |- + return id(relay).state; + +########################################################################################## +# Sensors +# https://esphome.io/components/text_sensor/index.html +########################################################################################## +sensor: + - platform: template + name: "Timeclock: Boost Duration" + id: boost_duration_time + unit_of_measurement: "mins" + accuracy_decimals: "0" + update_interval: "${update_interval}" + lambda: |- + return id(boost_duration); + + - platform: template + name: "Mins from Midnight" + id: mins_from_midnight + unit_of_measurement: "mins" + accuracy_decimals: "0" + update_interval: "${update_interval}" + internal: True # No need to show this in Home Assistant + 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" + update_interval: 5s + 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; + + +################################################################################################# +# 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}" + +################################################################################################# +# 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 + name: "Default timer settings" + id: default_timer_settings_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"); + - script.execute: evaluate_relay_state + +################################################################################################# +# SELECT COMPONENT +# https://esphome.io/components/select/index.html +################################################################################################# +select: + - platform: template + name: "Operation Mode" + id: operation_mode_select + update_interval: 5s + options: + - "OFF" + - "ON" + - "TIMER" + - "BOOST" + + # show the current mode + lambda: |- + switch (id(operation_mode)) { + case 1: return std::string("ON"); + case 2: return std::string("TIMER"); + 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 + id(boost_timer) = 0; + id(operation_mode) = 3; + } + - script.execute: evaluate_relay_state + +################################################################################################# +# 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 + { + bool should_on = false; + if (id(current_mins) >= id(morning_on) && id(current_mins) < id(morning_off)) + should_on = true; + 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 + if (!id(sntp_time).now().is_valid()) { + id(current_mins)++; + if (id(current_mins) >= 1440) id(current_mins) = 0; + } else { + auto now = id(sntp_time).now(); + id(current_mins) = now.hour * 60 + now.minute; + } + + // — 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 + diff --git a/group/basement_lights.yaml b/group/basement_lights.yaml index a6a39ce..664d009 100644 --- a/group/basement_lights.yaml +++ b/group/basement_lights.yaml @@ -1,11 +1,8 @@ basement_lights: name: Basement Lights entities: - - switch.tasmo_s4chan_4231_underhouselights_a - - switch.tasmo_s4chan_4231_underhouselights_b - - switch.tasmo_sdual_7681_officelights1_a - - switch.tasmo_sdual_7681_officelights1_b - - switch.esp_downstkitchlights_relay_1_dining_light - - switch.esp_downstkitchlights_relay_2_kitchen_light - switch.esp_officelights_relay_1_nighttime_lights - switch.esp_officelights_relay_2_daytime_lights + - switch.esp_underhouselights_underhouse_entrance_lights + - switch.esp_underhouselights_underhouse_storage_lights + - switch.esp_laundrylights_relay_1_laundry_lights diff --git a/group/foxhole_lights.yaml b/group/foxhole_lights.yaml index 4c195a0..35664c3 100644 --- a/group/foxhole_lights.yaml +++ b/group/foxhole_lights.yaml @@ -1,13 +1,14 @@ foxhole_lights: - name: Downstairs Lights - # Doesn't include the outdoor switch lights + name: Downstairs Flat Lights + # All the lights in the Downstairs flat + # Doesn't include the outdoor switch lights, or bedroom wardrobe light entities: - - switch.tasmo_ks811t_0707_downstloun_2a # Lounge Main Lights - - switch.tasmo_ks811t_0707_downstloun_2b # Lounge Wall Lights - - switch.tasmo_ks811s_3136_downstbed2_1a # Craft Room Lights - - switch.tasmo_ks811t_3642_downstbed1_1a # Main Bedroom, Main Lights - - switch.tasmo_ks811t_3642_downstbed1_1b # Main Bedroom, Wardrobe Light - - switch.tasmo_ks811t_3642_downstbed1_1c # Main Bedroom, Bedside switch - - switch.esp_downstkitchlights_relay_1_dining_light - - switch.esp_downstkitchlights_relay_2_kitchen_light - - switch.esp_downstkitchlights_relay_3_extract_fan + - switch.esp_downstloungemain_relay_1_main_lights # Lounge Main Lights + - switch.esp_downstloungemain_relay_2_back_wall_lights # Lounge Back Wall Lights + - switch.esp_downstbedrm1lights_relay_1_main_lights # Main Bedroom, Main Lights + - switch.esp_downstbedrm2lights_relay_1_main_lights # Small Bedroom Room Lights + - switch.esp_downstkitchlights_relay_2_kitchen_light # Kitchen Lights + - switch.esp_downstkitchlights_relay_1_dining_light # Dining Lights + - switch.esp_downstbathswitch_relay_1_main_lights # Bathroom main lights + - switch.esp_downstbathswitch_relay_2_cabinet_light # Bathroom Cabinet Lights + diff --git a/packages/pool_light_boost_switch.yaml b/packages/pool_light_boost_switch.yaml index f716c49..c9cebf5 100644 --- a/packages/pool_light_boost_switch.yaml +++ b/packages/pool_light_boost_switch.yaml @@ -22,12 +22,12 @@ automation: to: "on" condition: condition: state - entity_id: switch.esp_poollightspower_power_output + entity_id: switch.esp_poollightpower_power_output state: "off" action: - service: mqtt.publish data: - topic: "viewroad-commands/poollights-timer/operation" + topic: "viewroad-commands/poollight-timer/operation" payload: "BOOST" - alias: "Pool Lights → send OFF & schedule TIMER when user turns UI switch OFF" @@ -37,12 +37,12 @@ automation: to: "off" condition: condition: state - entity_id: switch.esp_poollightspower_power_output + entity_id: switch.esp_poollightpower_power_output state: "on" action: - service: mqtt.publish data: - topic: "viewroad-commands/poollights-timer/operation" + topic: "viewroad-commands/poollight-timer/operation" payload: "OFF" - service: input_boolean.turn_on data: @@ -68,12 +68,12 @@ automation: - alias: "Pool Lights → sync UI switch with real output (no MQTT)" trigger: platform: state - entity_id: switch.esp_poollightspower_power_output + entity_id: switch.esp_poollightpower_power_output action: - choose: - conditions: - condition: state - entity_id: switch.esp_poollightspower_power_output + entity_id: switch.esp_poollightpower_power_output state: "on" sequence: - service: input_boolean.turn_on @@ -84,7 +84,7 @@ automation: entity_id: input_boolean.timer_light_midnight_pending - conditions: - condition: state - entity_id: switch.esp_poollightspower_power_output + entity_id: switch.esp_poollightpower_power_output state: "off" sequence: - service: input_boolean.turn_off