various esphome changes
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
21
esphome/common/mqtt_common.yaml
Normal file
21
esphome/common/mqtt_common.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
#############################################
|
||||
# SYSTEM SPECIFIC VARIABLE SUBSTITUTIONS
|
||||
#############################################
|
||||
substitutions:
|
||||
mqtt_server: !secret ha_mqtt_server
|
||||
mqtt_username: !secret ha_mqtt_username
|
||||
mqtt_password: !secret ha_mqtt_password
|
||||
mqtt_topic: "esphome" #main topic for the mqtt server, call it what you like
|
||||
|
||||
#############################################
|
||||
# MQTT Monitoring
|
||||
# https://esphome.io/components/mqtt.html?highlight=mqtt
|
||||
# MUST also have api enabled if you enable MQTT
|
||||
#############################################
|
||||
mqtt:
|
||||
broker: ${mqtt_server}
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: false # enable entity discovery (true is default, we don't want two HA Instances)
|
||||
id: mqtt_client
|
77
esphome/common/multiclick_pushbutton_common.yaml
Normal file
77
esphome/common/multiclick_pushbutton_common.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
substitutions:
|
||||
local_gpioinvert: "True"
|
||||
local_singleclick_duration: "300000" # 5 minutes in ms
|
||||
# local_doubleclick_duration: "1800000" # 30 minutes in ms
|
||||
# local_tripleclick_duration: "7200000" # 2 hours in ms
|
||||
|
||||
#globals:
|
||||
# - id: single_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_singleclick_duration}
|
||||
# - id: double_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_doubleclick_duration}
|
||||
# - id: triple_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_tripleclick_duration}
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: ${local_gpio}
|
||||
mode: INPUT
|
||||
inverted: ${local_gpioinvert}
|
||||
name: ${local_name}
|
||||
on_multi_click:
|
||||
# Single Click: one press (short press/release)
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
if (id(Relay_3).state) {
|
||||
ESP_LOGD("button3", "Single click: Relay_3 is on, turning it off.");
|
||||
id(Relay_3).turn_off();
|
||||
} else {
|
||||
ESP_LOGD("button3", "Single click: Relay_3 is off, turning it on for %d ms.", id(single_click_delay));
|
||||
id(Relay_3).turn_on();
|
||||
delay(id(single_click_delay));
|
||||
id(Relay_3).turn_off();
|
||||
}
|
||||
# # Double Click: two quick press/release cycles
|
||||
# - timing:
|
||||
# - ON for at most 1s
|
||||
## - OFF for at most 1s
|
||||
# - ON for at most 1s
|
||||
# - OFF for at least 0.5s
|
||||
# then:
|
||||
# - lambda: |-
|
||||
# ESP_LOGD(${local_gpio}, "Double click detected: turning ",${local_relay_id}," on for %d ms.", ${local_doubleclick_duration});
|
||||
## ${local_relay_id}->turn_on();
|
||||
# delay(${local_doubleclick_duration});
|
||||
# ${local_relay_id}->turn_off();
|
||||
# # Triple Click: three quick press/release cycles
|
||||
## - timing:
|
||||
# - ON for at most 1s
|
||||
## - OFF for at most 1s
|
||||
# - ON for at most 1s
|
||||
# - OFF for at most 1s
|
||||
# - ON for at most 1s
|
||||
# - OFF for at least 0.5s
|
||||
# then:
|
||||
# - lambda: |-
|
||||
# ESP_LOGD(${local_gpio}, "Triple click detected: turning ",${local_relay_id}," on for %d ms.", ${local_tripleclick_duration});
|
||||
# ${local_relay_id}->turn_on();
|
||||
# delay(${local_tripleclick_duration});
|
||||
# ${local_relay_id}->turn_off();
|
||||
# # Hold: button held for at least 4 seconds
|
||||
# - timing:
|
||||
# - ON for at least 4s
|
||||
|
||||
## then:
|
||||
# - lambda: |-
|
||||
# ESP_LOGD(${local_gpio}, "Hold detected: turning ",${local_relay_id}," on indefinitely.");
|
||||
# ${local_relay_id}->turn_on();
|
75
esphome/common/network_common.yaml
Normal file
75
esphome/common/network_common.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
substitutions:
|
||||
##############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
wifi_ssid: !secret ha_wifi_ssid
|
||||
wifi_password: !secret ha_wifi_password
|
||||
fallback_ap_password: !secret fallback_ap_password
|
||||
|
||||
# Enables faster network connections, with last connected SSID being connected to and no full scan for SSID being undertaken
|
||||
wifi_fast_connect: "false"
|
||||
|
||||
# Define a domain for this device to use. i.e. iot.home.lan (so device will appear as athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs)
|
||||
dns_domain: ".local"
|
||||
|
||||
# Automatically add the mac address to the name
|
||||
# eg so you can use a single firmware for all devices
|
||||
add_mac_suffix: "false"
|
||||
|
||||
# Add these if we are giving it a static ip, or remove them in the Wifi section
|
||||
static_ip_subnet: !secret ha_wifi_subnet
|
||||
static_ip_gateway: !secret ha_wifi_gateway
|
||||
static_ip_dns1: !secret ha_wifi_gateway
|
||||
|
||||
#############################################
|
||||
# Common Wifi Settings
|
||||
# https://esphome.io/components/wifi.html
|
||||
#
|
||||
# Power Save mode (can reduce wifi reliability)
|
||||
# NONE (least power saving, Default for ESP8266)
|
||||
# LIGHT (Default for ESP32)
|
||||
# HIGH (most power saving)
|
||||
#############################################
|
||||
wifi:
|
||||
ssid: ${wifi_ssid}
|
||||
password: ${wifi_password}
|
||||
#power_save_mode: LIGHT # https://esphome.io/components/wifi.html#wifi-power-save-mode
|
||||
manual_ip: # optional static IP address
|
||||
static_ip: ${local_static_ip_address}
|
||||
gateway: ${static_ip_gateway}
|
||||
subnet: ${static_ip_subnet}
|
||||
dns1: ${static_ip_dns1}
|
||||
ap: # Details for fallback hotspot in case wifi connection fails https://esphome.io/components/wifi.html#access-point-mode
|
||||
ssid: ${devicename} AP
|
||||
password: ${fallback_ap_password}
|
||||
ap_timeout: 30min # Time until it brings up fallback AP. default is 1min
|
||||
# Allow rapid re-connection to previously connect WiFi SSID, skipping scan of all SSID
|
||||
fast_connect: "${wifi_fast_connect}"
|
||||
# Define dns domain / suffix to add to hostname
|
||||
domain: "${dns_domain}"
|
||||
|
||||
captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
||||
|
||||
#############################################
|
||||
# Enable the Home Assistant API
|
||||
# https://esphome.io/components/api.html
|
||||
#############################################
|
||||
api:
|
||||
encryption:
|
||||
key: ${local_api_key}
|
||||
|
||||
#############################################
|
||||
# Enable Over the Air Update Capability
|
||||
# https://esphome.io/components/ota.html?highlight=ota
|
||||
#############################################
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: ${local_ota_pass}
|
||||
|
||||
#############################################
|
||||
# Safe Mode
|
||||
# Safe mode will detect boot loops
|
||||
# https://esphome.io/components/safe_mode
|
||||
#############################################
|
||||
safe_mode:
|
@@ -0,0 +1,76 @@
|
||||
#substitutions:
|
||||
# local_gpioinvert: "True"
|
||||
# local_singleclick_duration: "300000" # 5 minutes in ms
|
||||
# local_doubleclick_duration: "1800000" # 30 minutes in ms
|
||||
# local_tripleclick_duration: "7200000" # 2 hours in ms
|
||||
|
||||
#globals:
|
||||
# - id: single_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_singleclick_duration}
|
||||
# - id: double_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_doubleclick_duration}
|
||||
# - id: triple_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_tripleclick_duration}
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: ${local_gpio}
|
||||
mode: INPUT
|
||||
inverted: True
|
||||
name: ${local_name}
|
||||
on_multi_click:
|
||||
# Single Click: one press (short press/release)
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
if (id(local_relay_id).state) {
|
||||
ESP_LOGD(id(local_gpio},"Single click: ",id(local_relay_id)," is on, turning it off.");
|
||||
id(local_relay_id).turn_off();
|
||||
} else {
|
||||
ESP_LOGD(id(local_gpio), "Single click: ",id(local_relay_id)," is off, turning it on for %d ms.", id(local_singleclick_duraton));
|
||||
id(local_relay_id).turn_on();
|
||||
delay(id(local_singleclick_duration));
|
||||
id(local_relay_id).turn_off();
|
||||
}
|
||||
# Double Click: two quick press/release cycles
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD(id(local_gpio), "Double click detected: turning ",id(local_relay_id)," on for %d ms.", id(local_doubleclick_duration));
|
||||
id(local_relay_id).turn_on();
|
||||
delay(id(local_doubleclick_duration));
|
||||
id(local_relay_id).turn_off();
|
||||
# Triple Click: three quick press/release cycles
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD(id(local_gpio), "Triple click detected: turning ",id(local_relay_id)," on for %d ms.", id(local_tripleclick_duration));
|
||||
id(local_relay_id).turn_on();
|
||||
delay(id(local_tripleclick_duration));
|
||||
id(local_relay_id).turn_off();
|
||||
# Hold: button held for at least 4 seconds
|
||||
- timing:
|
||||
- ON for at least 4s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD(id(local_gpio), "Hold detected: turning ",id(local_relay_id)," on indefinitely.");
|
||||
id(local_relay_id).turn_on();
|
@@ -0,0 +1,76 @@
|
||||
defaults:
|
||||
local_gpioinvert: "True"
|
||||
local_singleclick_duration: "300000" # 5 minutes in ms
|
||||
local_doubleclick_duration: "1800000" # 30 minutes in ms
|
||||
local_tripleclick_duration: "7200000" # 2 hours in ms
|
||||
|
||||
#globals:
|
||||
# - id: single_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_singleclick_duration}
|
||||
# - id: double_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_doubleclick_duration}
|
||||
# - id: triple_click_delay
|
||||
# type: long
|
||||
# restore_value: no
|
||||
# initial_value: ${local_tripleclick_duration}
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: ${local_gpio}
|
||||
mode: INPUT
|
||||
inverted: ${local_gpioinvert}
|
||||
name: ${local_name}
|
||||
on_multi_click:
|
||||
# Single Click: one press (short press/release)
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
if (id(${local_relay_id}).state) {
|
||||
ESP_LOGD("${local_gpio}", "Single click: ${local_relay_id} is on, turning it off.");
|
||||
id(${local_relay_id}).turn_off();
|
||||
} else {
|
||||
ESP_LOGD("${local_gpio}", "Single click: ${local_relay_id} is off, turning it on for %d ms.", id(single_click_delay));
|
||||
id(${local_relay_id}).turn_on();
|
||||
delay(id(single_click_delay));
|
||||
id(${local_relay_id}).turn_off();
|
||||
}
|
||||
# Double Click: two quick press/release cycles
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD(${local_gpio}, "Double click detected: turning ",${local_relay_id}," on for %d ms.", id(double_click_delay));
|
||||
id(${local_relay_id}).turn_on();
|
||||
delay(id(double_click_delay));
|
||||
id(${local_relay_id}).turn_off();
|
||||
# Triple Click: three quick press/release cycles
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD(${local_gpio}, "Triple click detected: turning ",${local_relay_id}," on for %d ms.", id(triple_click_delay));
|
||||
id(${local_relay_id}).turn_on();
|
||||
delay(id(triple_click_delay));
|
||||
id(${local_relay_id}).turn_off();
|
||||
# Hold: button held for at least 4 seconds
|
||||
- timing:
|
||||
- ON for at least 4s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD(${local_gpio}, "Hold detected (threshold %d ms): turning ",${local_relay_id}," on indefinitely.");
|
||||
id(${local_relay_id}).turn_on();
|
1
esphome/common/secrets copy.yaml
Normal file
1
esphome/common/secrets copy.yaml
Normal file
@@ -0,0 +1 @@
|
||||
<<: !include ../secrets.yaml
|
96
esphome/common/sensors_common.yaml
Normal file
96
esphome/common/sensors_common.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
#############################################
|
||||
# GENERAL COMMON SENSORS
|
||||
# https://esphome.io/components/sensor/
|
||||
#############################################
|
||||
sensor:
|
||||
- platform: uptime # Uptime for this device in seconds
|
||||
name: "Uptime (s): ${local_friendly_name}"
|
||||
update_interval: ${local_update_interval}
|
||||
id: uptime_sensor
|
||||
entity_category: "diagnostic"
|
||||
- platform: wifi_signal # Wifi Strength
|
||||
name: "Wifi dB: ${local_friendly_name}"
|
||||
id: wifi_signal_db
|
||||
update_interval: ${local_update_interval}
|
||||
entity_category: "diagnostic"
|
||||
- platform: copy # Reports the WiFi signal strength in %
|
||||
source_id: wifi_signal_db
|
||||
name: "WiFi Percent: ${local_friendly_name}"
|
||||
filters:
|
||||
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
|
||||
unit_of_measurement: "% Max"
|
||||
entity_category: "diagnostic"
|
||||
device_class: ""
|
||||
|
||||
#############################################
|
||||
# Text Sensors
|
||||
# https://esphome.io/components/text_sensor/index.html
|
||||
#############################################
|
||||
text_sensor:
|
||||
######################################################
|
||||
# General ESPHome Info
|
||||
######################################################
|
||||
- platform: version
|
||||
name: "Version: ${local_friendly_name}"
|
||||
entity_category: "diagnostic"
|
||||
|
||||
- platform: wifi_info
|
||||
ip_address:
|
||||
name: "IP Address: ${local_friendly_name}"
|
||||
|
||||
- platform: uptime # Uptime for this device human readable
|
||||
name: "Uptime: ${local_friendly_name}"
|
||||
icon: mdi:clock-start
|
||||
update_interval: ${local_update_interval}
|
||||
entity_category: "diagnostic"
|
||||
|
||||
######################################################
|
||||
# Creates a sensor showing when the device was last restarted
|
||||
# Uptime template sensor, and SNTP are needed
|
||||
######################################################
|
||||
#- platform: template
|
||||
# name: ${local_friendly_name} Last Restart
|
||||
# id: device_last_restart
|
||||
# icon: mdi:clock
|
||||
# entity_category: diagnostic
|
||||
# #device_class: timestamp
|
||||
|
||||
######################################################
|
||||
# Creates a sensor of the uptime of the device, in formatted days, hours, minutes and seconds
|
||||
######################################################
|
||||
#- platform: template
|
||||
# name: "Uptime"
|
||||
# entity_category: diagnostic
|
||||
# lambda: |-
|
||||
# int seconds = (id(uptime_sensor).state);
|
||||
# int days = seconds / (24 * 3600);
|
||||
# seconds = seconds % (24 * 3600);
|
||||
# int hours = seconds / 3600;
|
||||
# seconds = seconds % 3600;
|
||||
# int minutes = seconds / 60;
|
||||
# seconds = seconds % 60;
|
||||
# if ( days > 3650 ) {
|
||||
# return { "Starting up" };
|
||||
# } else if ( days ) {
|
||||
# return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
# } else if ( hours ) {
|
||||
# return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
# } else if ( minutes ) {
|
||||
# return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
# } else {
|
||||
# return { (String(seconds) +"s").c_str() };
|
||||
# }
|
||||
# icon: mdi:clock-start
|
||||
|
||||
button:
|
||||
- platform: safe_mode
|
||||
name: "Safe Mode Restart: ${local_friendly_name}"
|
||||
entity_category: "diagnostic"
|
||||
- platform: restart
|
||||
name: "Restart: ${local_friendly_name}"
|
||||
entity_category: "diagnostic"
|
||||
disabled_by_default: true
|
||||
- platform: factory_reset
|
||||
name: "FACTORY RESET: ${local_friendly_name}"
|
||||
entity_category: "diagnostic"
|
||||
disabled_by_default: true
|
@@ -137,6 +137,7 @@ mqtt:
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: False # enable entity discovery (true is default, we don't want two HA Instances)
|
||||
|
||||
# Availability Topic
|
||||
birth_message:
|
||||
|
509
esphome/esp-datapower-a.yaml
Normal file
509
esphome/esp-datapower-a.yaml
Normal file
@@ -0,0 +1,509 @@
|
||||
#############################################
|
||||
#############################################
|
||||
# Data Cupboard Power Monitor A
|
||||
# Athom Smart Plug Power Monitor ESP32-C3
|
||||
#
|
||||
# V1.0 2025-03-13 Initial Version
|
||||
#
|
||||
# based on https://github.com/athom-tech/esp32-configs/blob/main/athom-smart-plug.yaml
|
||||
#
|
||||
# SUMMARY
|
||||
# Smart plug with power moniroting. It has limited ability to
|
||||
# accidentally turn it off as it powers equipment in a data cupboard.
|
||||
# It does have the ability to turn off and back on automatically
|
||||
# a short time later, just in case a remote system reset is needed.
|
||||
# Also, the button on the side can't be bumped, you have to hold
|
||||
# it down for a few seconds to power it off.
|
||||
# The yaml code also calculates various power use summaries.
|
||||
#
|
||||
#############################################
|
||||
#############################################
|
||||
|
||||
substitutions:
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
devicename: "esp-datapower-a"
|
||||
friendly_name: "Data Cupboard Power Monitor A"
|
||||
description_comment: "Smart plug power Monitor A, Data Cupboard"
|
||||
room: "Data Cupboard" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant.
|
||||
|
||||
api_key: !secret esp-datapower-a_api_key # unfortunately you can't use substitutions inside secrets names
|
||||
ota_pass: !secret esp-datapower-a_ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
static_ip_address: !secret esp-datapower-a_ip
|
||||
|
||||
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
|
||||
|
||||
# Project Details
|
||||
project_name: "Athom Technology.Smart Plug V3"
|
||||
project_version: "v1.0.7" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
|
||||
|
||||
# Restore the relay (GPO switch) upon reboot to state:
|
||||
relay_restore_mode: RESTORE_DEFAULT_ON
|
||||
|
||||
# Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16.
|
||||
current_limit : "10"
|
||||
|
||||
# Hide the ENERGY sensor that shows kWh consumed, but with no time period associated with it. Resets when device restarted and reflashed.
|
||||
hide_energy_sensor: "true"
|
||||
# Enable or disable the use of IPv6 networking on the device
|
||||
ipv6_enable: "false"
|
||||
# Power plug icon selection. Change to reflect the type/country of powr plug in use, this will update the power plug icon shown next to the switch
|
||||
power_plug_type: "power-socket-au" # Options: power-socket-au | power-socket-ch | power-socket-de | power-socket-eu | power-socket-fr | power-socket-it | power-socket-jp | power-socket-uk | power-socket-us |
|
||||
|
||||
#############################################
|
||||
# SYSTEM SPECIFIC VARIABLE SUBSTITUTIONS
|
||||
#############################################
|
||||
|
||||
timezone: "Pacific/Auckland"
|
||||
sntp_update_interval: 6h # Set the duration between the sntp service polling
|
||||
# Network time servers https://www.ntppool.org/zone/@
|
||||
sntp_server_1: !secret ntp_server_1
|
||||
sntp_server_2: !secret ntp_server_2
|
||||
sntp_server_3: !secret ntp_server_3
|
||||
|
||||
wifi_ssid: !secret ha_wifi_ssid
|
||||
wifi_password: !secret ha_wifi_password
|
||||
fallback_ap_password: !secret fallback_ap_password
|
||||
|
||||
# Enables faster network connections, with last connected SSID being connected to and no full scan for SSID being undertaken
|
||||
wifi_fast_connect: "false"
|
||||
|
||||
# Define a domain for this device to use. i.e. iot.home.lan (so device will appear as athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs)
|
||||
dns_domain: ".local"
|
||||
|
||||
# Automatically add the mac address to the name
|
||||
# eg so you can use a single firmware for all devices
|
||||
add_mac_suffix: "false"
|
||||
|
||||
# Add these if we are giving it a static ip, or remove them in the Wifi section
|
||||
static_ip_subnet: !secret ha_wifi_subnet
|
||||
static_ip_gateway: !secret ha_wifi_gateway
|
||||
|
||||
mqtt_server: !secret ha_mqtt_server
|
||||
mqtt_username: !secret ha_mqtt_username
|
||||
mqtt_password: !secret ha_mqtt_password
|
||||
mqtt_topic: "esphome" #main topic for the mqtt server, call it what you like
|
||||
|
||||
# Add these if we are using the internal web server (this is pretty processor intensive)
|
||||
#web_server_username: !secret web_server_username
|
||||
#web_server_password: !secret web_server_password
|
||||
|
||||
#############################################
|
||||
# Included Common Packages
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
packages:
|
||||
wifi: !include common/wifi_common.yaml
|
||||
|
||||
#############################################
|
||||
# ESPHome
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
esphome:
|
||||
name: ${devicename}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: ${description_comment} #Appears on the esphome page in HA
|
||||
area: "${room}"
|
||||
name_add_mac_suffix: "${add_mac_suffix}"
|
||||
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
|
||||
|
||||
#############################################
|
||||
# ESP Platform and Framework
|
||||
# https://esphome.io/components/esp32.html
|
||||
#############################################
|
||||
#esp8266:
|
||||
# board: esp01_1m # The original sonoff basic
|
||||
esp32:
|
||||
board: esp32-c3-devkitm-1
|
||||
flash_size: 4MB
|
||||
variant: ESP32C3
|
||||
framework:
|
||||
type: arduino
|
||||
version: recommended
|
||||
|
||||
preferences:
|
||||
flash_write_interval: 5min
|
||||
|
||||
#############################################
|
||||
# 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
|
||||
|
||||
#############################################
|
||||
# Enable the Home Assistant API
|
||||
# https://esphome.io/components/api.html
|
||||
#############################################
|
||||
api:
|
||||
encryption:
|
||||
key: ${api_key}
|
||||
|
||||
#############################################
|
||||
# Enable Over the Air Update Capability
|
||||
# https://esphome.io/components/ota.html?highlight=ota
|
||||
#############################################
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: ${ota_pass}
|
||||
|
||||
#############################################
|
||||
# Safe Mode
|
||||
# Safe mode will detect boot loops
|
||||
# https://esphome.io/components/safe_mode
|
||||
#############################################
|
||||
safe_mode:
|
||||
|
||||
#############################################
|
||||
# Wifi Settings
|
||||
# https://esphome.io/components/wifi.html
|
||||
#
|
||||
# Power Save mode (can reduce wifi reliability)
|
||||
# NONE (least power saving, Default for ESP8266)
|
||||
# LIGHT (Default for ESP32)
|
||||
# HIGH (most power saving)
|
||||
#############################################
|
||||
##ifi:
|
||||
# ssid: ${wifi_ssid}
|
||||
# password: ${wifi_password}
|
||||
#power_save_mode: LIGHT # https://esphome.io/components/wifi.html#wifi-power-save-mode
|
||||
# manual_ip: # optional static IP address
|
||||
# static_ip: ${static_ip_address}
|
||||
# gateway: ${static_ip_gateway}
|
||||
# subnet: ${static_ip_subnet}
|
||||
# ap: # Details for fallback hotspot in case wifi connection fails https://esphome.io/components/wifi.html#access-point-mode
|
||||
# ssid: ${devicename} AP
|
||||
# password: ${fallback_ap_password}
|
||||
# ap_timeout: 30min # Time until it brings up fallback AP. default is 1min
|
||||
# # Allow rapid re-connection to previously connect WiFi SSID, skipping scan of all SSID
|
||||
# fast_connect: "${wifi_fast_connect}"
|
||||
# # Define dns domain / suffix to add to hostname
|
||||
# domain: "${dns_domain}"
|
||||
|
||||
#captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
||||
|
||||
#############################################
|
||||
# Real time clock time source for ESPHome
|
||||
# If it's invalid, we fall back to an internal clock
|
||||
# https://esphome.io/components/time/index.html
|
||||
# https://esphome.io/components/time/sntp
|
||||
#############################################
|
||||
time:
|
||||
- platform: sntp
|
||||
id: sntp_time
|
||||
# Define the timezone of the device
|
||||
timezone: "${timezone}"
|
||||
# Change sync interval from default 5min to 6 hours (or as set in substitutions)
|
||||
update_interval: ${sntp_update_interval}
|
||||
# Set specific sntp servers to use
|
||||
servers:
|
||||
- "${sntp_server_1}"
|
||||
- "${sntp_server_2}"
|
||||
- "${sntp_server_3}"
|
||||
# Publish the time the device was last restarted
|
||||
on_time_sync:
|
||||
then:
|
||||
# Update last restart time, but only once.
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(device_last_restart).state == "";'
|
||||
then:
|
||||
- text_sensor.template.publish:
|
||||
id: device_last_restart
|
||||
state: !lambda 'return id(sntp_time).now().strftime("%a %d %b %Y - %I:%M:%S %p");'
|
||||
|
||||
#############################################
|
||||
# MQTT Monitoring
|
||||
# https://esphome.io/components/mqtt.html?highlight=mqtt
|
||||
# MUST also have api enabled if you enable MQTT
|
||||
#############################################
|
||||
mqtt:
|
||||
broker: ${mqtt_server}
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: false # enable entity discovery (true is default, we don't want two HA Instances)
|
||||
|
||||
#############################################
|
||||
# Web Portal for display and monitoring
|
||||
# Turning this off is maybe a good idea to save resources,
|
||||
# especially on an esp8266.
|
||||
# https://esphome.io/components/web_server.html
|
||||
#############################################
|
||||
#web_server:
|
||||
# port: 80
|
||||
# auth:
|
||||
# username: ${web_server_username} # probably a good idea to secure it
|
||||
# password: ${web_server_password}
|
||||
|
||||
|
||||
|
||||
|
||||
network:
|
||||
enable_ipv6: ${ipv6_enable}
|
||||
|
||||
esp32_improv:
|
||||
authorizer: none
|
||||
|
||||
dashboard_import:
|
||||
package_import_url: github://athom-tech/esp32-configs/athom-smart-plug.yaml
|
||||
|
||||
uart:
|
||||
rx_pin: GPIO20
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
stop_bits: 1
|
||||
parity: EVEN
|
||||
|
||||
globals:
|
||||
- id: total_energy
|
||||
type: float
|
||||
restore_value: yes
|
||||
initial_value: '0.0'
|
||||
|
||||
# - id: restore_mode
|
||||
# type: int
|
||||
# restore_value: yes
|
||||
# initial_value: "2" # 0 = Always_Off. 1 = Restore_Power_Off. 2 = Always_On.
|
||||
|
||||
binary_sensor:
|
||||
- platform: status
|
||||
name: "Status"
|
||||
icon: mdi:check-network-outline
|
||||
entity_category: diagnostic
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO3
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
name: "Power Button"
|
||||
id: power_button
|
||||
disabled_by_default: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 10s
|
||||
- OFF for at least 2s
|
||||
then:
|
||||
- switch.toggle: relay
|
||||
# - timing:
|
||||
# - ON for at least 4s
|
||||
# then:
|
||||
# - button.press: Reset
|
||||
|
||||
- platform: template
|
||||
name: "Relay Status"
|
||||
lambda: |-
|
||||
return id(relay).state;
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: "Uptime Sensor"
|
||||
id: uptime_sensor
|
||||
entity_category: diagnostic
|
||||
internal: true
|
||||
|
||||
- platform: wifi_signal
|
||||
name: "WiFi Signal dB"
|
||||
id: wifi_signal_db
|
||||
update_interval: 60s
|
||||
entity_category: "diagnostic"
|
||||
|
||||
- platform: copy
|
||||
source_id: wifi_signal_db
|
||||
name: "WiFi Signal Percent"
|
||||
filters:
|
||||
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
|
||||
unit_of_measurement: "Signal %"
|
||||
entity_category: "diagnostic"
|
||||
device_class: ""
|
||||
|
||||
- platform: cse7766
|
||||
id: athom_cse7766
|
||||
current:
|
||||
name: "Current"
|
||||
icon: mdi:current-ac
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
- lambda: if (x < 0.060) return 0.0; else return x; #For the chip will report less than 3w power when no load is connected
|
||||
on_value_range:
|
||||
- above: ${current_limit}
|
||||
then:
|
||||
- switch.turn_off: relay
|
||||
|
||||
voltage:
|
||||
name: "Voltage"
|
||||
icon: mdi:sine-wave
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
power:
|
||||
name: "Power"
|
||||
id: power_sensor
|
||||
icon: mdi:power
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
- lambda: if (x < 3.0) return 0.0; else return x; #For the chip will report less than 3w power when no load is connected
|
||||
|
||||
energy:
|
||||
name: "Energy"
|
||||
id: energy
|
||||
icon: mdi:lightning-bolt
|
||||
unit_of_measurement: kWh
|
||||
filters:
|
||||
- throttle: ${update_interval}
|
||||
# Multiplication factor from W to kW is 0.001
|
||||
- multiply: 0.001
|
||||
on_value:
|
||||
then:
|
||||
- lambda: |-
|
||||
static float previous_energy_value = 0.0;
|
||||
float current_energy_value = id(energy).state;
|
||||
id(total_energy) += current_energy_value - previous_energy_value;
|
||||
previous_energy_value = current_energy_value;
|
||||
id(total_energy_sensor).update();
|
||||
|
||||
apparent_power:
|
||||
name: "Apparent Power"
|
||||
icon: mdi:power
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
reactive_power:
|
||||
name: "Reactive Power"
|
||||
icon: mdi:flash
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
power_factor:
|
||||
name: "Power Factor"
|
||||
icon: mdi:percent-outline
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
- platform: template
|
||||
name: "Total Energy"
|
||||
id: total_energy_sensor
|
||||
unit_of_measurement: kWh
|
||||
device_class: "energy"
|
||||
state_class: "total_increasing"
|
||||
icon: mdi:lightning-bolt
|
||||
accuracy_decimals: 3
|
||||
lambda: |-
|
||||
return id(total_energy);
|
||||
update_interval: ${update_interval}
|
||||
|
||||
- platform: total_daily_energy
|
||||
name: "Total Daily Energy"
|
||||
restore: true
|
||||
power_id: power_sensor
|
||||
unit_of_measurement: kWh
|
||||
icon: mdi:hours-24
|
||||
accuracy_decimals: 3
|
||||
filters:
|
||||
- multiply: 0.001
|
||||
|
||||
button:
|
||||
# - platform: restart
|
||||
# name: "Restart"
|
||||
# entity_category: config
|
||||
|
||||
# - platform: factory_reset
|
||||
# name: "Factory Reset"
|
||||
# id: Reset
|
||||
# entity_category: config
|
||||
|
||||
# - platform: safe_mode
|
||||
# name: "Safe Mode"
|
||||
# internal: false
|
||||
# entity_category: config
|
||||
|
||||
- platform: template
|
||||
name: "Turn Off Relay Temporarily"
|
||||
on_press:
|
||||
then:
|
||||
- switch.turn_off: relay
|
||||
- delay: 5s
|
||||
- switch.turn_on: relay
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
name: "Switch"
|
||||
pin: GPIO5
|
||||
id: relay
|
||||
restore_mode: ALWAYS_ON # Ensures the relay is on at boot
|
||||
internal: true # Hides the switch from Home Assistant
|
||||
#icon: mdi:${power_plug_type} # Don't need an icon if we can't see it...
|
||||
|
||||
light:
|
||||
- platform: status_led
|
||||
name: "Status LED"
|
||||
id: blue_led
|
||||
icon: mdi:lightbulb-outline
|
||||
disabled_by_default: false
|
||||
pin:
|
||||
inverted: true
|
||||
number: GPIO6
|
||||
|
||||
text_sensor:
|
||||
- platform: wifi_info
|
||||
ip_address:
|
||||
name: "IP Address"
|
||||
icon: mdi:ip-network
|
||||
entity_category: diagnostic
|
||||
ssid:
|
||||
name: "Connected SSID"
|
||||
icon: mdi:wifi-strength-2
|
||||
entity_category: diagnostic
|
||||
mac_address:
|
||||
name: "Mac Address"
|
||||
icon: mdi:network-pos
|
||||
entity_category: diagnostic
|
||||
|
||||
# Creates a sensor showing when the device was last restarted
|
||||
- platform: template
|
||||
name: 'Last Restart'
|
||||
id: device_last_restart
|
||||
icon: mdi:clock
|
||||
entity_category: diagnostic
|
||||
# device_class: timestamp
|
||||
|
||||
# Creates a sensor of the uptime of the device, in formatted days, hours, minutes and seconds
|
||||
- platform: template
|
||||
name: "Uptime"
|
||||
entity_category: diagnostic
|
||||
lambda: |-
|
||||
int seconds = (id(uptime_sensor).state);
|
||||
int days = seconds / (24 * 3600);
|
||||
seconds = seconds % (24 * 3600);
|
||||
int hours = seconds / 3600;
|
||||
seconds = seconds % 3600;
|
||||
int minutes = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
if ( days > 3650 ) {
|
||||
return { "Starting up" };
|
||||
} else if ( days ) {
|
||||
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
} else if ( hours ) {
|
||||
return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
} else if ( minutes ) {
|
||||
return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
} else {
|
||||
return { (String(seconds) +"s").c_str() };
|
||||
}
|
||||
icon: mdi:clock-start
|
||||
|
504
esphome/esp-datapower-b.yaml
Normal file
504
esphome/esp-datapower-b.yaml
Normal file
@@ -0,0 +1,504 @@
|
||||
#############################################
|
||||
#############################################
|
||||
# Data Cupboard Power Monitor B
|
||||
# Athom Smart Plug Power Monitor ESP32-C3
|
||||
#
|
||||
# V1.0 2025-03-13 Initial Version
|
||||
#
|
||||
# based on https://github.com/athom-tech/esp32-configs/blob/main/athom-smart-plug.yaml
|
||||
#
|
||||
# SUMMARY
|
||||
# Smart plug with power moniroting. It has limited ability to
|
||||
# accidentally turn it off as it powers equipment in a data cupboard.
|
||||
# It does have the ability to turn off and back on automatically
|
||||
# a short time later, just in case a remote system reset is needed.
|
||||
# Also, the button on the side can't be bumped, you have to hold
|
||||
# it down for a few seconds to power it off.
|
||||
# The yaml code also calculates various power use summaries.
|
||||
#
|
||||
#############################################
|
||||
#############################################
|
||||
|
||||
substitutions:
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
devicename: "esp-datapower-b"
|
||||
friendly_name: "Data Cupboard Power Monitor B"
|
||||
description_comment: "Smart plug power Monitor B, Data Cupboard"
|
||||
room: "Data Cupboard" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant.
|
||||
|
||||
api_key: !secret esp-datapower-b_api_key # unfortunately you can't use substitutions inside secrets names
|
||||
ota_pass: !secret esp-datapower-b_ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
static_ip_address: !secret esp-datapower-b_ip
|
||||
|
||||
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
|
||||
|
||||
# Project Details
|
||||
project_name: "Athom Technology.Smart Plug V3"
|
||||
project_version: "v1.0.7" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
|
||||
|
||||
# Restore the relay (GPO switch) upon reboot to state:
|
||||
relay_restore_mode: RESTORE_DEFAULT_ON
|
||||
|
||||
# Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16.
|
||||
current_limit : "10"
|
||||
|
||||
# Hide the ENERGY sensor that shows kWh consumed, but with no time period associated with it. Resets when device restarted and reflashed.
|
||||
hide_energy_sensor: "true"
|
||||
# Enable or disable the use of IPv6 networking on the device
|
||||
ipv6_enable: "false"
|
||||
# Power plug icon selection. Change to reflect the type/country of powr plug in use, this will update the power plug icon shown next to the switch
|
||||
power_plug_type: "power-socket-au" # Options: power-socket-au | power-socket-ch | power-socket-de | power-socket-eu | power-socket-fr | power-socket-it | power-socket-jp | power-socket-uk | power-socket-us |
|
||||
|
||||
|
||||
|
||||
#############################################
|
||||
# SYSTEM SPECIFIC VARIABLE SUBSTITUTIONS
|
||||
#############################################
|
||||
|
||||
timezone: "Pacific/Auckland"
|
||||
sntp_update_interval: 6h # Set the duration between the sntp service polling
|
||||
# Network time servers https://www.ntppool.org/zone/@
|
||||
sntp_server_1: !secret ntp_server_1
|
||||
sntp_server_2: !secret ntp_server_2
|
||||
sntp_server_3: !secret ntp_server_3
|
||||
|
||||
wifi_ssid: !secret ha_wifi_ssid
|
||||
wifi_password: !secret ha_wifi_password
|
||||
fallback_ap_password: !secret fallback_ap_password
|
||||
|
||||
# Enables faster network connections, with last connected SSID being connected to and no full scan for SSID being undertaken
|
||||
wifi_fast_connect: "false"
|
||||
|
||||
# Define a domain for this device to use. i.e. iot.home.lan (so device will appear as athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs)
|
||||
dns_domain: ".local"
|
||||
|
||||
# Automatically add the mac address to the name
|
||||
# eg so you can use a single firmware for all devices
|
||||
add_mac_suffix: "false"
|
||||
|
||||
# Add these if we are giving it a static ip, or remove them in the Wifi section
|
||||
static_ip_subnet: !secret ha_wifi_subnet
|
||||
static_ip_gateway: !secret ha_wifi_gateway
|
||||
|
||||
mqtt_server: !secret ha_mqtt_server
|
||||
mqtt_username: !secret ha_mqtt_username
|
||||
mqtt_password: !secret ha_mqtt_password
|
||||
mqtt_topic: "esphome" #main topic for the mqtt server, call it what you like
|
||||
|
||||
# Add these if we are using the internal web server (this is pretty processor intensive)
|
||||
#web_server_username: !secret web_server_username
|
||||
#web_server_password: !secret web_server_password
|
||||
|
||||
|
||||
#############################################
|
||||
# ESPHome
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
esphome:
|
||||
name: ${devicename}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: ${description_comment} #Appears on the esphome page in HA
|
||||
area: "${room}"
|
||||
name_add_mac_suffix: "${add_mac_suffix}"
|
||||
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
|
||||
|
||||
#############################################
|
||||
# ESP Platform and Framework
|
||||
# https://esphome.io/components/esp32.html
|
||||
#############################################
|
||||
#esp8266:
|
||||
# board: esp01_1m # The original sonoff basic
|
||||
esp32:
|
||||
board: esp32-c3-devkitm-1
|
||||
flash_size: 4MB
|
||||
variant: ESP32C3
|
||||
framework:
|
||||
type: arduino
|
||||
version: recommended
|
||||
|
||||
preferences:
|
||||
flash_write_interval: 5min
|
||||
|
||||
#############################################
|
||||
# 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
|
||||
|
||||
#############################################
|
||||
# Enable the Home Assistant API
|
||||
# https://esphome.io/components/api.html
|
||||
#############################################
|
||||
api:
|
||||
encryption:
|
||||
key: ${api_key}
|
||||
|
||||
#############################################
|
||||
# Enable Over the Air Update Capability
|
||||
# https://esphome.io/components/ota.html?highlight=ota
|
||||
#############################################
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: ${ota_pass}
|
||||
|
||||
#############################################
|
||||
# Safe Mode
|
||||
# Safe mode will detect boot loops
|
||||
# https://esphome.io/components/safe_mode
|
||||
#############################################
|
||||
safe_mode:
|
||||
|
||||
#############################################
|
||||
# Wifi Settings
|
||||
# https://esphome.io/components/wifi.html
|
||||
#
|
||||
# Power Save mode (can reduce wifi reliability)
|
||||
# NONE (least power saving, Default for ESP8266)
|
||||
# LIGHT (Default for ESP32)
|
||||
# HIGH (most power saving)
|
||||
#############################################
|
||||
wifi:
|
||||
ssid: ${wifi_ssid}
|
||||
password: ${wifi_password}
|
||||
#power_save_mode: LIGHT # https://esphome.io/components/wifi.html#wifi-power-save-mode
|
||||
manual_ip: # optional static IP address
|
||||
static_ip: ${static_ip_address}
|
||||
gateway: ${static_ip_gateway}
|
||||
subnet: ${static_ip_subnet}
|
||||
ap: # Details for fallback hotspot in case wifi connection fails https://esphome.io/components/wifi.html#access-point-mode
|
||||
ssid: ${devicename} AP
|
||||
password: ${fallback_ap_password}
|
||||
ap_timeout: 30min # Time until it brings up fallback AP. default is 1min
|
||||
# Allow rapid re-connection to previously connect WiFi SSID, skipping scan of all SSID
|
||||
fast_connect: "${wifi_fast_connect}"
|
||||
# Define dns domain / suffix to add to hostname
|
||||
domain: "${dns_domain}"
|
||||
|
||||
captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
||||
|
||||
#############################################
|
||||
# Real time clock time source for ESPHome
|
||||
# If it's invalid, we fall back to an internal clock
|
||||
# https://esphome.io/components/time/index.html
|
||||
# https://esphome.io/components/time/sntp
|
||||
#############################################
|
||||
time:
|
||||
- platform: sntp
|
||||
id: sntp_time
|
||||
# Define the timezone of the device
|
||||
timezone: "${timezone}"
|
||||
# Change sync interval from default 5min to 6 hours (or as set in substitutions)
|
||||
update_interval: ${sntp_update_interval}
|
||||
# Set specific sntp servers to use
|
||||
servers:
|
||||
- "${sntp_server_1}"
|
||||
- "${sntp_server_2}"
|
||||
- "${sntp_server_3}"
|
||||
# Publish the time the device was last restarted
|
||||
on_time_sync:
|
||||
then:
|
||||
# Update last restart time, but only once.
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(device_last_restart).state == "";'
|
||||
then:
|
||||
- text_sensor.template.publish:
|
||||
id: device_last_restart
|
||||
state: !lambda 'return id(sntp_time).now().strftime("%a %d %b %Y - %I:%M:%S %p");'
|
||||
|
||||
#############################################
|
||||
# MQTT Monitoring
|
||||
# https://esphome.io/components/mqtt.html?highlight=mqtt
|
||||
# MUST also have api enabled if you enable MQTT
|
||||
#############################################
|
||||
mqtt:
|
||||
broker: ${mqtt_server}
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: False # enable entity discovery (true is default, we don't want two HA Instances)
|
||||
|
||||
#############################################
|
||||
# Web Portal for display and monitoring
|
||||
# Turning this off is maybe a good idea to save resources,
|
||||
# especially on an esp8266.
|
||||
# https://esphome.io/components/web_server.html
|
||||
#############################################
|
||||
#web_server:
|
||||
# port: 80
|
||||
# auth:
|
||||
# username: ${web_server_username} # probably a good idea to secure it
|
||||
# password: ${web_server_password}
|
||||
|
||||
|
||||
|
||||
|
||||
network:
|
||||
enable_ipv6: ${ipv6_enable}
|
||||
|
||||
esp32_improv:
|
||||
authorizer: none
|
||||
|
||||
dashboard_import:
|
||||
package_import_url: github://athom-tech/esp32-configs/athom-smart-plug.yaml
|
||||
|
||||
uart:
|
||||
rx_pin: GPIO20
|
||||
baud_rate: 4800
|
||||
data_bits: 8
|
||||
stop_bits: 1
|
||||
parity: EVEN
|
||||
|
||||
globals:
|
||||
- id: total_energy
|
||||
type: float
|
||||
restore_value: yes
|
||||
initial_value: '0.0'
|
||||
|
||||
# - id: restore_mode
|
||||
# type: int
|
||||
# restore_value: yes
|
||||
# initial_value: "2" # 0 = Always_Off. 1 = Restore_Power_Off. 2 = Always_On.
|
||||
|
||||
binary_sensor:
|
||||
- platform: status
|
||||
name: "Status"
|
||||
icon: mdi:check-network-outline
|
||||
entity_category: diagnostic
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO3
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
name: "Power Button"
|
||||
id: power_button
|
||||
disabled_by_default: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 10s
|
||||
- OFF for at least 2s
|
||||
then:
|
||||
- switch.toggle: relay
|
||||
# - timing:
|
||||
# - ON for at least 4s
|
||||
# then:
|
||||
# - button.press: Reset
|
||||
|
||||
- platform: template
|
||||
name: "Relay Status"
|
||||
lambda: |-
|
||||
return id(relay).state;
|
||||
|
||||
sensor:
|
||||
- platform: uptime
|
||||
name: "Uptime Sensor"
|
||||
id: uptime_sensor
|
||||
entity_category: diagnostic
|
||||
internal: true
|
||||
|
||||
- platform: wifi_signal
|
||||
name: "WiFi Signal dB"
|
||||
id: wifi_signal_db
|
||||
update_interval: 60s
|
||||
entity_category: "diagnostic"
|
||||
|
||||
- platform: copy
|
||||
source_id: wifi_signal_db
|
||||
name: "WiFi Signal Percent"
|
||||
filters:
|
||||
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
|
||||
unit_of_measurement: "Signal %"
|
||||
entity_category: "diagnostic"
|
||||
device_class: ""
|
||||
|
||||
- platform: cse7766
|
||||
id: athom_cse7766
|
||||
current:
|
||||
name: "Current"
|
||||
icon: mdi:current-ac
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
- lambda: if (x < 0.060) return 0.0; else return x; #For the chip will report less than 3w power when no load is connected
|
||||
on_value_range:
|
||||
- above: ${current_limit}
|
||||
then:
|
||||
- switch.turn_off: relay
|
||||
|
||||
voltage:
|
||||
name: "Voltage"
|
||||
icon: mdi:sine-wave
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
power:
|
||||
name: "Power"
|
||||
id: power_sensor
|
||||
icon: mdi:power
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
- lambda: if (x < 3.0) return 0.0; else return x; #For the chip will report less than 3w power when no load is connected
|
||||
|
||||
energy:
|
||||
name: "Energy"
|
||||
id: energy
|
||||
icon: mdi:lightning-bolt
|
||||
unit_of_measurement: kWh
|
||||
filters:
|
||||
- throttle: ${update_interval}
|
||||
# Multiplication factor from W to kW is 0.001
|
||||
- multiply: 0.001
|
||||
on_value:
|
||||
then:
|
||||
- lambda: |-
|
||||
static float previous_energy_value = 0.0;
|
||||
float current_energy_value = id(energy).state;
|
||||
id(total_energy) += current_energy_value - previous_energy_value;
|
||||
previous_energy_value = current_energy_value;
|
||||
id(total_energy_sensor).update();
|
||||
|
||||
apparent_power:
|
||||
name: "Apparent Power"
|
||||
icon: mdi:power
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
reactive_power:
|
||||
name: "Reactive Power"
|
||||
icon: mdi:flash
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
power_factor:
|
||||
name: "Power Factor"
|
||||
icon: mdi:percent-outline
|
||||
filters:
|
||||
- throttle_average: ${update_interval}
|
||||
|
||||
- platform: template
|
||||
name: "Total Energy"
|
||||
id: total_energy_sensor
|
||||
unit_of_measurement: kWh
|
||||
device_class: "energy"
|
||||
state_class: "total_increasing"
|
||||
icon: mdi:lightning-bolt
|
||||
accuracy_decimals: 3
|
||||
lambda: |-
|
||||
return id(total_energy);
|
||||
update_interval: ${update_interval}
|
||||
|
||||
- platform: total_daily_energy
|
||||
name: "Total Daily Energy"
|
||||
restore: true
|
||||
power_id: power_sensor
|
||||
unit_of_measurement: kWh
|
||||
icon: mdi:hours-24
|
||||
accuracy_decimals: 3
|
||||
filters:
|
||||
- multiply: 0.001
|
||||
|
||||
button:
|
||||
# - platform: restart
|
||||
# name: "Restart"
|
||||
# entity_category: config
|
||||
|
||||
# - platform: factory_reset
|
||||
# name: "Factory Reset"
|
||||
# id: Reset
|
||||
# entity_category: config
|
||||
|
||||
# - platform: safe_mode
|
||||
# name: "Safe Mode"
|
||||
# internal: false
|
||||
# entity_category: config
|
||||
|
||||
- platform: template
|
||||
name: "Turn Off Relay Temporarily"
|
||||
on_press:
|
||||
then:
|
||||
- switch.turn_off: relay
|
||||
- delay: 5s
|
||||
- switch.turn_on: relay
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
name: "Switch"
|
||||
pin: GPIO5
|
||||
id: relay
|
||||
restore_mode: ALWAYS_ON # Ensures the relay is on at boot
|
||||
internal: true # Hides the switch from Home Assistant
|
||||
#icon: mdi:${power_plug_type} # Don't need an icon if we can't see it...
|
||||
|
||||
light:
|
||||
- platform: status_led
|
||||
name: "Status LED"
|
||||
id: blue_led
|
||||
icon: mdi:lightbulb-outline
|
||||
disabled_by_default: false
|
||||
pin:
|
||||
inverted: true
|
||||
number: GPIO6
|
||||
|
||||
text_sensor:
|
||||
- platform: wifi_info
|
||||
ip_address:
|
||||
name: "IP Address"
|
||||
icon: mdi:ip-network
|
||||
entity_category: diagnostic
|
||||
ssid:
|
||||
name: "Connected SSID"
|
||||
icon: mdi:wifi-strength-2
|
||||
entity_category: diagnostic
|
||||
mac_address:
|
||||
name: "Mac Address"
|
||||
icon: mdi:network-pos
|
||||
entity_category: diagnostic
|
||||
|
||||
# Creates a sensor showing when the device was last restarted
|
||||
- platform: template
|
||||
name: 'Last Restart'
|
||||
id: device_last_restart
|
||||
icon: mdi:clock
|
||||
entity_category: diagnostic
|
||||
# device_class: timestamp
|
||||
|
||||
# Creates a sensor of the uptime of the device, in formatted days, hours, minutes and seconds
|
||||
- platform: template
|
||||
name: "Uptime"
|
||||
entity_category: diagnostic
|
||||
lambda: |-
|
||||
int seconds = (id(uptime_sensor).state);
|
||||
int days = seconds / (24 * 3600);
|
||||
seconds = seconds % (24 * 3600);
|
||||
int hours = seconds / 3600;
|
||||
seconds = seconds % 3600;
|
||||
int minutes = seconds / 60;
|
||||
seconds = seconds % 60;
|
||||
if ( days > 3650 ) {
|
||||
return { "Starting up" };
|
||||
} else if ( days ) {
|
||||
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
} else if ( hours ) {
|
||||
return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
} else if ( minutes ) {
|
||||
return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||
} else {
|
||||
return { (String(seconds) +"s").c_str() };
|
||||
}
|
||||
icon: mdi:clock-start
|
@@ -10,27 +10,14 @@
|
||||
# INSTRUCTIONS
|
||||
# -
|
||||
#
|
||||
# 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 towel rail will go on
|
||||
# mqtt_timer_topic/morning-off/08:00 : Time towel rail will go off
|
||||
# mqtt_timer_topic/evening-on/09:00 : Time towel rail will go on
|
||||
# mqtt_timer_topic/evening-off/00:00 : Time towel rail will go off
|
||||
# mqtt_timer_topic/operation/ON : Towel rail permanently on
|
||||
# mqtt_timer_topic/operation/OFF : Towel rail permanently off
|
||||
# mqtt_timer_topic/operation/TIMER : Towel rail will obey timer settings
|
||||
# mqtt_timer_topic/operation/STARTUP : Turn on for 2 hours then TIMER (also on startup)
|
||||
#
|
||||
#############################################
|
||||
#############################################
|
||||
|
||||
substitutions:
|
||||
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
devicename: "esp-downstbathswitch"
|
||||
friendly_name: "Downstairs Bath Lightswitch"
|
||||
description_comment: "Downstairs Bathroom Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Light (1), Cabinet Light (2), Extract Fan (3)"
|
||||
@@ -39,35 +26,45 @@ substitutions:
|
||||
ota_pass: !secret esp-downstbathswitch_ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
static_ip_address: !secret esp-downstbathswitch_ip
|
||||
|
||||
#mqtt_timer_topic: "viewroad-commands/masterbath-towelrail" # Topics you will use to change stuff
|
||||
#startup_duration: "120" # Minutes to stay ON in STARTUP mode before reverting to TIMER
|
||||
#timezone: "Pacific/Auckland" # For setting clock with snmp
|
||||
|
||||
|
||||
#############################################
|
||||
# MY SYSTEM VARIABLE SUBSTITUTIONS
|
||||
#############################################
|
||||
wifi_ssid: !secret ha_wifi_ssid
|
||||
wifi_password: !secret ha_wifi_password
|
||||
fallback_ap_password: !secret fallback_ap_password
|
||||
|
||||
# Add these if we are giving it a static ip, or remove them in the Wifi section
|
||||
static_ip_subnet: !secret ha_wifi_subnet
|
||||
static_ip_gateway: !secret ha_wifi_gateway
|
||||
|
||||
mqtt_server: !secret ha_mqtt_server
|
||||
mqtt_username: !secret ha_mqtt_username
|
||||
mqtt_password: !secret ha_mqtt_password
|
||||
mqtt_topic: "esphome" #main topic for the mqtt server, call it what you like
|
||||
|
||||
# Add these if we are using the internal web server (this is pretty processor intensive)
|
||||
#web_server_username: !secret web_server_username
|
||||
#web_server_password: !secret web_server_password
|
||||
|
||||
update_interval: 60s # update time for for general sensors etc
|
||||
|
||||
#############################################
|
||||
# Included Common Packages
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
packages:
|
||||
common_wifi: !include
|
||||
file: common/network_common.yaml
|
||||
vars:
|
||||
local_static_ip_address: ${static_ip_address}
|
||||
local_api_key: ${api_key}
|
||||
local_ota_pass: ${ota_pass}
|
||||
common_mqtt: !include
|
||||
file: common/mqtt_common.yaml
|
||||
common_general_sensors: !include
|
||||
file: common/sensors_common.yaml
|
||||
vars:
|
||||
local_friendly_name: ${friendly_name}
|
||||
local_update_interval: ${update_interval}
|
||||
|
||||
|
||||
# common_multiclick_pushbutton_Switch_2: !include
|
||||
# file: common/multiclick_pushbutton_common.yaml
|
||||
# vars:
|
||||
# local_name: "Button: Light Switch 2 (Cabinet)"
|
||||
# local_gpio: GPIO05 # Switch 2 for KS-811 Triple is GPIO5
|
||||
# local_relay_id: Relay_2 # ID of relay to turn on
|
||||
# local_singleclick_duration: 7200000 # 2 hrs in ms
|
||||
# common_multiclick_pushbutton_Switch_3: !include
|
||||
# file: common/multiclick_pushbutton_common.yaml
|
||||
# vars:
|
||||
# local_name: "Button: Extract Fan"
|
||||
# local_gpio: GPIO04 # Switch 3 for KS-811 Triple is GPIO4
|
||||
# local_relay_id: Relay_3 # ID of relay to turn on
|
||||
# local_singleclick_duration: 300000 # 5 minutes in ms
|
||||
# local_doubleclick_duration: 1800000 # 30 minutes in ms
|
||||
# local_tripleclick_duration: 7200000 # 2 hours in ms
|
||||
|
||||
#############################################
|
||||
# ESPHome
|
||||
# https://esphome.io/components/esphome.html
|
||||
@@ -76,14 +73,13 @@ esphome:
|
||||
name: ${devicename}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: ${description_comment} #Appears on the esphome page in HA
|
||||
|
||||
|
||||
#############################################
|
||||
# ESP Platform and Framework
|
||||
# https://esphome.io/components/esp32.html
|
||||
#############################################
|
||||
esp8266:
|
||||
board: esp01_1m # The original sonoff basic
|
||||
board: esp01_1m
|
||||
|
||||
#############################################
|
||||
# ESPHome Logging Enable
|
||||
@@ -95,52 +91,6 @@ logger:
|
||||
#esp8266_store_log_strings_in_flash: false
|
||||
#tx_buffer_size: 64
|
||||
|
||||
#############################################
|
||||
# Enable the Home Assistant API
|
||||
# https://esphome.io/components/api.html
|
||||
#############################################
|
||||
api:
|
||||
encryption:
|
||||
key: ${api_key}
|
||||
|
||||
#############################################
|
||||
# Enable Over the Air Update Capability
|
||||
# https://esphome.io/components/ota.html?highlight=ota
|
||||
#############################################
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: ${ota_pass}
|
||||
|
||||
#############################################
|
||||
# Safe Mode
|
||||
# Safe mode will detect boot loops
|
||||
# https://esphome.io/components/safe_mode
|
||||
#############################################
|
||||
safe_mode:
|
||||
|
||||
#############################################
|
||||
# Wifi Settings
|
||||
# https://esphome.io/components/wifi.html
|
||||
#
|
||||
# Power Save mode (can reduce wifi reliability)
|
||||
# NONE (least power saving, Default for ESP8266)
|
||||
# LIGHT (Default for ESP32)
|
||||
# HIGH (most power saving)
|
||||
#############################################
|
||||
wifi:
|
||||
ssid: ${wifi_ssid}
|
||||
password: ${wifi_password}
|
||||
#power_save_mode: LIGHT # https://esphome.io/components/wifi.html#wifi-power-save-mode
|
||||
manual_ip: # optional static IP address
|
||||
static_ip: ${static_ip_address}
|
||||
gateway: ${static_ip_gateway}
|
||||
subnet: ${static_ip_subnet}
|
||||
ap: # Details for fallback hotspot in case wifi connection fails https://esphome.io/components/wifi.html#access-point-mode
|
||||
ssid: ${devicename} AP
|
||||
password: ${fallback_ap_password}
|
||||
ap_timeout: 30min # Time until it brings up fallback AP. default is 1min
|
||||
|
||||
captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
||||
|
||||
#############################################
|
||||
# Real time clock time source for ESPHome
|
||||
@@ -152,35 +102,6 @@ time:
|
||||
- platform: sntp
|
||||
id: sntp_time
|
||||
|
||||
#############################################
|
||||
# MQTT Monitoring
|
||||
# https://esphome.io/components/mqtt.html?highlight=mqtt
|
||||
# MUST also have api enabled if you enable MQTT
|
||||
#############################################
|
||||
mqtt:
|
||||
broker: ${mqtt_server}
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
#discovery: True # enable entity discovery (true is default)
|
||||
#discover_ip: True # enable device discovery (true is default)
|
||||
|
||||
#############################################
|
||||
# Global Variables for use in automations etc
|
||||
# https://esphome.io/guides/automations.html?highlight=globals#global-variables
|
||||
#############################################
|
||||
#globals:
|
||||
|
||||
#############################################
|
||||
# TEXT SENSORS
|
||||
# https://esphome.io/components/text_sensor/
|
||||
#############################################
|
||||
text_sensor:
|
||||
- platform: version
|
||||
name: ${friendly_name} Version
|
||||
- platform: wifi_info
|
||||
ip_address:
|
||||
name: ${friendly_name} IP Address
|
||||
|
||||
#############################################
|
||||
# STATUS LED
|
||||
@@ -191,6 +112,7 @@ status_led:
|
||||
number: GPIO2
|
||||
inverted: yes
|
||||
|
||||
|
||||
#############################################
|
||||
# BINARY SENSORS
|
||||
# https://esphome.io/components/binary_sensor/
|
||||
@@ -201,25 +123,107 @@ binary_sensor:
|
||||
number: GPIO16
|
||||
mode: INPUT
|
||||
inverted: True
|
||||
name: "Light Switch 1 (Main)"
|
||||
name: "Button: Light Switch 1 (Main)"
|
||||
on_press:
|
||||
- switch.toggle: Relay_1
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO05
|
||||
mode: INPUT
|
||||
inverted: True
|
||||
name: "Light Switch 2 (Cabinet)"
|
||||
name: "Button: Light Switch 2 (Cabinet)"
|
||||
on_press:
|
||||
- switch.toggle: Relay_2
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO04
|
||||
number: GPIO4
|
||||
mode: INPUT
|
||||
inverted: True
|
||||
name: "Extract Fan"
|
||||
on_press:
|
||||
- switch.toggle: Relay_3
|
||||
name: "Button: Light Switch 3 (Fan)"
|
||||
on_multi_click:
|
||||
# Single click: 1 press → relay on for 5 minutes
|
||||
- timing:
|
||||
- ON for at most 0.5s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(Relay_3).state;'
|
||||
then:
|
||||
- switch.turn_off: Relay_3
|
||||
else:
|
||||
- switch.turn_on: Relay_3
|
||||
- delay: 5min
|
||||
- switch.turn_off: Relay_3
|
||||
|
||||
# Double click: 2 presses → relay on for 30 minutes
|
||||
- timing:
|
||||
- ON for at most 0.5s
|
||||
- OFF for at most 0.5s
|
||||
- ON for at most 0.5s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(Relay_3).state;'
|
||||
then:
|
||||
- switch.turn_off: Relay_3
|
||||
else:
|
||||
- switch.turn_on: Relay_3
|
||||
- delay: 30min
|
||||
- switch.turn_off: Relay_3
|
||||
|
||||
# Triple click: 3 presses → relay on for 4 hours
|
||||
- timing:
|
||||
- ON for at most 0.5s
|
||||
- OFF for at most 0.5s
|
||||
- ON for at most 0.5s
|
||||
- OFF for at most 0.5s
|
||||
- ON for at most 0.5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(Relay_3).state;'
|
||||
then:
|
||||
- switch.turn_off: Relay_3
|
||||
else:
|
||||
- switch.turn_on: Relay_3
|
||||
- delay: 4h
|
||||
- switch.turn_off: Relay_3
|
||||
|
||||
# Hold: pressed for 1 second or more → relay toggles permanently
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(Relay_3).state;'
|
||||
then:
|
||||
- switch.turn_off: Relay_3
|
||||
else:
|
||||
- switch.turn_on: Relay_3
|
||||
|
||||
# - platform: gpio
|
||||
# pin:
|
||||
# number: GPIO04
|
||||
# mode: INPUT
|
||||
# inverted: True
|
||||
# name: "Button: Light Switch 3 (Fan)"
|
||||
# on_press:
|
||||
# - switch.toggle: Relay_3
|
||||
|
||||
# - platform: gpio
|
||||
# pin:
|
||||
# number: GPIO05
|
||||
# mode: INPUT
|
||||
# inverted: True
|
||||
# name: "Button: Light Switch 2 (Cabinet)"
|
||||
# on_press:
|
||||
# - switch.toggle: Relay_2
|
||||
|
||||
|
||||
#############################################
|
||||
# SWITCH COMPONENT
|
||||
@@ -227,38 +231,16 @@ binary_sensor:
|
||||
#############################################
|
||||
switch:
|
||||
- platform: gpio
|
||||
name: "Main Light"
|
||||
name: "Relay: Main Light"
|
||||
pin: GPIO13
|
||||
id: Relay_1
|
||||
- platform: gpio
|
||||
name: "Cabinet Light"
|
||||
name: "Relay: Cabinet Light"
|
||||
pin: GPIO12
|
||||
id: Relay_2
|
||||
- platform: gpio
|
||||
name: "Extract Fan"
|
||||
name: "Relay: Extract Fan"
|
||||
pin: GPIO14
|
||||
id: Relay_3
|
||||
|
||||
#############################################
|
||||
# GENERAL SENSORS
|
||||
# https://esphome.io/components/sensor/
|
||||
#############################################
|
||||
sensor:
|
||||
- platform: uptime # Uptime for this device
|
||||
name: ${friendly_name} Uptime
|
||||
update_interval: ${update_interval}
|
||||
entity_category: "diagnostic"
|
||||
- platform: wifi_signal # Wifi Strength
|
||||
name: ${friendly_name} Wifi Signal dB
|
||||
id: wifi_signal_db
|
||||
update_interval: ${update_interval}
|
||||
entity_category: "diagnostic"
|
||||
- platform: copy # Reports the WiFi signal strength in %
|
||||
source_id: wifi_signal_db
|
||||
name: ${friendly_name} WiFi Signal Percent
|
||||
filters:
|
||||
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
|
||||
unit_of_measurement: "Signal %"
|
||||
entity_category: "diagnostic"
|
||||
device_class: ""
|
||||
|
||||
|
215
esphome/esp-downstbathswitch.yaml.changes
Normal file
215
esphome/esp-downstbathswitch.yaml.changes
Normal file
@@ -0,0 +1,215 @@
|
||||
#############################################
|
||||
#############################################
|
||||
# DOWNSTAIRS BATHROOM MAIN LIGHTSWITCH
|
||||
# Zemismart KS-811 Triple push button
|
||||
#
|
||||
# V1.0 2025-02-14 Initial Version
|
||||
#
|
||||
# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/
|
||||
#
|
||||
# INSTRUCTIONS
|
||||
# -
|
||||
#
|
||||
#############################################
|
||||
#############################################
|
||||
|
||||
substitutions:
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
devicename: "esp-downstbathswitch"
|
||||
friendly_name: "Downstairs Bath Lightswitch"
|
||||
description_comment: "Downstairs Bathroom Main Lightswitch using a Zemismart KS-811 Triple Push Button. Main Light (1), Cabinet Light (2), Extract Fan (3)"
|
||||
|
||||
api_key: !secret esp-downstbathswitch_api_key # unfortunately you can't use substitutions inside secrets names
|
||||
ota_pass: !secret esp-downstbathswitch_ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
static_ip_address: !secret esp-downstbathswitch_ip
|
||||
|
||||
update_interval: 60s # update time for for general sensors etc
|
||||
hold_threshold: "4000ms" # Hold threshold as a compile-time constant
|
||||
|
||||
#############################################
|
||||
# Included Common Packages
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
packages:
|
||||
common_wifi: !include
|
||||
file: common/network_common.yaml
|
||||
vars:
|
||||
local_static_ip_address: ${static_ip_address}
|
||||
local_api_key: ${api_key}
|
||||
local_ota_pass: ${ota_pass}
|
||||
common_mqtt: !include
|
||||
file: common/mqtt_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: ${devicename}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: ${description_comment} #Appears on the esphome page in HA
|
||||
|
||||
#############################################
|
||||
# ESP Platform and Framework
|
||||
# https://esphome.io/components/esp32.html
|
||||
#############################################
|
||||
esp8266:
|
||||
board: esp01_1m
|
||||
|
||||
#############################################
|
||||
# ESPHome Logging Enable
|
||||
# https://esphome.io/components/logger.html
|
||||
#############################################
|
||||
logger:
|
||||
level: INFO #INFO Level suggested, or DEBUG for testing
|
||||
#baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
|
||||
#esp8266_store_log_strings_in_flash: false
|
||||
#tx_buffer_size: 64
|
||||
|
||||
|
||||
#############################################
|
||||
# Real time clock time source for ESPHome
|
||||
# If it's invalid, we fall back to an internal clock
|
||||
# https://esphome.io/components/time/
|
||||
# https://esphome.io/components/time/sntp
|
||||
#############################################
|
||||
time:
|
||||
- platform: sntp
|
||||
id: sntp_time
|
||||
|
||||
|
||||
#############################################
|
||||
# STATUS LED
|
||||
# https://esphome.io/components/status_led.html
|
||||
#############################################
|
||||
status_led:
|
||||
pin:
|
||||
number: GPIO2
|
||||
inverted: yes
|
||||
|
||||
globals:
|
||||
- id: single_click_delay
|
||||
type: long
|
||||
restore_value: no
|
||||
initial_value: '300000' # 5 minutes in ms
|
||||
- id: double_click_delay
|
||||
type: long
|
||||
restore_value: no
|
||||
initial_value: '1800000' # 30 minutes in ms
|
||||
- id: triple_click_delay
|
||||
type: long
|
||||
restore_value: no
|
||||
initial_value: '7200000' # 2 hours in ms
|
||||
- id: hold_threshold_val
|
||||
type: long
|
||||
restore_value: no
|
||||
initial_value: '4000' # 4 seconds in ms
|
||||
|
||||
|
||||
#############################################
|
||||
# BINARY SENSORS
|
||||
# https://esphome.io/components/binary_sensor/
|
||||
#############################################
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO16
|
||||
mode: INPUT
|
||||
inverted: True
|
||||
name: "Button: Light Switch 1 (Main)"
|
||||
on_press:
|
||||
- switch.toggle: Relay_1
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO05
|
||||
mode: INPUT
|
||||
inverted: True
|
||||
name: "Button: Light Switch 2 (Cabinet)"
|
||||
on_press:
|
||||
- switch.toggle: Relay_2
|
||||
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: GPIO04
|
||||
mode: INPUT
|
||||
inverted: True
|
||||
name: "Button: Extract Fan"
|
||||
on_multi_click:
|
||||
# Single Click: one press (short press/release)
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
if (id(Relay_3).state) {
|
||||
ESP_LOGD("button3", "Single click: Relay_3 is on, turning it off.");
|
||||
id(Relay_3).turn_off();
|
||||
} else {
|
||||
ESP_LOGD("button3", "Single click: Relay_3 is off, turning it on for %d ms.", id(single_click_delay));
|
||||
id(Relay_3).turn_on();
|
||||
delay(id(single_click_delay));
|
||||
id(Relay_3).turn_off();
|
||||
}
|
||||
# Double Click: two quick press/release cycles
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("button3", "Double click detected: turning Relay_3 on for %d ms.", id(double_click_delay));
|
||||
id(Relay_3).turn_on();
|
||||
delay(id(double_click_delay));
|
||||
id(Relay_3).turn_off();
|
||||
# Triple Click: three quick press/release cycles
|
||||
- timing:
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at most 1s
|
||||
- ON for at most 1s
|
||||
- OFF for at least 0.5s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("button3", "Triple click detected: turning Relay_3 on for %d ms.", id(triple_click_delay));
|
||||
id(Relay_3).turn_on();
|
||||
delay(id(triple_click_delay));
|
||||
id(Relay_3).turn_off();
|
||||
# Hold: button held for at least 4 seconds
|
||||
- timing:
|
||||
- ON for at least 4s
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("button3", "Hold detected (threshold %d ms): turning Relay_3 on indefinitely.", id(hold_threshold_val));
|
||||
id(Relay_3).turn_on();
|
||||
|
||||
|
||||
#############################################
|
||||
# SWITCH COMPONENT
|
||||
# https://esphome.io/components/switch/
|
||||
#############################################
|
||||
switch:
|
||||
- platform: gpio
|
||||
name: "Relay: Main Light"
|
||||
pin: GPIO13
|
||||
id: Relay_1
|
||||
- platform: gpio
|
||||
name: "Relay: Cabinet Light"
|
||||
pin: GPIO12
|
||||
id: Relay_2
|
||||
- platform: gpio
|
||||
name: "Relay: Extract Fan"
|
||||
pin: GPIO14
|
||||
id: Relay_3
|
||||
|
||||
|
@@ -136,6 +136,8 @@ mqtt:
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: false # enable entity discovery (true is default)
|
||||
#discover_ip: True # enable device discovery (true is default)
|
||||
|
||||
|
||||
#############################################
|
||||
|
@@ -151,8 +151,8 @@ mqtt:
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: True # enable entity discovery (true is default)
|
||||
discover_ip: True # enable device discovery (true is default)
|
||||
discovery: False # enable entity discovery (true is default)
|
||||
#discover_ip: True # enable device discovery (true is default)
|
||||
|
||||
#############################################
|
||||
# i2c bus
|
||||
|
@@ -143,6 +143,7 @@ mqtt:
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: False # enable entity discovery (true is default, we don't want two HA Instances)
|
||||
|
||||
# Availability Topic
|
||||
birth_message:
|
||||
|
639
esphome/esp-masterbathtowelrail copy.yaml.old
Normal file
639
esphome/esp-masterbathtowelrail copy.yaml.old
Normal file
@@ -0,0 +1,639 @@
|
||||
#############################################
|
||||
#############################################
|
||||
# MASTER BATHROOM HEATED TOWEL RAIL
|
||||
# Controlled by a Sonoff Basic
|
||||
#
|
||||
# V1.1 2025-04-12 Fixes to timers and offline modes
|
||||
# V1.0 2025-02-14 Initial Version
|
||||
#
|
||||
# INSTRUCTIONS
|
||||
# - It allows a heated towel rail device to work in a standalone operation
|
||||
# - On startup, it will turn on for (startup_duration) hours then go into timer mode (this allows you to just turn it on to get some heat immediately)
|
||||
# - The timer has a morning and evening time (but no weekday/weekend setting)
|
||||
# - Default values are 5am-7am and 9pm-Midnight (as this suits our use case)
|
||||
# - 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 4 on/off times via MQTT (See below commands)
|
||||
# - You can set 4 modes ON/OFF/TIMER/STARTUP via MQTT. That way, you can set to STARTUP for a short boost
|
||||
# - Any new timer times set via MQTT will be remembered though a reboot
|
||||
# - On a reboot, the device will always turn on for the Startup Duration (STARTUP mode, default 2 hours)
|
||||
# - TIMER mode will always be switched on after startup mode is complete
|
||||
# - 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 towel rail will go on
|
||||
# mqtt_timer_topic/morning-off/08:00 : Time towel rail will go off
|
||||
# mqtt_timer_topic/evening-on/09:00 : Time towel rail will go on
|
||||
# mqtt_timer_topic/evening-off/00:00 : Time towel rail will go off
|
||||
# mqtt_timer_topic/operation/ON : Towel rail permanently on
|
||||
# mqtt_timer_topic/operation/OFF : Towel rail permanently off
|
||||
# mqtt_timer_topic/operation/TIMER : Towel rail will obey timer settings
|
||||
# mqtt_timer_topic/operation/STARTUP : Turn on for (startup_duration) hours then TIMER (also on startup)
|
||||
#
|
||||
#############################################
|
||||
#############################################
|
||||
|
||||
|
||||
substitutions:
|
||||
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
|
||||
mqtt_timer_topic: "viewroad-commands/masterbath-towelrail" # Topics you will use to change stuff
|
||||
startup_duration: "10" # Minutes to stay ON in STARTUP mode before reverting to TIMER
|
||||
|
||||
devicename: "esp-masterbathtowelrail"
|
||||
friendly_name: "Master Bathroom Towelrail"
|
||||
description_comment: "Sonoff Basic controlling ON/OFF/Timer for the Heated Towel Rail in the Master Bathroom"
|
||||
|
||||
api_key: !secret esp-masterbathtowelrail_api_key # unfortunately you can't use substitutions inside secrets names
|
||||
ota_pass: !secret esp-masterbathtowelrail_ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
static_ip_address: !secret esp-masterbathtowelrail_ip
|
||||
|
||||
update_interval: "300s" # Update time for for general sensors etc.
|
||||
|
||||
#############################################
|
||||
# SYSTEM SPECIFIC VARIABLE SUBSTITUTIONS
|
||||
#############################################
|
||||
|
||||
timezone: "Pacific/Auckland"
|
||||
sntp_update_interval: 6h # Set the duration between the sntp service polling
|
||||
# Network time servers https://www.ntppool.org/zone/@
|
||||
# Make sure you have some DNS, or use IP addresses only here.
|
||||
sntp_server_1: !secret ntp_server_1
|
||||
sntp_server_2: !secret ntp_server_2
|
||||
sntp_server_3: !secret ntp_server_3
|
||||
|
||||
#############################################
|
||||
# Included Common Packages
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
packages:
|
||||
common_wifi: !include
|
||||
file: common/network_common.yaml
|
||||
vars:
|
||||
local_static_ip_address: ${static_ip_address}
|
||||
local_api_key: ${api_key}
|
||||
local_ota_pass: ${ota_pass}
|
||||
common_mqtt: !include
|
||||
file: common/mqtt_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: ${devicename}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: ${description_comment} # Appears on the esphome page in HA
|
||||
on_boot:
|
||||
priority: 900 # High priority to run after globals are initialized
|
||||
then:
|
||||
- lambda: |-
|
||||
// 1) Figure out the current time in "seconds from midnight"
|
||||
// using SNTP if available, otherwise fallback_time * 60.
|
||||
bool have_sntp = id(sntp_time).now().is_valid();
|
||||
int current_time_s = 0;
|
||||
|
||||
if (have_sntp) {
|
||||
auto now = id(sntp_time).now();
|
||||
current_time_s = now.hour * 3600 + now.minute * 60 + now.second;
|
||||
} else {
|
||||
// fallback_time is in minutes; convert to seconds
|
||||
current_time_s = id(fallback_time) * 60;
|
||||
}
|
||||
|
||||
// 2) Compare with the last boot time
|
||||
int diff = current_time_s - id(last_boot_time_s);
|
||||
|
||||
// If within 30 seconds, increment boot_count; otherwise reset to 1
|
||||
if (diff >= 0 && diff <= 30) {
|
||||
id(boot_count)++;
|
||||
} else {
|
||||
id(boot_count) = 1;
|
||||
}
|
||||
|
||||
// Update stored last boot time
|
||||
id(last_boot_time_s) = current_time_s;
|
||||
|
||||
// 3) If we've booted 4+ times in 20s => force ON mode
|
||||
if (id(boot_count) >= 4) {
|
||||
id(operation_mode) = 1; // ON
|
||||
ESP_LOGI("power_cycle", "Detected 4 power cycles in 20s => Forcing ON mode");
|
||||
} else {
|
||||
// Otherwise do your normal startup logic:
|
||||
id(operation_mode) = 3; // on_boot -> sets operation_mode = 3 (STARTUP)
|
||||
id(startup_timer) = 0; // and reset startup_timer = 0 (for time sync if no sntp)
|
||||
ESP_LOGI("power_cycle", "Boot count=%d => STARTUP mode", id(boot_count));
|
||||
}
|
||||
|
||||
#############################################
|
||||
# ESP Platform and Framework
|
||||
# https://esphome.io/components/esp32.html
|
||||
#############################################
|
||||
esp8266:
|
||||
board: esp01_1m # The original sonoff basic
|
||||
|
||||
#############################################
|
||||
# ESPHome Logging Enable
|
||||
# https://esphome.io/components/logger.html
|
||||
#############################################
|
||||
logger:
|
||||
level: DEBUG #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
|
||||
|
||||
#############################################
|
||||
# Real time clock time source for ESPHome
|
||||
# If it's invalid, we fall back to an internal clock
|
||||
# https://esphome.io/components/time/index.html
|
||||
# https://esphome.io/components/time/sntp
|
||||
#############################################
|
||||
time:
|
||||
- platform: sntp
|
||||
id: sntp_time
|
||||
# Define the timezone of the device
|
||||
timezone: "${timezone}"
|
||||
# Change sync interval from default 5min to 6 hours (or as set in substitutions)
|
||||
update_interval: "${sntp_update_interval}"
|
||||
# Set specific sntp servers to use
|
||||
servers:
|
||||
- "${sntp_server_1}"
|
||||
- "${sntp_server_2}"
|
||||
- "${sntp_server_3}"
|
||||
# Publish the time the device was last restarted
|
||||
on_time_sync:
|
||||
then:
|
||||
- logger.log: "Synchronised sntp clock"
|
||||
- text_sensor.template.publish:
|
||||
id: time_sync
|
||||
state: "SNTP clock Syncd"
|
||||
# Update last restart time, but only once.
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(device_last_restart).state == "";'
|
||||
then:
|
||||
- text_sensor.template.publish:
|
||||
id: device_last_restart
|
||||
state: !lambda 'return id(sntp_time).now().strftime("%a %d %b %Y - %I:%M:%S %p");'
|
||||
|
||||
#############################################
|
||||
# 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),
|
||||
# default 05:00 => 300
|
||||
- id: morning_on
|
||||
type: int
|
||||
restore_value: true
|
||||
initial_value: "300"
|
||||
|
||||
# Morning Off time (minutes from midnight),
|
||||
# default 07:00 => 420
|
||||
- id: morning_off
|
||||
type: int
|
||||
restore_value: true
|
||||
initial_value: "420"
|
||||
|
||||
# Evening On time (minutes from midnight),
|
||||
# default 21:00 => 1260
|
||||
- id: evening_on
|
||||
type: int
|
||||
restore_value: true
|
||||
initial_value: "1260"
|
||||
|
||||
# Evening Off time (minutes from midnight),
|
||||
# default 00:00 => 0 => treat as midnight
|
||||
- id: evening_off
|
||||
type: int
|
||||
restore_value: true
|
||||
initial_value: "0"
|
||||
|
||||
####################################################
|
||||
# operation_mode:
|
||||
# 0 = OFF
|
||||
# 1 = ON
|
||||
# 2 = TIMER
|
||||
# 3 = STARTUP
|
||||
####################################################
|
||||
- id: operation_mode
|
||||
type: int
|
||||
restore_value: false
|
||||
initial_value: "3"
|
||||
|
||||
####################################################
|
||||
# fallback_time is used if SNTP is invalid.
|
||||
# We assume user powers on the device at 12:00 noon
|
||||
# => 12 * 60 = 720 minutes from midnight.
|
||||
# Not restored, so it resets each boot.
|
||||
####################################################
|
||||
- id: fallback_time
|
||||
type: int
|
||||
restore_value: false
|
||||
initial_value: "720"
|
||||
|
||||
- id: current_mins
|
||||
type: int
|
||||
restore_value: false
|
||||
initial_value: '0'
|
||||
|
||||
####################################################
|
||||
# startup_timer: counts minutes in STARTUP mode
|
||||
# After 'startup_duration' minutes, revert to TIMER.
|
||||
# Not restored, so each boot starts fresh at 0.
|
||||
####################################################
|
||||
- id: startup_timer
|
||||
type: int
|
||||
restore_value: false
|
||||
initial_value: "0"
|
||||
|
||||
|
||||
# Time period string for converting to seconds
|
||||
#- id: update_interval_string
|
||||
# type: std::string
|
||||
# restore_value: false
|
||||
# max_restore_data_length: 12
|
||||
# initial_value: ${update_interval}
|
||||
|
||||
#############################################
|
||||
# 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());
|
||||
}
|
||||
####################################################
|
||||
# Subscribe to operation mode:
|
||||
# OFF, ON, TIMER, STARTUP
|
||||
# We do case-insensitive compare using strcasecmp
|
||||
# (Requires <strings.h> typically included in ESPHome)
|
||||
####################################################
|
||||
- platform: mqtt_subscribe
|
||||
name: "Operation Mode Setting"
|
||||
id: timer_operation_mode_topic
|
||||
topic: "${mqtt_timer_topic}/operation" # STARTUP,ON,OFF,TIMER
|
||||
internal: True # No need to show this in Home Assistant as there is a sensor that shows the set value
|
||||
on_value:
|
||||
then:
|
||||
- lambda: |-
|
||||
/*
|
||||
* In standard C++ (ESPHome), no 'equalsIgnoreCase()'.
|
||||
* We use 'strcasecmp' for case-insensitive compare.
|
||||
* Returns 0 if they match ignoring case.
|
||||
*/
|
||||
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(), "STARTUP") == 0) {
|
||||
id(operation_mode) = 3;
|
||||
id(startup_timer) = 0; // Reset the startup timer to zero
|
||||
ESP_LOGI("timer","Operation mode set to STARTUP");
|
||||
} else {
|
||||
ESP_LOGW("timer","Invalid operation mode: %s", x.c_str());
|
||||
}
|
||||
|
||||
|
||||
######################################################
|
||||
# Expose the current operation mode (OFF, ON, TIMER, STARTUP)
|
||||
######################################################
|
||||
- platform: template
|
||||
name: "Operation Mode State"
|
||||
lambda: |-
|
||||
// 0=OFF, 1=ON, 2=TIMER, 3=STARTUP
|
||||
switch (id(operation_mode)) {
|
||||
case 0: return {"OFF"};
|
||||
case 1: return {"ON"};
|
||||
case 2: return {"TIMER"};
|
||||
case 3: return {"STARTUP"};
|
||||
default: return {"UNKNOWN"};
|
||||
}
|
||||
update_interval: ${update_interval}
|
||||
|
||||
|
||||
|
||||
######################################################
|
||||
# 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}
|
||||
|
||||
######################################################
|
||||
# Creates a sensor showing when the device was last restarted
|
||||
# Uptime template sensor, and SNTP are needed
|
||||
######################################################
|
||||
- platform: template
|
||||
name: "Last Restart: ${friendly_name}"
|
||||
id: device_last_restart
|
||||
update_interval: ${update_interval}
|
||||
icon: mdi:clock
|
||||
entity_category: diagnostic
|
||||
#device_class: timestamp
|
||||
|
||||
- platform: template
|
||||
name: "Time Sync Status"
|
||||
id: time_sync
|
||||
update_interval: ${update_interval}
|
||||
entity_category: diagnostic
|
||||
|
||||
- platform: template
|
||||
name: "Internal Time"
|
||||
id: time_text
|
||||
update_interval: ${update_interval}
|
||||
entity_category: diagnostic
|
||||
lambda: |-
|
||||
auto time_text = id(sntp_time).now().strftime("%H:%M:%S - %d-%m-%Y");
|
||||
return { time_text };
|
||||
|
||||
sensor:
|
||||
- platform: template
|
||||
name: "Mins from Midnight"
|
||||
#unit_of_measurement: "s"
|
||||
#accuracy_decimals: 0
|
||||
update_interval: 1s
|
||||
lambda: |-
|
||||
return id(current_mins);
|
||||
|
||||
|
||||
####################################################
|
||||
# Relay Switch (Sonoff Basic Relay on GPIO12)
|
||||
####################################################
|
||||
switch:
|
||||
- platform: gpio
|
||||
name: "Towel Rail Power"
|
||||
pin: GPIO12
|
||||
id: relay
|
||||
restore_mode: RESTORE_DEFAULT_OFF
|
||||
|
||||
####################################################
|
||||
# Check every minute to decide relay state
|
||||
####################################################
|
||||
interval:
|
||||
- interval: "1min"
|
||||
then:
|
||||
- lambda: |-
|
||||
// operation_mode:
|
||||
// 0 = OFF
|
||||
// 1 = ON
|
||||
// 2 = TIMER
|
||||
// 3 = STARTUP
|
||||
int mode = id(operation_mode);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// STARTUP MODE: Relay ON for 'startup_duration'
|
||||
// minutes, then automatically revert to TIMER.
|
||||
//////////////////////////////////////////////////
|
||||
if (mode == 3) {
|
||||
id(startup_timer) = id(startup_timer) ++ ; // works as long as update_interval in seconds
|
||||
// Compare with the substitution startup_duration
|
||||
if (id(startup_timer) < (int) ${startup_duration}) {
|
||||
// Still within the STARTUP period => turn relay on
|
||||
id(relay).turn_on();
|
||||
} else {
|
||||
// After 'startup_duration' minutes => switch to TIMER
|
||||
id(operation_mode) = 2;
|
||||
id(mqtt_client).publish("${mqtt_timer_topic}/operation", "TIMER");
|
||||
}
|
||||
// Skip the rest of the logic
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// OFF MODE => always off
|
||||
//////////////////////////////////////////////////
|
||||
if (mode == 0) {
|
||||
id(relay).turn_off();
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// ON MODE => always on
|
||||
//////////////////////////////////////////////////
|
||||
if (mode == 1) {
|
||||
id(relay).turn_on();
|
||||
return;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// TIMER MODE => follow morning/evening schedule
|
||||
// using SNTP if valid, else fallback_time
|
||||
//////////////////////////////////////////////////
|
||||
if (mode == 2) {
|
||||
//auto now = id(sntp_time).now();
|
||||
//bool have_sntp = now.is_valid();
|
||||
|
||||
//int current_mins;
|
||||
//if (!have_sntp) {
|
||||
//if (!id(time_sync).has_state()) {
|
||||
//if 1 == 1 {
|
||||
// SNTP not available => fallback clock
|
||||
current_mins = id(fallback_time);
|
||||
// increment the fallback clock by 1 minute
|
||||
id(fallback_time) += 1;
|
||||
// wrap around at 1440 => next day
|
||||
if (id(fallback_time) >= 1440) {
|
||||
id(fallback_time) = 0;
|
||||
//}
|
||||
//} else {
|
||||
// Use real time from SNTP
|
||||
// current_mins = now.hour * 60 + now.minute;
|
||||
}
|
||||
|
||||
bool should_on = false;
|
||||
|
||||
// If evening_off == 0 => treat as midnight => 1440
|
||||
int evening_off_local = id(evening_off);
|
||||
if (evening_off_local == 0) {
|
||||
evening_off_local = 1440;
|
||||
}
|
||||
|
||||
// Check morning window
|
||||
// Example: morning_on=360 => 06:00, morning_off=480 => 08:00
|
||||
// If current_mins in [360..480), should_on = true
|
||||
if (id(morning_on) < id(morning_off)) {
|
||||
if (current_mins >= id(morning_on) && current_mins < id(morning_off)) {
|
||||
should_on = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check evening window
|
||||
// Example: evening_on=540 => 09:00, evening_off=1440 => midnight
|
||||
if (id(evening_on) < evening_off_local) {
|
||||
if (current_mins >= id(evening_on) && current_mins < evening_off_local) {
|
||||
should_on = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Final relay state based on schedule
|
||||
if (should_on) {
|
||||
id(relay).turn_on();
|
||||
} else {
|
||||
id(relay).turn_off();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,21 +3,22 @@
|
||||
# MASTER BATHROOM HEATED TOWEL RAIL
|
||||
# Controlled by a Sonoff Basic
|
||||
#
|
||||
# V1.1 2025-04-12 Fixes to timers and offline modes
|
||||
# V1.0 2025-02-14 Initial Version
|
||||
#
|
||||
# INSTRUCTIONS
|
||||
# - It allows a heated towel rail device to work in a standalone operation
|
||||
# - On startup, it will turn on for 2 hours then go into timer mode (this allows you to just turn it on to get some heat immediately)
|
||||
# - On startup, it will turn on for (startup_duration) hours then go into timer mode (this allows you to just turn it on to get some heat immediately)
|
||||
# - The timer has a morning and evening time (but no weekday/weekend setting)
|
||||
# - Default values are 5am-7am and 9pm-Midnight (as this suits our use case)
|
||||
# - 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 4 on/off times via MQTT (See below commands)
|
||||
# - You can set 4 modes ON/OFF/TIMER/STARTUP via MQTT
|
||||
# - You can set 4 modes ON/OFF/TIMER/STARTUP via MQTT. That way, you can set to STARTUP for a short boost
|
||||
# - Any new timer times set via MQTT will be remembered though a reboot
|
||||
# - On a reboot, the device will always turn on for the Startup Duration (STARTUP mode, default 2 hours)
|
||||
# - TIMER mode will always be switched on after startup mode is complete
|
||||
# - If you need it ON continuously with no MQTT, toggle power ON/OFF 4 times within 20 seconds (with ~2 secs in between to allow it to boot)
|
||||
# - 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
|
||||
@@ -29,49 +30,61 @@
|
||||
# mqtt_timer_topic/operation/ON : Towel rail permanently on
|
||||
# mqtt_timer_topic/operation/OFF : Towel rail permanently off
|
||||
# mqtt_timer_topic/operation/TIMER : Towel rail will obey timer settings
|
||||
# mqtt_timer_topic/operation/STARTUP : Turn on for 2 hours then TIMER (also on startup)
|
||||
# mqtt_timer_topic/operation/STARTUP : Turn on for (startup_duration) hours then TIMER (also on startup)
|
||||
#
|
||||
#############################################
|
||||
#############################################
|
||||
|
||||
#############################################
|
||||
# VARIABLE SUBSTITUTIONS
|
||||
# Give the device a useful name & description here
|
||||
# and change values accordingly.
|
||||
#############################################
|
||||
substitutions:
|
||||
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
|
||||
mqtt_timer_topic: "viewroad-commands/masterbath-towelrail" # Topics you will use to change stuff
|
||||
startup_duration: "120" # Minutes to stay ON in STARTUP mode before reverting to TIMER
|
||||
timezone: "Pacific/Auckland" # For setting clock with snmp
|
||||
|
||||
devicename: "esp-masterbathtowelrail"
|
||||
friendly_name: "Master Bathroom Towelrail"
|
||||
description_comment: "Sonoff Basic controlling ON/OFF/Timer for the Heated Towel Rail in the Master Bathroom"
|
||||
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
|
||||
api_key: !secret esp-masterbathtowelrail_api_key # unfortunately you can't use substitutions inside secrets names
|
||||
ota_pass: !secret esp-masterbathtowelrail_ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
wifi_ssid: !secret wifi_ssid
|
||||
wifi_password: !secret wifi_password
|
||||
fallback_ap_password: !secret fallback_ap_password
|
||||
|
||||
# Add these if we are giving it a static ip, or remove them in the Wifi section
|
||||
#static_ip_address: !secret esp-occupancyoffice_static_ip
|
||||
#static_ip_gateway: !secret esp-occupancyoffice_gateway
|
||||
#static_ip_subnet: !secret esp-occupancyoffice_subnet
|
||||
static_ip_address: !secret esp-masterbathtowelrail_ip
|
||||
|
||||
mqtt_server: !secret mqtt_server
|
||||
mqtt_username: !secret mqtt_username
|
||||
mqtt_password: !secret mqtt_password
|
||||
mqtt_topic: "esphome" #main topic for the mqtt server, call it what you like
|
||||
update_interval: "60s" # Update time for for general sensors etc.
|
||||
|
||||
# Add these if we are using the internal web server (this is pretty processor intensive)
|
||||
#web_server_username: !secret web_server_username
|
||||
#web_server_password: !secret web_server_password
|
||||
#############################################
|
||||
# SYSTEM SPECIFIC VARIABLE SUBSTITUTIONS
|
||||
#############################################
|
||||
|
||||
update_interval: 60s # update time for for general sensors etc
|
||||
timezone: "Pacific/Auckland"
|
||||
sntp_update_interval: 6h # Set the duration between the sntp service polling
|
||||
# Network time servers https://www.ntppool.org/zone/@
|
||||
# Make sure you have some DNS, or use IP addresses only here.
|
||||
sntp_server_1: !secret ntp_server_1
|
||||
sntp_server_2: !secret ntp_server_2
|
||||
sntp_server_3: !secret ntp_server_3
|
||||
|
||||
#############################################
|
||||
# Included Common Packages
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
packages:
|
||||
common_wifi: !include
|
||||
file: common/network_common.yaml
|
||||
vars:
|
||||
local_static_ip_address: ${static_ip_address}
|
||||
local_api_key: ${api_key}
|
||||
local_ota_pass: ${ota_pass}
|
||||
common_mqtt: !include
|
||||
file: common/mqtt_common.yaml
|
||||
common_general_sensors: !include
|
||||
file: common/sensors_common.yaml
|
||||
vars:
|
||||
local_friendly_name: ${friendly_name}
|
||||
local_update_interval: ${update_interval}
|
||||
|
||||
#############################################
|
||||
# ESPHome
|
||||
@@ -80,13 +93,13 @@ substitutions:
|
||||
esphome:
|
||||
name: ${devicename}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: ${description_comment} #a ppears on the esphome page in HA
|
||||
comment: ${description_comment} # Appears on the esphome page in HA
|
||||
on_boot:
|
||||
priority: 900 # high priority to run after globals are initialized
|
||||
priority: 900 # High priority to run after globals are initialized
|
||||
then:
|
||||
- lambda: |-
|
||||
// 1) Figure out the current time in "seconds from midnight"
|
||||
// using SNTP if available, otherwise fallback_time * 60.
|
||||
// using SNTP if available, otherwise current_mins * 60.
|
||||
bool have_sntp = id(sntp_time).now().is_valid();
|
||||
int current_time_s = 0;
|
||||
|
||||
@@ -94,15 +107,15 @@ esphome:
|
||||
auto now = id(sntp_time).now();
|
||||
current_time_s = now.hour * 3600 + now.minute * 60 + now.second;
|
||||
} else {
|
||||
// fallback_time is in minutes; convert to seconds
|
||||
current_time_s = id(fallback_time) * 60;
|
||||
// current_mins is in minutes; convert to seconds
|
||||
current_time_s = id(current_mins) * 60;
|
||||
}
|
||||
|
||||
// 2) Compare with the last boot time
|
||||
int diff = current_time_s - id(last_boot_time_s);
|
||||
|
||||
// If within 20 seconds, increment boot_count; otherwise reset to 1
|
||||
if (diff >= 0 && diff <= 20) {
|
||||
// If within 30 seconds, increment boot_count; otherwise reset to 1
|
||||
if (diff >= 0 && diff <= 30) {
|
||||
id(boot_count)++;
|
||||
} else {
|
||||
id(boot_count) = 1;
|
||||
@@ -134,58 +147,11 @@ esp8266:
|
||||
# https://esphome.io/components/logger.html
|
||||
#############################################
|
||||
logger:
|
||||
level: INFO #INFO Level suggested, or DEBUG for testing
|
||||
level: DEBUG #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
|
||||
|
||||
#############################################
|
||||
# Enable the Home Assistant API
|
||||
# https://esphome.io/components/api.html
|
||||
#############################################
|
||||
api:
|
||||
encryption:
|
||||
key: ${api_key}
|
||||
|
||||
#############################################
|
||||
# Enable Over the Air Update Capability
|
||||
# https://esphome.io/components/ota.html?highlight=ota
|
||||
#############################################
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: ${ota_pass}
|
||||
|
||||
#############################################
|
||||
# Safe Mode
|
||||
# Safe mode will detect boot loops
|
||||
# https://esphome.io/components/safe_mode
|
||||
#############################################
|
||||
safe_mode:
|
||||
|
||||
#############################################
|
||||
# Wifi Settings
|
||||
# https://esphome.io/components/wifi.html
|
||||
#
|
||||
# Power Save mode (can reduce wifi reliability)
|
||||
# NONE (least power saving, Default for ESP8266)
|
||||
# LIGHT (Default for ESP32)
|
||||
# HIGH (most power saving)
|
||||
#############################################
|
||||
wifi:
|
||||
ssid: ${wifi_ssid}
|
||||
password: ${wifi_password}
|
||||
#power_save_mode: LIGHT # https://esphome.io/components/wifi.html#wifi-power-save-mode
|
||||
#manual_ip: # optional static IP address
|
||||
#static_ip: ${static_ip_address}
|
||||
#gateway: ${static_ip_gateway}
|
||||
#subnet: ${static_ip_subnet}
|
||||
ap: # Details for fallback hotspot in case wifi connection fails https://esphome.io/components/wifi.html#access-point-mode
|
||||
ssid: ${devicename} AP
|
||||
password: ${fallback_ap_password}
|
||||
ap_timeout: 30min # Time until it brings up fallback AP. default is 1min
|
||||
|
||||
captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
||||
|
||||
#############################################
|
||||
# Real time clock time source for ESPHome
|
||||
# If it's invalid, we fall back to an internal clock
|
||||
@@ -195,19 +161,30 @@ captive_portal: # extra fallback mechanism for when connecting if the configure
|
||||
time:
|
||||
- platform: sntp
|
||||
id: sntp_time
|
||||
|
||||
#############################################
|
||||
# MQTT Monitoring
|
||||
# https://esphome.io/components/mqtt.html?highlight=mqtt
|
||||
# MUST also have api enabled if you enable MQTT
|
||||
#############################################
|
||||
mqtt:
|
||||
broker: ${mqtt_server}
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
#discovery: True # enable entity discovery (true is default)
|
||||
#discover_ip: True # enable device discovery (true is default)
|
||||
# Define the timezone of the device
|
||||
timezone: "${timezone}"
|
||||
# Change sync interval from default 5min to 6 hours (or as set in substitutions)
|
||||
update_interval: "${sntp_update_interval}"
|
||||
# Set specific sntp servers to use
|
||||
servers:
|
||||
- "${sntp_server_1}"
|
||||
- "${sntp_server_2}"
|
||||
- "${sntp_server_3}"
|
||||
# Publish the time the device was last restarted
|
||||
on_time_sync:
|
||||
then:
|
||||
- logger.log: "Synchronised sntp clock"
|
||||
- text_sensor.template.publish:
|
||||
id: time_sync
|
||||
state: "SNTP clock Syncd"
|
||||
# Update last restart time, but only once.
|
||||
- if:
|
||||
condition:
|
||||
lambda: 'return id(device_last_restart).state == "";'
|
||||
then:
|
||||
- text_sensor.template.publish:
|
||||
id: device_last_restart
|
||||
state: !lambda 'return id(sntp_time).now().strftime("%a %d %b %Y - %I:%M:%S %p");'
|
||||
|
||||
#############################################
|
||||
# Global Variables for use in automations etc
|
||||
@@ -221,7 +198,7 @@ globals:
|
||||
restore_value: true
|
||||
initial_value: "0"
|
||||
|
||||
# Counts how many consecutive boots have occurred within 10 seconds
|
||||
# Counts how many consecutive boots have occurred (within X seconds)
|
||||
- id: boot_count
|
||||
type: int
|
||||
restore_value: true
|
||||
@@ -249,11 +226,11 @@ globals:
|
||||
initial_value: "1260"
|
||||
|
||||
# Evening Off time (minutes from midnight),
|
||||
# default 00:00 => 0 => treat as midnight
|
||||
# default 24:00 => 1440 => treat as midnight
|
||||
- id: evening_off
|
||||
type: int
|
||||
restore_value: true
|
||||
initial_value: "0"
|
||||
initial_value: "1440"
|
||||
|
||||
####################################################
|
||||
# operation_mode:
|
||||
@@ -268,15 +245,15 @@ globals:
|
||||
initial_value: "3"
|
||||
|
||||
####################################################
|
||||
# fallback_time is used if SNTP is invalid.
|
||||
# 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.
|
||||
# Not restored, so it resets each boot.
|
||||
####################################################
|
||||
- id: fallback_time
|
||||
- id: current_mins
|
||||
type: int
|
||||
restore_value: false
|
||||
initial_value: "720"
|
||||
initial_value: "720" # 720 is 12:00 Noon
|
||||
|
||||
####################################################
|
||||
# startup_timer: counts minutes in STARTUP mode
|
||||
@@ -288,6 +265,7 @@ globals:
|
||||
restore_value: false
|
||||
initial_value: "0"
|
||||
|
||||
|
||||
#############################################
|
||||
# Text Sensors
|
||||
# https://esphome.io/components/text_sensor/index.html
|
||||
@@ -297,7 +275,6 @@ text_sensor:
|
||||
############################
|
||||
# MQTT Subscriptions
|
||||
############################
|
||||
|
||||
####################################################
|
||||
# Subscribe to the Morning On time, format "HH:MM"
|
||||
# We check x.size() == 5 and x[2] == ':',
|
||||
@@ -305,9 +282,9 @@ text_sensor:
|
||||
# std::string uses 'substr', not 'substring'.
|
||||
####################################################
|
||||
- platform: mqtt_subscribe
|
||||
name: "Morning On Time"
|
||||
name: "Morning On Time Setting"
|
||||
id: morning_on_topic
|
||||
topic: "${mqtt_timer_topic}/morning-on"
|
||||
topic: "${mqtt_timer_topic}/morning-on" # Stored in the format HH:MM
|
||||
internal: True
|
||||
on_value:
|
||||
then:
|
||||
@@ -321,14 +298,13 @@ text_sensor:
|
||||
} else {
|
||||
ESP_LOGW("timer","Invalid Morning On format: %s", x.c_str());
|
||||
}
|
||||
|
||||
####################################################
|
||||
# Morning Off time => "HH:MM"
|
||||
####################################################
|
||||
- platform: mqtt_subscribe
|
||||
name: "Morning Off Time"
|
||||
name: "Morning Off Time Setting"
|
||||
id: morning_off_topic
|
||||
topic: "${mqtt_timer_topic}/morning-off"
|
||||
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:
|
||||
@@ -341,14 +317,13 @@ text_sensor:
|
||||
} else {
|
||||
ESP_LOGW("timer","Invalid Morning Off format: %s", x.c_str());
|
||||
}
|
||||
|
||||
####################################################
|
||||
# Evening On time => "HH:MM"
|
||||
####################################################
|
||||
- platform: mqtt_subscribe
|
||||
name: "Evening On Time"
|
||||
name: "Evening On Time Setting"
|
||||
id: evening_on_topic
|
||||
topic: "${mqtt_timer_topic}/evening-on"
|
||||
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:
|
||||
@@ -361,14 +336,13 @@ text_sensor:
|
||||
} else {
|
||||
ESP_LOGW("timer","Invalid Evening On format: %s", x.c_str());
|
||||
}
|
||||
|
||||
####################################################
|
||||
# Evening Off time => "HH:MM"
|
||||
####################################################
|
||||
- platform: mqtt_subscribe
|
||||
name: "Evening Off Time"
|
||||
name: "Evening Off Time Setting"
|
||||
id: evening_off_topic
|
||||
topic: "${mqtt_timer_topic}/evening-off"
|
||||
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:
|
||||
@@ -381,7 +355,6 @@ text_sensor:
|
||||
} else {
|
||||
ESP_LOGW("timer","Invalid Evening Off format: %s", x.c_str());
|
||||
}
|
||||
|
||||
####################################################
|
||||
# Subscribe to operation mode:
|
||||
# OFF, ON, TIMER, STARTUP
|
||||
@@ -389,9 +362,9 @@ text_sensor:
|
||||
# (Requires <strings.h> typically included in ESPHome)
|
||||
####################################################
|
||||
- platform: mqtt_subscribe
|
||||
name: "Timer Operation Mode"
|
||||
name: "Operation Mode Setting"
|
||||
id: timer_operation_mode_topic
|
||||
topic: "${mqtt_timer_topic}/operation"
|
||||
topic: "${mqtt_timer_topic}/operation" # STARTUP,ON,OFF,TIMER
|
||||
internal: True # No need to show this in Home Assistant as there is a sensor that shows the set value
|
||||
on_value:
|
||||
then:
|
||||
@@ -412,7 +385,7 @@ text_sensor:
|
||||
ESP_LOGI("timer","Operation mode set to OFF");
|
||||
} else if (strcasecmp(x.c_str(), "STARTUP") == 0) {
|
||||
id(operation_mode) = 3;
|
||||
id(startup_timer) = 0;
|
||||
id(startup_timer) = 0; // Reset the startup timer to zero
|
||||
ESP_LOGI("timer","Operation mode set to STARTUP");
|
||||
} else {
|
||||
ESP_LOGW("timer","Invalid operation mode: %s", x.c_str());
|
||||
@@ -438,7 +411,7 @@ text_sensor:
|
||||
# Expose the "Morning On" time as a text (HH:MM)
|
||||
######################################################
|
||||
- platform: template
|
||||
name: "Morning On Time State"
|
||||
name: "Timeclock: Morning On Time"
|
||||
lambda: |-
|
||||
int hour = id(morning_on) / 60;
|
||||
int minute = id(morning_on) % 60;
|
||||
@@ -452,7 +425,7 @@ text_sensor:
|
||||
# Expose the "Morning Off" time as a text (HH:MM)
|
||||
######################################################
|
||||
- platform: template
|
||||
name: "Morning Off Time State"
|
||||
name: "Timeclock: Morning Off Time"
|
||||
lambda: |-
|
||||
int hour = id(morning_off) / 60;
|
||||
int minute = id(morning_off) % 60;
|
||||
@@ -467,7 +440,7 @@ text_sensor:
|
||||
# Expose the "Evening On" time as a text (HH:MM)
|
||||
######################################################
|
||||
- platform: template
|
||||
name: "Evening On Time State"
|
||||
name: "Timeclock: Evening On Time"
|
||||
lambda: |-
|
||||
int hour = id(evening_on) / 60;
|
||||
int minute = id(evening_on) % 60;
|
||||
@@ -482,7 +455,7 @@ text_sensor:
|
||||
# Expose the "Evening Off" time as a text (HH:MM)
|
||||
######################################################
|
||||
- platform: template
|
||||
name: "Evening Off Time State"
|
||||
name: "Timeclock: Evening Off Time"
|
||||
lambda: |-
|
||||
int hour = id(evening_off) / 60;
|
||||
int minute = id(evening_off) % 60;
|
||||
@@ -494,25 +467,45 @@ text_sensor:
|
||||
update_interval: ${update_interval}
|
||||
|
||||
######################################################
|
||||
# ESPHome Info
|
||||
# Creates a sensor showing when the device was last restarted
|
||||
# Uptime template sensor, and SNTP are needed
|
||||
######################################################
|
||||
- platform: version
|
||||
name: ${friendly_name} Version
|
||||
- platform: wifi_info
|
||||
ip_address:
|
||||
name: ${friendly_name} IP Address
|
||||
- platform: template
|
||||
name: "Last Restart: ${friendly_name}"
|
||||
id: device_last_restart
|
||||
update_interval: ${update_interval}
|
||||
icon: mdi:clock
|
||||
entity_category: diagnostic
|
||||
|
||||
- platform: template
|
||||
name: "Time Sync Status"
|
||||
id: time_sync
|
||||
update_interval: ${update_interval}
|
||||
entity_category: diagnostic
|
||||
|
||||
- platform: template
|
||||
name: "Internal Time"
|
||||
id: time_text
|
||||
update_interval: ${update_interval}
|
||||
entity_category: diagnostic
|
||||
lambda: |-
|
||||
auto time_text = id(sntp_time).now().strftime("%H:%M:%S - %d-%m-%Y");
|
||||
return { time_text };
|
||||
|
||||
#############################################
|
||||
# General Sensors
|
||||
# https://esphome.io/components/sensor/index.html
|
||||
# Sensors
|
||||
# https://esphome.io/components/text_sensor/index.html
|
||||
#############################################
|
||||
sensor:
|
||||
- platform: uptime # Uptime for this device
|
||||
name: ${friendly_name} Uptime
|
||||
update_interval: ${update_interval}
|
||||
- platform: wifi_signal # Wifi Strength
|
||||
name: ${friendly_name} Wifi Signal
|
||||
update_interval: ${update_interval}
|
||||
- platform: template
|
||||
name: "Mins from Midnight"
|
||||
unit_of_measurement: "mins"
|
||||
accuracy_decimals: 0
|
||||
update_interval: ${update_interval}
|
||||
internal: True
|
||||
lambda: |-
|
||||
return id(current_mins);
|
||||
|
||||
|
||||
####################################################
|
||||
# Relay Switch (Sonoff Basic Relay on GPIO12)
|
||||
@@ -528,9 +521,27 @@ switch:
|
||||
# Check every minute to decide relay state
|
||||
####################################################
|
||||
interval:
|
||||
- interval: ${update_interval}
|
||||
- interval: "1min" # Must be 1min as this is used to calculate times
|
||||
then:
|
||||
- lambda: |-
|
||||
|
||||
// Do we have correct time from SNTP? If not...
|
||||
if (!id(time_sync).has_state()) {
|
||||
// Set minutes since midnight
|
||||
id(current_mins) = id(current_mins) +1 ;
|
||||
|
||||
// wrap around at 1440 => next day
|
||||
if (id(current_mins) >= 1440) {
|
||||
id(current_mins) = 0;
|
||||
}
|
||||
|
||||
// If we do have proper SNMP time...
|
||||
} else {
|
||||
// Use real time from SNTP
|
||||
auto now = id(sntp_time).now();
|
||||
id(current_mins) = now.hour * 60 + now.minute;
|
||||
}
|
||||
|
||||
// operation_mode:
|
||||
// 0 = OFF
|
||||
// 1 = ON
|
||||
@@ -543,7 +554,7 @@ interval:
|
||||
// minutes, then automatically revert to TIMER.
|
||||
//////////////////////////////////////////////////
|
||||
if (mode == 3) {
|
||||
id(startup_timer)++;
|
||||
id(startup_timer) = id(startup_timer) + 1 ; // works as long as update_interval in seconds
|
||||
// Compare with the substitution startup_duration
|
||||
if (id(startup_timer) < (int) ${startup_duration}) {
|
||||
// Still within the STARTUP period => turn relay on
|
||||
@@ -551,8 +562,10 @@ interval:
|
||||
} else {
|
||||
// After 'startup_duration' minutes => switch to TIMER
|
||||
id(operation_mode) = 2;
|
||||
id(mqtt_client).publish("${mqtt_timer_topic}/operation", "TIMER");
|
||||
}
|
||||
// Skip the rest of the logic
|
||||
ESP_LOGI("startup_timer", "startup_timer=%d", id(startup_timer));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -574,50 +587,26 @@ interval:
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// TIMER MODE => follow morning/evening schedule
|
||||
// using SNTP if valid, else fallback_time
|
||||
// using SNTP if valid, else current_mins
|
||||
//////////////////////////////////////////////////
|
||||
if (mode == 2) {
|
||||
auto now = id(sntp_time).now();
|
||||
bool have_sntp = now.is_valid();
|
||||
|
||||
int current_mins;
|
||||
if (!have_sntp) {
|
||||
// SNTP not available => fallback clock
|
||||
current_mins = id(fallback_time);
|
||||
// increment the fallback clock by 1 minute
|
||||
id(fallback_time) += 1;
|
||||
// wrap around at 1440 => next day
|
||||
if (id(fallback_time) >= 1440) {
|
||||
id(fallback_time) = 0;
|
||||
}
|
||||
} else {
|
||||
// Use real time from SNTP
|
||||
current_mins = now.hour * 60 + now.minute;
|
||||
}
|
||||
if (mode == 2)
|
||||
{
|
||||
|
||||
bool should_on = false;
|
||||
|
||||
// If evening_off == 0 => treat as midnight => 1440
|
||||
int evening_off_local = id(evening_off);
|
||||
if (evening_off_local == 0) {
|
||||
evening_off_local = 1440;
|
||||
}
|
||||
|
||||
// Check morning window
|
||||
// Example: morning_on=360 => 06:00, morning_off=480 => 08:00
|
||||
// If current_mins in [360..480), should_on = true
|
||||
if (id(morning_on) < id(morning_off)) {
|
||||
if (current_mins >= id(morning_on) && current_mins < id(morning_off)) {
|
||||
should_on = true;
|
||||
}
|
||||
if (id(current_mins) >= id(morning_on) && id(current_mins) < id(morning_off) )
|
||||
{
|
||||
should_on = true;
|
||||
}
|
||||
|
||||
// Check evening window
|
||||
// Example: evening_on=540 => 09:00, evening_off=1440 => midnight
|
||||
if (id(evening_on) < evening_off_local) {
|
||||
if (current_mins >= id(evening_on) && current_mins < evening_off_local) {
|
||||
should_on = true;
|
||||
}
|
||||
// Example: evening_on=1260 => 21:00, evening_off=1440 => midnight
|
||||
if (id(current_mins) >= id(evening_on) && id(current_mins) < id(evening_off) )
|
||||
{
|
||||
should_on = true;
|
||||
}
|
||||
|
||||
// Final relay state based on schedule
|
||||
@@ -626,4 +615,8 @@ interval:
|
||||
} else {
|
||||
id(relay).turn_off();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -165,8 +165,8 @@ mqtt:
|
||||
topic_prefix: ${mqtt_topic}/${device_name}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: True # enable entity discovery (true is default)
|
||||
discover_ip: True # enable device discovery (true is default)
|
||||
discovery: False # enable entity discovery (true is default)
|
||||
#discover_ip: True # enable device discovery (true is default)
|
||||
|
||||
|
||||
#############################################
|
||||
@@ -291,5 +291,72 @@ light:
|
||||
warm_white: output_ww
|
||||
cold_white_color_temperature: 4800 K
|
||||
warm_white_color_temperature: 2500 K # 2500k is the original value of the lamp. To correct binning for 2700k to look more like 2700k use 2650k instead
|
||||
restore_mode: ALWAYS_ON
|
||||
gamma_correct: 0
|
||||
restore_mode: ALWAYS_OFF
|
||||
gamma_correct: 0
|
||||
|
||||
|
||||
|
||||
|
||||
#globals:
|
||||
# - id: fade_brightness
|
||||
# type: float
|
||||
# initial_value: '0.0'
|
||||
# - id: fade_step
|
||||
# type: float
|
||||
# initial_value: '0.0'
|
||||
|
||||
|
||||
# This script fades the light ON to full brightness over 20 seconds.
|
||||
#script:
|
||||
# - id: fade_on
|
||||
# then:
|
||||
# # First, capture the current brightness.
|
||||
# - lambda: |-
|
||||
# // If the light is off, current brightness will be 0.0.
|
||||
# float current = id(light1).current_values.get_brightness();
|
||||
# id(fade_brightness) = current;
|
||||
# // Compute the step size so that after 100 steps (200ms each) we reach full brightness.
|
||||
# id(fade_step) = (1.0 - current) / 100.0;
|
||||
# - repeat:
|
||||
# count: 100
|
||||
# then:
|
||||
# - lambda: |-
|
||||
# id(fade_brightness) += id(fade_step);
|
||||
# if (id(fade_brightness) > 1.0) {
|
||||
# id(fade_brightness) = 1.0;
|
||||
# }
|
||||
# // Update the light’s brightness.
|
||||
# id(light1).turn_on({ brightness: id(fade_brightness) });
|
||||
# - delay: 200ms
|
||||
|
||||
# This script fades the light OFF over 20 seconds.
|
||||
# - id: fade_off
|
||||
# then:
|
||||
# - lambda: |-
|
||||
# // Capture current brightness (if the light is on).
|
||||
# float current = id(light1).current_values.get_brightness();
|
||||
# id(fade_brightness) = current;
|
||||
# // Compute step size so that after 100 steps we reach 0.
|
||||
# id(fade_step) = current / 100.0;
|
||||
# - repeat:
|
||||
# count: 100
|
||||
# then:
|
||||
# - lambda: |-
|
||||
# id(fade_brightness) -= id(fade_step);
|
||||
# if (id(fade_brightness) < 0.0) {
|
||||
# id(fade_brightness) = 0.0;
|
||||
# }
|
||||
# id(light1).turn_on({ brightness: id(fade_brightness) });
|
||||
# - delay: 200ms
|
||||
# # Finally, ensure the light is turned off.
|
||||
# - lambda: |-
|
||||
# id(light1).turn_off();
|
||||
|
||||
#switch:
|
||||
# - platform: template
|
||||
# name: "Fade on and off"
|
||||
# id: virtual_switch
|
||||
# turn_on_action:
|
||||
# - script.execute: fade_on
|
||||
# turn_off_action:
|
||||
# - script.execute: fade_off
|
86
esphome/esp-nexmulti1.yaml
Normal file
86
esphome/esp-nexmulti1.yaml
Normal file
@@ -0,0 +1,86 @@
|
||||
#############################################
|
||||
#############################################
|
||||
#
|
||||
#
|
||||
#
|
||||
# V1.0 2025-02-14 Initial Version
|
||||
#
|
||||
# pinout/schematic https://community.home-assistant.io/t/zemismart-ks-811-working-with-esphome/
|
||||
#
|
||||
# INSTRUCTIONS
|
||||
# -
|
||||
#
|
||||
#############################################
|
||||
#############################################
|
||||
|
||||
substitutions:
|
||||
#############################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
#############################################
|
||||
devicename: "esp-nexmulti1"
|
||||
friendly_name: "esp-nexmulti1"
|
||||
description_comment: "Multisensor 1 test"
|
||||
|
||||
api_key: !secret esp-nexmulti1_api_key # unfortunately you can't use substitutions inside secrets names
|
||||
ota_pass: !secret esp-nexmulti1_ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
static_ip_address: !secret esp-nexmulti1_ip
|
||||
|
||||
update_interval: 60s # update time for for general sensors etc
|
||||
|
||||
#############################################
|
||||
# Included Common Packages
|
||||
# https://esphome.io/components/esphome.html
|
||||
#############################################
|
||||
packages:
|
||||
common_wifi: !include
|
||||
file: common/network_common.yaml
|
||||
vars:
|
||||
local_static_ip_address: ${static_ip_address}
|
||||
local_api_key: ${api_key}
|
||||
local_ota_pass: ${ota_pass}
|
||||
common_mqtt: !include
|
||||
file: common/mqtt_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: ${devicename}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: ${description_comment} #Appears on the esphome page in HA
|
||||
|
||||
#############################################
|
||||
# ESP Platform and Framework
|
||||
# https://esphome.io/components/esp32.html
|
||||
#############################################
|
||||
esp8266:
|
||||
board: esp01_1m
|
||||
|
||||
#############################################
|
||||
# ESPHome Logging Enable
|
||||
# https://esphome.io/components/logger.html
|
||||
#############################################
|
||||
logger:
|
||||
level: INFO #INFO Level suggested, or DEBUG for testing
|
||||
#baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
|
||||
#esp8266_store_log_strings_in_flash: false
|
||||
#tx_buffer_size: 64
|
||||
|
||||
|
||||
#############################################
|
||||
# Real time clock time source for ESPHome
|
||||
# If it's invalid, we fall back to an internal clock
|
||||
# https://esphome.io/components/time/
|
||||
# https://esphome.io/components/time/sntp
|
||||
#############################################
|
||||
#time:
|
||||
# - platform: sntp
|
||||
# id: sntp_time
|
||||
|
@@ -183,8 +183,8 @@ mqtt:
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: True # enable entity discovery (true is default)
|
||||
discover_ip: True # enable device discovery (true is default)
|
||||
discovery: False # enable entity discovery (true is default)
|
||||
#discover_ip: True # enable device discovery (true is default)
|
||||
|
||||
|
||||
#############################################
|
||||
|
@@ -150,8 +150,8 @@ mqtt:
|
||||
topic_prefix: ${mqtt_topic}/${devicename}
|
||||
username: ${mqtt_username}
|
||||
password: ${mqtt_password}
|
||||
discovery: True # enable entity discovery (true is default)
|
||||
discover_ip: True # enable device discovery (true is default)
|
||||
discovery: false # enable entity discovery (true is default)
|
||||
#discover_ip: True # enable device discovery (true is default)
|
||||
|
||||
#############################################
|
||||
# Bluetooth
|
||||
|
@@ -11,5 +11,5 @@ foxhole_lights:
|
||||
- switch.tasmo_ks811t_2192_downstkitch_1a # Kitchen Entry Lights
|
||||
- switch.tasmo_ks811t_2192_downstkitch_1b # Kitchen Main Lights
|
||||
- switch.tasmo_ks811t_2192_downstkitch_1c # Kitchen (Unused, future strip lights)
|
||||
- switch.tasmo_ks811t_1181_downstbath_a # Downstairs Bathroom Main Lights
|
||||
- switch.tasmo_ks811t_1181_downstbath_b # Downstairs Bathroom Mirror Lights
|
||||
- switch.esp_downstbathswitch_relay_main_light # Downstairs Bathroom Main Lights
|
||||
- switch.esp_downstbathswitch_relay_cabinet_light # Downstairs Bathroom Mirror Lights
|
||||
|
@@ -1,6 +1,7 @@
|
||||
mqtt:
|
||||
sensor:
|
||||
- unique_id: washing_machine_finished
|
||||
device_class: timestamp
|
||||
name: "Washer Finished"
|
||||
state_topic: "viewroad-status/activityfeed/Washer_complete"
|
||||
icon: mdi:washing-machine
|
||||
|
25
packages/climate_master_bedroom_dehum.yaml
Normal file
25
packages/climate_master_bedroom_dehum.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
automation:
|
||||
|
||||
# Automation to turn on drying at 9pm in the master bedroom (if switched on ith the helper)
|
||||
- id: master_bedroom_offpeak_dehumidify
|
||||
alias: Master Bedroom Off-Peak Dehumidify
|
||||
mode: single
|
||||
trigger:
|
||||
- platform: time
|
||||
at: "21:20:00"
|
||||
condition:
|
||||
- condition: state
|
||||
entity_id: input_boolean.master_bedroom_offpeak_dehumidify
|
||||
state: "on"
|
||||
action:
|
||||
- service: climate.set_hvac_mode
|
||||
target:
|
||||
entity_id: climate.master_bedroom
|
||||
data:
|
||||
hvac_mode: dry
|
||||
- wait_for_trigger:
|
||||
- platform: time
|
||||
at: "00:00:00"
|
||||
- service: climate.turn_off
|
||||
target:
|
||||
entity_id: climate.master_bedroom
|
@@ -13,11 +13,11 @@ input_select:
|
||||
|
||||
input_boolean:
|
||||
heat_pump_automation:
|
||||
name: Enable Heat Master Bedroom Night Cycling
|
||||
name: Enable Heat Pump Master Bedroom Night Cycling
|
||||
initial: off
|
||||
|
||||
automation:
|
||||
- alias: "Master Bedroom Night Cycling"
|
||||
- alias: "Master Bedroom Heat Pump Night Cycling"
|
||||
description: "Turns the climate.master_bedroom to 'cool' for 15 minutes every hour if temperature is below the selected threshold."
|
||||
trigger:
|
||||
- platform: time_pattern # Use time_pattern to run the automation on a recurring schedule.
|
||||
@@ -31,7 +31,6 @@ automation:
|
||||
- condition: template
|
||||
value_template: >
|
||||
{{ states('sensor.master_bedroom_environment_zth01_temperature_2') | float > states('input_select.heat_pump_temperature_threshold') | float }}
|
||||
|
||||
# Actions: Define the steps of the automation.
|
||||
action:
|
||||
# Action 1: Turn on the heat pump by setting HVAC mode to "cool".
|
||||
@@ -48,7 +47,6 @@ automation:
|
||||
- service: climate.turn_off
|
||||
target:
|
||||
entity_id: climate.master_bedroom
|
||||
|
||||
mode: single # Ensures only one instance of this automation runs at a time.
|
||||
|
||||
# always switch off the automation at 5am
|
||||
@@ -73,3 +71,15 @@ automation:
|
||||
target:
|
||||
entity_id: climate.master_bedroom
|
||||
mode: single
|
||||
|
||||
# ensure the automation is off on a HA reboot
|
||||
- alias: "Ensure Heat Pump Automation is Off on Startup"
|
||||
description: "Turns off the heat pump automation (input_boolean.heat_pump_automation) when Home Assistant starts."
|
||||
trigger:
|
||||
- platform: homeassistant
|
||||
event: start
|
||||
action:
|
||||
- service: input_boolean.turn_off
|
||||
target:
|
||||
entity_id: input_boolean.heat_pump_automation
|
||||
mode: single
|
||||
|
@@ -1,12 +1,12 @@
|
||||
mqtt_statestream:
|
||||
base_topic: hamqtt
|
||||
publish_attributes: true
|
||||
publish_timestamps: true
|
||||
include:
|
||||
entities:
|
||||
- sensor.main_bathroom_humidity_change_rate
|
||||
entity_globs:
|
||||
- sensor.*_zt*
|
||||
#mqtt_statestream:
|
||||
# base_topic: hamqtt
|
||||
# publish_attributes: true
|
||||
# publish_timestamps: true
|
||||
# include:
|
||||
# entities:
|
||||
# - sensor.main_bathroom_humidity_change_rate
|
||||
# entity_globs:
|
||||
# - sensor.*_zt*
|
||||
#exclude:
|
||||
# entity_globs:
|
||||
# - sensor.*zoruno*
|
||||
# - sensor.*zoruno*
|
@@ -40,5 +40,5 @@ switch:
|
||||
- switch.tasmo_ks811t_3642_downstbed1_1a # Foxhole Main Bedroom, Main Lights
|
||||
- switch.tasmo_ks811t_2192_downstkitch_1a # Foxhole Kitchen Entry Lights
|
||||
- switch.tasmo_ks811t_2192_downstkitch_1b # Foxhole Kitchen Main Lights
|
||||
- switch.tasmo_ks811t_1181_downstbath_a # Foxhole Downstairs Bathroom Main Lights
|
||||
- switch.esp_downstbathswitch_relay_main_light # Foxhole Downstairs Bathroom Main Lights
|
||||
- switch.tasmo_s4chan_4231_underhouselights_b # Underhouse Main Lights
|
||||
|
@@ -15,42 +15,42 @@ mqtt:
|
||||
- unique_id: weewx_outTemp_C
|
||||
state_topic: "weewx/outTemp_C"
|
||||
name: "Weewx Outdoor Temperature"
|
||||
unit_of_measurement: "C"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: "temperature"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
icon: "mdi:thermometer"
|
||||
- unique_id: weewx_inTemp_C
|
||||
state_topic: "weewx/inTemp_C"
|
||||
name: "Weewx Indoor Temperature"
|
||||
unit_of_measurement: "C"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: "temperature"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
icon: "mdi:thermometer"
|
||||
- unique_id: weewx_humidex_C
|
||||
state_topic: "weewx/humidex_C"
|
||||
name: "Weewx Humidex"
|
||||
unit_of_measurement: "C"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: "temperature"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
icon: "mdi:thermometer"
|
||||
- unique_id: weewx_dewpoint_C
|
||||
state_topic: "weewx/dewpoint_C"
|
||||
name: "Weewx Dewpoint"
|
||||
unit_of_measurement: "C"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: "temperature"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
icon: "mdi:thermometer"
|
||||
- unique_id: weewx_heatindex_C
|
||||
state_topic: "weewx/heatindex_C"
|
||||
name: "Weewx Heat Index"
|
||||
unit_of_measurement: "C"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: "temperature"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
icon: "mdi:thermometer"
|
||||
- unique_id: weewx_windchill_C
|
||||
state_topic: "weewx/windchill_C"
|
||||
name: "Weewx Windchill"
|
||||
unit_of_measurement: "C"
|
||||
unit_of_measurement: "°C"
|
||||
device_class: "temperature"
|
||||
value_template: "{{ value | round(1) }}"
|
||||
icon: "mdi:thermometer"
|
||||
|
Reference in New Issue
Block a user