yaml tidyups and warning removals
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
|||||||
{"pid": 67, "version": 1, "ha_version": "2026.1.2", "start_ts": 1768726150.935691}
|
{"pid": 67, "version": 1, "ha_version": "2026.1.3", "start_ts": 1769216420.8243344}
|
||||||
@@ -59,12 +59,12 @@ wifi:
|
|||||||
# Allow rapid re-connection to previously connect WiFi SSID, skipping scan of all SSID
|
# Allow rapid re-connection to previously connect WiFi SSID, skipping scan of all SSID
|
||||||
fast_connect: ${wifi_fast_connect}
|
fast_connect: ${wifi_fast_connect}
|
||||||
# Define dns domain / suffix to add to hostname
|
# Define dns domain / suffix to add to hostname
|
||||||
domain: "${dns_domain}"
|
domain: ${dns_domain}
|
||||||
#min_auth_mode: WPA2
|
min_auth_mode: WPA2
|
||||||
# Reboot eventually when Wi-Fi is down (default is 15min)
|
# Reboot eventually when Wi-Fi is down (default is 15min)
|
||||||
reboot_timeout: 56h
|
reboot_timeout: 56h
|
||||||
|
|
||||||
#captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
||||||
|
|
||||||
###########################################################################################
|
###########################################################################################
|
||||||
# Enable Over the Air Update Capability
|
# Enable Over the Air Update Capability
|
||||||
|
|||||||
@@ -11,6 +11,33 @@ substitutions:
|
|||||||
sntp_server_2: !secret ntp_server_2
|
sntp_server_2: !secret ntp_server_2
|
||||||
sntp_server_3: !secret ntp_server_3
|
sntp_server_3: !secret ntp_server_3
|
||||||
|
|
||||||
|
###########################################################################################
|
||||||
|
# Internal clock fallback support
|
||||||
|
# If SNTP is invalid, we fall back to a simple internal minute counter
|
||||||
|
# We assume user powers on the device at 12:00 noon
|
||||||
|
# => 12 * 60 = 720 minutes from midnight.
|
||||||
|
# Not restored, so it resets each boot.
|
||||||
|
# Therefore, if no network and you still need timing functions, switch on ay noon.
|
||||||
|
###########################################################################################
|
||||||
|
globals:
|
||||||
|
- id: current_mins
|
||||||
|
type: int
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "720" # 720 is 12:00 Noon
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 60s
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// If SNTP valid, store minutes since midnight.
|
||||||
|
auto now = id(sntp_time).now();
|
||||||
|
if (now.is_valid()) {
|
||||||
|
id(current_mins) = (now.hour * 60) + now.minute;
|
||||||
|
} else {
|
||||||
|
// Fallback: minutes since boot.
|
||||||
|
id(current_mins) = (int)(millis() / 60000UL);
|
||||||
|
}
|
||||||
|
|
||||||
###########################################################################################
|
###########################################################################################
|
||||||
# Real time clock time source for ESPHome
|
# Real time clock time source for ESPHome
|
||||||
# If it's invalid, we fall back to an internal clock
|
# If it's invalid, we fall back to an internal clock
|
||||||
@@ -72,7 +99,6 @@ text_sensor:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: show internal clock based on current_mins (minutes from midnight).
|
// Fallback: show internal clock based on current_mins (minutes from midnight).
|
||||||
// NOTE: current_mins is expected to be a global defined in the main device YAML.
|
|
||||||
int mins = id(current_mins);
|
int mins = id(current_mins);
|
||||||
if (mins < 0) mins = 0;
|
if (mins < 0) mins = 0;
|
||||||
if (mins >= 1440) mins = mins % 1440;
|
if (mins >= 1440) mins = mins % 1440;
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ status_led:
|
|||||||
pin:
|
pin:
|
||||||
number: GPIO2
|
number: GPIO2
|
||||||
inverted: yes
|
inverted: yes
|
||||||
|
ignore_strapping_warning: true # GPIO2: This just supresses a warning, we know what we are doing
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# SCRIPT COMPONENT
|
# SCRIPT COMPONENT
|
||||||
@@ -478,6 +479,7 @@ binary_sensor:
|
|||||||
number: GPIO05
|
number: GPIO05
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: true
|
inverted: true
|
||||||
|
ignore_strapping_warning: true # GPIO05: This just supresses a warning, we know what we are doing
|
||||||
name: "Button 3: ${switch_3_name}"
|
name: "Button 3: ${switch_3_name}"
|
||||||
filters:
|
filters:
|
||||||
- delayed_on: 50ms
|
- delayed_on: 50ms
|
||||||
@@ -864,7 +866,7 @@ sensor:
|
|||||||
pin: GPIO36
|
pin: GPIO36
|
||||||
id: dimmer_raw
|
id: dimmer_raw
|
||||||
name: "${variable_1_name} Raw"
|
name: "${variable_1_name} Raw"
|
||||||
attenuation: 11db
|
attenuation: 12db
|
||||||
update_interval: 0.5s
|
update_interval: 0.5s
|
||||||
on_value:
|
on_value:
|
||||||
then:
|
then:
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
##########################################################################################
|
||||||
|
##########################################################################################
|
||||||
|
#
|
||||||
|
##########################################################################################
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||||
|
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||||
|
##########################################################################################
|
||||||
|
substitutions:
|
||||||
|
# Device Naming
|
||||||
|
device_name: "esp-arcademachine1"
|
||||||
|
friendly_name: "Arcade Cabinet 1"
|
||||||
|
description_comment: "MAME Arcade 1 (Defender) machine power :: Athom Smart Plug Power V1"
|
||||||
|
device_area: "Downstairs Flat" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant.
|
||||||
|
|
||||||
|
# Project Naming
|
||||||
|
project_name: "Athom Technology.Smart Plug V1" # Project Details
|
||||||
|
project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
|
||||||
|
|
||||||
|
# Passwords
|
||||||
|
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
|
||||||
|
ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||||
|
static_ip_address: !secret esp-arcademachine1_ip
|
||||||
|
|
||||||
|
# Device Settings
|
||||||
|
log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
|
||||||
|
update_interval: "10s" # update time for for general sensors etc
|
||||||
|
|
||||||
|
# Device Settings
|
||||||
|
relay_icon: "mdi:power-socket-au"
|
||||||
|
current_limit : "10" # Current Limit in Amps. AU Plug = 10. IL, BR, EU, UK, US Plug = 16.
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# PACKAGES: Included Common Packages
|
||||||
|
# https://esphome.io/components/packages.html
|
||||||
|
##########################################################################################
|
||||||
|
packages:
|
||||||
|
##################################################
|
||||||
|
# MANDATORY packages (won't compile without them!)
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
#### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode ####
|
||||||
|
common_wifi: !include
|
||||||
|
file: common/network_common.yaml
|
||||||
|
vars:
|
||||||
|
local_device_name: "${device_name}"
|
||||||
|
local_static_ip_address: "${static_ip_address}"
|
||||||
|
local_ota_pass: "${ota_pass}"
|
||||||
|
|
||||||
|
##################################################
|
||||||
|
# OPTIONAL packages (comment if you don't want them)
|
||||||
|
##################################################
|
||||||
|
|
||||||
|
#### HOME ASSISTANT API (choose encryption or no encryption options) ####
|
||||||
|
common_api: !include
|
||||||
|
file: common/api_common.yaml
|
||||||
|
#file: common/api_common_noencryption.yaml
|
||||||
|
vars:
|
||||||
|
local_api_key: "${api_key}"
|
||||||
|
|
||||||
|
#### WEB PORTAL ####
|
||||||
|
#common_webportal: !include
|
||||||
|
# file: common/webportal_common.yaml
|
||||||
|
|
||||||
|
#### MQTT ####
|
||||||
|
common_mqtt: !include
|
||||||
|
file: common/mqtt_common.yaml
|
||||||
|
vars:
|
||||||
|
local_device_name: "${device_name}"
|
||||||
|
|
||||||
|
#### SNTP (Only use if you want/need accurate timeclocks) ####
|
||||||
|
common_sntp: !include
|
||||||
|
file: common/sntp_common.yaml
|
||||||
|
|
||||||
|
#### DIAGNOSTICS Lite Sensors ####
|
||||||
|
common_lite_sensors: !include
|
||||||
|
file: common/sensors_common_lite.yaml
|
||||||
|
|
||||||
|
#### DIAGNOSTICS General Sensors ####
|
||||||
|
common_general_sensors: !include
|
||||||
|
file: common/sensors_common.yaml
|
||||||
|
|
||||||
|
#### DEBUGGING Sensors ####
|
||||||
|
# A count of various resets
|
||||||
|
#common_resetcount_debugging: !include
|
||||||
|
# file: common/resetcount_common.yaml
|
||||||
|
|
||||||
|
# Device Specific included packages
|
||||||
|
common_athompowermonV1: !include
|
||||||
|
file: common/athompowermonv1_common.yaml
|
||||||
|
vars:
|
||||||
|
local_friendly_name: "${friendly_name}"
|
||||||
|
local_current_limit: "${current_limit}"
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# ESPHome
|
||||||
|
# https://esphome.io/components/esphome.html
|
||||||
|
##########################################################################################
|
||||||
|
esphome:
|
||||||
|
name: "${device_name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${description_comment}" #Appears on the esphome page in HA
|
||||||
|
area: "${device_area}"
|
||||||
|
name_add_mac_suffix: False
|
||||||
|
min_version: 2024.6.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# ESP Platform and Framework
|
||||||
|
# https://esphome.io/components/esp32.html
|
||||||
|
##########################################################################################
|
||||||
|
esp8266:
|
||||||
|
board: esp8285
|
||||||
|
restore_from_flash: true # mainly for calculating cumulative energy, but not that important here
|
||||||
|
#framework:
|
||||||
|
# version: 2.7.4
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 10min
|
||||||
|
|
||||||
|
#mdns:
|
||||||
|
# disabled: True # binary size saving
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# ESPHome Logging Enable
|
||||||
|
# https://esphome.io/components/logger.html
|
||||||
|
##########################################################################################
|
||||||
|
logger:
|
||||||
|
level: "${log_level}" #INFO Level suggested, or DEBUG for testing
|
||||||
|
baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
|
||||||
|
#esp8266_store_log_strings_in_flash: false
|
||||||
|
#tx_buffer_size: 64
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# Global Variables for use in automations etc
|
||||||
|
# https://esphome.io/guides/automations.html?highlight=globals#global-variables
|
||||||
|
##########################################################################################
|
||||||
|
globals:
|
||||||
|
|
||||||
|
# Tracks the time (in seconds from midnight) at the previous boot
|
||||||
|
- id: last_boot_time_s
|
||||||
|
type: int
|
||||||
|
restore_value: true
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
# Counts how many consecutive boots have occurred (within X seconds)
|
||||||
|
- id: boot_count
|
||||||
|
type: int
|
||||||
|
restore_value: true
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# boost_timer: counts minutes in BOOST mode
|
||||||
|
# After 'boost_duration' minutes, revert to TIMER.
|
||||||
|
####################################################
|
||||||
|
- id: boost_timer
|
||||||
|
type: int
|
||||||
|
restore_value: true
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# BINARY SENSORS
|
||||||
|
# https://esphome.io/components/binary_sensor/
|
||||||
|
##########################################################################################
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
pin:
|
||||||
|
number: GPIO03
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
name: "Power Button"
|
||||||
|
id: power_button
|
||||||
|
filters:
|
||||||
|
- delayed_on: 20ms
|
||||||
|
on_click:
|
||||||
|
- min_length: 20ms
|
||||||
|
max_length: 500ms
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
if (id(relay).state) {
|
||||||
|
// Relay is ON: turn it OFF and set mode to 2 (TIMER)
|
||||||
|
id(relay).turn_off();
|
||||||
|
} else {
|
||||||
|
// Relay is OFF: turn it ON and set mode to 3 (BOOST)
|
||||||
|
id(relay).turn_on();
|
||||||
|
}
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Relay Status"
|
||||||
|
lambda: |-
|
||||||
|
return id(relay).state;
|
||||||
|
|
||||||
|
#################################################################################################
|
||||||
|
# SWITCH COMPONENT
|
||||||
|
# https://esphome.io/components/switch/
|
||||||
|
#################################################################################################
|
||||||
|
switch:
|
||||||
|
- platform: gpio
|
||||||
|
name: "Power Output"
|
||||||
|
pin: GPIO14
|
||||||
|
id: relay
|
||||||
|
restore_mode: RESTORE_DEFAULT_OFF # Ensures the relay is restored (or off) at boot
|
||||||
|
#internal: true # Hides the switch from Home Assistant
|
||||||
|
icon: "${relay_icon}"
|
||||||
|
|
||||||
@@ -141,6 +141,7 @@ wifi:
|
|||||||
ssid: ${devicename} AP
|
ssid: ${devicename} AP
|
||||||
password: ${fallback_ap_password}
|
password: ${fallback_ap_password}
|
||||||
ap_timeout: 30min # Time until it brings up fallback AP. default is 1min
|
ap_timeout: 30min # Time until it brings up fallback AP. default is 1min
|
||||||
|
min_auth_mode: WPA2
|
||||||
|
|
||||||
captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
|
||||||
|
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- mqtt.publish:
|
- mqtt.publish:
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -121,8 +121,8 @@ esphome:
|
|||||||
build_flags:
|
build_flags:
|
||||||
- "-Os" # optimize for size
|
- "-Os" # optimize for size
|
||||||
- "-Wl,--gc-sections" # drop unused code/data
|
- "-Wl,--gc-sections" # drop unused code/data
|
||||||
- "-fno-exceptions" # strip C++ exceptions
|
#- "-fno-exceptions" # strip C++ exceptions
|
||||||
- "-fno-rtti" # strip C++ RTTI
|
#- "-fno-rtti" # strip C++ RTTI
|
||||||
# on_boot:
|
# on_boot:
|
||||||
# priority: 200
|
# priority: 200
|
||||||
# then:
|
# then:
|
||||||
@@ -170,6 +170,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- mqtt.publish:
|
- mqtt.publish:
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ binary_sensor:
|
|||||||
input: true
|
input: true
|
||||||
pullup: false # set to true if you need an internal pull-up
|
pullup: false # set to true if you need an internal pull-up
|
||||||
inverted: true
|
inverted: true
|
||||||
|
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
filters:
|
filters:
|
||||||
- delayed_on: 30ms
|
- delayed_on: 30ms
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ switch:
|
|||||||
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
||||||
- platform: template
|
- platform: template
|
||||||
id: mosfet_ramp_switch
|
id: mosfet_ramp_switch
|
||||||
name: "${friendly_name} Fade Up/Down"
|
name: "${friendly_name} Fade Up-Down"
|
||||||
icon: mdi:led-strip-variant
|
icon: mdi:led-strip-variant
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return id(ramp_switch_target_on);
|
return id(ramp_switch_target_on);
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
filters:
|
filters:
|
||||||
- delayed_on: 30ms
|
- delayed_on: 30ms
|
||||||
- delayed_off: 30ms
|
- delayed_off: 30ms
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
filters:
|
filters:
|
||||||
- delayed_on: 30ms
|
- delayed_on: 30ms
|
||||||
- delayed_off: 30ms
|
- delayed_off: 30ms
|
||||||
|
|||||||
@@ -108,16 +108,18 @@ esphome:
|
|||||||
# Restore "Last Trip" text from persisted epoch (if any)
|
# Restore "Last Trip" text from persisted epoch (if any)
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
if (id(last_trip_epoch) > 0) {
|
if (id(last_trip_epoch) > 0) {
|
||||||
auto t = time::ESPTime::from_epoch_local(id(last_trip_epoch));
|
time_t tt = (time_t) id(last_trip_epoch);
|
||||||
|
struct tm tm;
|
||||||
|
localtime_r(&tt, &tm);
|
||||||
char buf[24];
|
char buf[24];
|
||||||
t.strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S");
|
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
|
||||||
id(ts_last_trip).publish_state(buf);
|
id(ts_last_trip).publish_state(buf);
|
||||||
} else {
|
} else {
|
||||||
id(ts_last_trip).publish_state("Never");
|
id(ts_last_trip).publish_state("Never");
|
||||||
}
|
}
|
||||||
# Apply Power Restore Mode selector (Always ON / Always OFF / Previous State)
|
# Apply Power Restore Mode selector (Always ON / Always OFF / Previous State)
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
std::string mode = id(sel_restore_mode).state;
|
std::string mode = id(sel_restore_mode).current_option();
|
||||||
if (mode == "Always ON") {
|
if (mode == "Always ON") {
|
||||||
id(relay_virtual).turn_on();
|
id(relay_virtual).turn_on();
|
||||||
} else if (mode == "Always OFF") {
|
} else if (mode == "Always OFF") {
|
||||||
@@ -151,6 +153,7 @@ status_led:
|
|||||||
pin:
|
pin:
|
||||||
number: GPIO8
|
number: GPIO8
|
||||||
inverted: true
|
inverted: true
|
||||||
|
ignore_strapping_warning: true # GPIO08: This just supresses a warning, we know what we are doing
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# UART BUS
|
# UART BUS
|
||||||
@@ -550,6 +553,7 @@ binary_sensor:
|
|||||||
number: GPIO9
|
number: GPIO9
|
||||||
mode: INPUT_PULLUP
|
mode: INPUT_PULLUP
|
||||||
inverted: true
|
inverted: true
|
||||||
|
ignore_strapping_warning: true # GPIO09: This just supresses a warning, we know what we are doing
|
||||||
name: "${button_1_name}"
|
name: "${button_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: relay_virtual
|
- switch.toggle: relay_virtual
|
||||||
@@ -743,7 +747,7 @@ script:
|
|||||||
if (f > 1.0f) f = 1.0f;
|
if (f > 1.0f) f = 1.0f;
|
||||||
int slow_ms = ${led_flash_slow_ms};
|
int slow_ms = ${led_flash_slow_ms};
|
||||||
int fast_ms = ${led_flash_fast_ms};
|
int fast_ms = ${led_flash_fast_ms};
|
||||||
if (slow_ms < fast_ms) { int t = slow_ms; slow_ms = fast_ms; fast_ms = t; } # ensure slow >= fast
|
if (slow_ms < fast_ms) { int t = slow_ms; slow_ms = fast_ms; fast_ms = t; } // ensure slow >= fast
|
||||||
int period = slow_ms - (int)((slow_ms - fast_ms) * f);
|
int period = slow_ms - (int)((slow_ms - fast_ms) * f);
|
||||||
id(_blink_period_ms) = period;
|
id(_blink_period_ms) = period;
|
||||||
# Blink with 50% duty cycle at the computed period
|
# Blink with 50% duty cycle at the computed period
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ switch:
|
|||||||
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
||||||
- platform: template
|
- platform: template
|
||||||
id: mosfet_ramp_switch
|
id: mosfet_ramp_switch
|
||||||
name: "${friendly_name} Fade Up/Down"
|
name: "${friendly_name} Fade Up-Down"
|
||||||
icon: mdi:led-strip-variant
|
icon: mdi:led-strip-variant
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return id(ramp_switch_target_on);
|
return id(ramp_switch_target_on);
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ esphome:
|
|||||||
build_flags:
|
build_flags:
|
||||||
- "-Os" # optimize for size
|
- "-Os" # optimize for size
|
||||||
- "-Wl,--gc-sections" # drop unused code/data
|
- "-Wl,--gc-sections" # drop unused code/data
|
||||||
- "-fno-exceptions" # strip C++ exceptions
|
#- "-fno-exceptions" # strip C++ exceptions
|
||||||
- "-fno-rtti" # strip C++ RTTI
|
#- "-fno-rtti" # strip C++ RTTI
|
||||||
on_boot:
|
on_boot:
|
||||||
priority: 900 # High priority to run after globals are initialized
|
priority: 900 # High priority to run after globals are initialized
|
||||||
then:
|
then:
|
||||||
@@ -274,17 +274,6 @@ globals:
|
|||||||
restore_value: true
|
restore_value: true
|
||||||
initial_value: "2"
|
initial_value: "2"
|
||||||
|
|
||||||
####################################################
|
|
||||||
# current_mins is set if SNTP is invalid.
|
|
||||||
# We assume user powers on the device at 12:00 noon
|
|
||||||
# => 12 * 60 = 720 minutes from midnight.
|
|
||||||
# Not restored, so it resets each boot.
|
|
||||||
####################################################
|
|
||||||
- id: current_mins
|
|
||||||
type: int
|
|
||||||
restore_value: false
|
|
||||||
initial_value: "720" # 720 is 12:00 Noon
|
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
# boost_timer: counts minutes in BOOST mode
|
# boost_timer: counts minutes in BOOST mode
|
||||||
# After 'boost_duration' minutes, revert to TIMER.
|
# After 'boost_duration' minutes, revert to TIMER.
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -438,6 +438,7 @@ binary_sensor:
|
|||||||
mode:
|
mode:
|
||||||
input: true
|
input: true
|
||||||
pullup: true
|
pullup: true
|
||||||
|
ignore_strapping_warning: true # GPIO15: This just supresses a warning, we know what we are doing
|
||||||
inverted: True
|
inverted: True
|
||||||
filters:
|
filters:
|
||||||
- delayed_on: 20ms
|
- delayed_on: 20ms
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
##########################################################################################
|
##########################################################################################
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# FLY SPRAYER – Sinilink XY-WFUSB (ESP8266/ESP8285) – ESPHome
|
# FLY SPRAYER - Sinilink XY-WFUSB (ESP8266/ESP8285) - ESPHome
|
||||||
#
|
#
|
||||||
# V1.0 2025-05-30 Initial Version
|
# V1.0 2025-05-30 Initial Version
|
||||||
#
|
#
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
# - Sprayer has its own timers, but it fires whenever it is started up, which we utilise here.
|
# - Sprayer has its own timers, but it fires whenever it is started up, which we utilise here.
|
||||||
# - Enforce a cooldown so it never double-fires too quickly (Sprayer has some memory)
|
# - Enforce a cooldown so it never double-fires too quickly (Sprayer has some memory)
|
||||||
# - Operation window select: Night only / Day only / 24 Hours / On / Off.
|
# - Operation window select: Night only / Day only / 24 Hours / On / Off.
|
||||||
# - Randomize each interval by ± a percentage to avoid a perfectly regular pattern.
|
# - Randomize each interval by +- a percentage to avoid a perfectly regular pattern.
|
||||||
# - Red LED (GPIO14, inverted) pulses slowly when idle; goes solid ON during spray.
|
# - Red LED (GPIO14, inverted) pulses slowly when idle; goes solid ON during spray.
|
||||||
# - Green LED (GPIO16) as standard ESPHome status LED.
|
# - Green LED (GPIO16) as standard ESPHome status LED.
|
||||||
# - Has a resettable total spray count, and a daily spray count
|
# - Has a resettable total spray count, and a daily spray count
|
||||||
@@ -26,14 +26,14 @@
|
|||||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
substitutions:
|
substitutions:
|
||||||
# Device Naming
|
# Device Naming
|
||||||
device_name: "esp-flysprayer1"
|
device_name: "esp-flysprayer1"
|
||||||
friendly_name: "Fly Sprayer"
|
friendly_name: "Fly Sprayer"
|
||||||
description_comment: "Control of generic automatic fly sprayer on a configurable interval"
|
description_comment: "Control of generic automatic fly sprayer on a configurable interval"
|
||||||
device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant.
|
device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant.
|
||||||
|
|
||||||
# Project Naming
|
# Project Naming
|
||||||
project_name: "Generic ESP8266.XY-WFUSB" # Project Details
|
project_name: "Generic ESP8266.XY-WFUSB" # Project Details
|
||||||
project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
|
project_version: "v1.0" # Project V denotes release of yaml file, allowing checking of deployed vs latest version
|
||||||
|
|
||||||
# Passwords & Secrets
|
# Passwords & Secrets
|
||||||
@@ -67,8 +67,8 @@ substitutions:
|
|||||||
night_start_h: 21 # 21:00 (9pm)
|
night_start_h: 21 # 21:00 (9pm)
|
||||||
night_end_h: 7 # 07:00 (7am)
|
night_end_h: 7 # 07:00 (7am)
|
||||||
|
|
||||||
# Interval jitter (± percent of selected interval)
|
# Interval jitter (+- percent of selected interval)
|
||||||
interval_jitter_pct: 10 # Default ±10%
|
interval_jitter_pct: 10 # Default +-10%
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# PACKAGES: Included Common Packages
|
# PACKAGES: Included Common Packages
|
||||||
@@ -95,7 +95,7 @@ packages:
|
|||||||
file: common/mqtt_common.yaml
|
file: common/mqtt_common.yaml
|
||||||
vars:
|
vars:
|
||||||
local_device_name: "${device_name}"
|
local_device_name: "${device_name}"
|
||||||
|
|
||||||
#### WEB PORTAL ####
|
#### WEB PORTAL ####
|
||||||
#common_webportal: !include common/webportal_common.yaml
|
#common_webportal: !include common/webportal_common.yaml
|
||||||
#### SNTP (Only use if you want/need accurate timeclocks) ####
|
#### SNTP (Only use if you want/need accurate timeclocks) ####
|
||||||
@@ -142,7 +142,6 @@ esphome:
|
|||||||
id(next_spray_in_text).publish_state("Ready");
|
id(next_spray_in_text).publish_state("Ready");
|
||||||
- script.execute: spray_loop
|
- script.execute: spray_loop
|
||||||
|
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# ESP PLATFORM AND FRAMEWORK
|
# ESP PLATFORM AND FRAMEWORK
|
||||||
# https://esphome.io/components/esp8266.html
|
# https://esphome.io/components/esp8266.html
|
||||||
@@ -162,7 +161,7 @@ preferences:
|
|||||||
##########################################################################################
|
##########################################################################################
|
||||||
globals:
|
globals:
|
||||||
# millisecond tick when we last fired successfully
|
# millisecond tick when we last fired successfully
|
||||||
- id: last_fire_ms
|
- id: last_fire_ms
|
||||||
type: uint32_t
|
type: uint32_t
|
||||||
restore_value: no
|
restore_value: no
|
||||||
initial_value: '0'
|
initial_value: '0'
|
||||||
@@ -178,34 +177,34 @@ globals:
|
|||||||
initial_value: 'false'
|
initial_value: 'false'
|
||||||
|
|
||||||
# absolute millis() when the next spray countdown ends
|
# absolute millis() when the next spray countdown ends
|
||||||
- id: next_target_ms
|
- id: next_target_ms
|
||||||
type: uint32_t
|
type: uint32_t
|
||||||
restore_value: no
|
restore_value: no
|
||||||
initial_value: '0'
|
initial_value: '0'
|
||||||
|
|
||||||
# total successful sprays (persists across reboots)
|
# total successful sprays (persists across reboots)
|
||||||
- id: spray_count
|
- id: spray_count
|
||||||
type: uint32_t
|
type: uint32_t
|
||||||
restore_value: yes
|
restore_value: yes
|
||||||
initial_value: '0'
|
initial_value: '0'
|
||||||
|
|
||||||
# total sprays since local midnight
|
# total sprays since local midnight
|
||||||
- id: spray_count_today
|
- id: spray_count_today
|
||||||
type: uint32_t
|
type: uint32_t
|
||||||
restore_value: yes
|
restore_value: yes
|
||||||
initial_value: '0'
|
initial_value: '0'
|
||||||
|
|
||||||
# day-of-month snapshot to detect midnight rollover
|
# day-of-month snapshot to detect midnight rollover
|
||||||
- id: last_day
|
- id: last_day
|
||||||
type: int
|
type: int
|
||||||
restore_value: yes
|
restore_value: yes
|
||||||
initial_value: '-1'
|
initial_value: '-1'
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# LOGGER COMPONENT
|
# LOGGER COMPONENT
|
||||||
# https://esphome.io/components/logger.html
|
# https://esphome.io/components/logger.html
|
||||||
# Logs all log messages through the serial port and through MQTT topics.
|
# Logs all log messages through the serial port and through MQTT topics.
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
logger:
|
logger:
|
||||||
level: "${log_level}" #INFO Level suggested, or DEBUG for testing
|
level: "${log_level}" #INFO Level suggested, or DEBUG for testing
|
||||||
#baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
|
#baud_rate: 0 #set to 0 for no logging via UART, needed if you are using it for other serial things (eg PZEM)
|
||||||
@@ -286,7 +285,7 @@ button:
|
|||||||
- lambda: |-
|
- lambda: |-
|
||||||
id(spray_count) = 0;
|
id(spray_count) = 0;
|
||||||
id(spray_count_sensor).publish_state(0);
|
id(spray_count_sensor).publish_state(0);
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# SELECT COMPONENT
|
# SELECT COMPONENT
|
||||||
# https://esphome.io/components/select/index.html
|
# https://esphome.io/components/select/index.html
|
||||||
@@ -310,8 +309,8 @@ select:
|
|||||||
on_value:
|
on_value:
|
||||||
then:
|
then:
|
||||||
- logger.log:
|
- logger.log:
|
||||||
format: "Spray Interval changed to %s — rescheduling"
|
format: "Spray Interval changed to %s - rescheduling"
|
||||||
args: [ 'id(spray_interval).state.c_str()' ]
|
args: [ 'id(spray_interval).current_option().c_str()' ]
|
||||||
- script.execute: spray_loop
|
- script.execute: spray_loop
|
||||||
|
|
||||||
- platform: template
|
- platform: template
|
||||||
@@ -330,8 +329,8 @@ select:
|
|||||||
on_value:
|
on_value:
|
||||||
then:
|
then:
|
||||||
- logger.log:
|
- logger.log:
|
||||||
format: "Operation changed to %s — rescheduling"
|
format: "Operation changed to %s - rescheduling"
|
||||||
args: [ 'id(spray_operation).state.c_str()' ]
|
args: [ 'id(spray_operation).current_option().c_str()' ]
|
||||||
- script.execute: spray_loop
|
- script.execute: spray_loop
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
@@ -339,7 +338,7 @@ select:
|
|||||||
# https://esphome.io/components/binary_sensor/
|
# https://esphome.io/components/binary_sensor/
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
# Front panel/local button (GPIO4) – single press triggers a Spray Now (honors cooldown)
|
# Front panel/local button (GPIO4) - single press triggers a Spray Now (honors cooldown)
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
id: btn_local
|
id: btn_local
|
||||||
pin:
|
pin:
|
||||||
@@ -441,20 +440,12 @@ light:
|
|||||||
# https://esphome.io/components/number/
|
# https://esphome.io/components/number/
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
|
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# SCRIPT COMPONENT
|
# SCRIPT COMPONENT
|
||||||
# https://esphome.io/components/script.html
|
# https://esphome.io/components/script.html
|
||||||
# Scripts can be executed nearly anywhere in your device configuration with a single call.
|
# Scripts can be executed nearly anywhere in your device configuration with a single call.
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# SCRIPTS – main loop, cooldown-safe trigger, and actual spray action
|
# SCRIPTS - main loop, cooldown-safe trigger, and actual spray action
|
||||||
##########################################################################################
|
|
||||||
##########################################################################################
|
|
||||||
# SCRIPT COMPONENT
|
|
||||||
# https://esphome.io/components/script.html
|
|
||||||
# Scripts can be executed nearly anywhere in your device configuration with a single call.
|
|
||||||
##########################################################################################
|
|
||||||
# SCRIPTS – main loop, cooldown-safe trigger, and actual spray action
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
script:
|
script:
|
||||||
# Cooldown-checked "Spray Now"
|
# Cooldown-checked "Spray Now"
|
||||||
@@ -495,7 +486,7 @@ script:
|
|||||||
brightness: 50%
|
brightness: 50%
|
||||||
effect: red_idle_pulse
|
effect: red_idle_pulse
|
||||||
|
|
||||||
# Scheduler loop – waits a randomized interval, updates countdown text, checks window, then tries to spray
|
# Scheduler loop - waits a randomized interval, updates countdown text, checks window, then tries to spray
|
||||||
- id: spray_loop
|
- id: spray_loop
|
||||||
mode: restart
|
mode: restart
|
||||||
then:
|
then:
|
||||||
@@ -505,7 +496,7 @@ script:
|
|||||||
then:
|
then:
|
||||||
# 1) Compute the base interval and randomized wait
|
# 1) Compute the base interval and randomized wait
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
auto s = id(spray_interval).state;
|
auto s = id(spray_interval).current_option();
|
||||||
uint32_t base_sec = 3600; // default 1 hour
|
uint32_t base_sec = 3600; // default 1 hour
|
||||||
if (s == "5 minutes") base_sec = 5 * 60;
|
if (s == "5 minutes") base_sec = 5 * 60;
|
||||||
else if (s == "10 minutes") base_sec = 10 * 60;
|
else if (s == "10 minutes") base_sec = 10 * 60;
|
||||||
@@ -515,13 +506,13 @@ script:
|
|||||||
else if (s == "2 hours") base_sec = 2 * 60 * 60;
|
else if (s == "2 hours") base_sec = 2 * 60 * 60;
|
||||||
else if (s == "4 hours") base_sec = 4 * 60 * 60;
|
else if (s == "4 hours") base_sec = 4 * 60 * 60;
|
||||||
|
|
||||||
// Jitter ±pct
|
// Jitter +-pct
|
||||||
const uint32_t pct = ${interval_jitter_pct};
|
const uint32_t pct = ${interval_jitter_pct};
|
||||||
const uint32_t jitter = (base_sec * pct) / 100;
|
const uint32_t jitter = (base_sec * pct) / 100;
|
||||||
const uint32_t span = (jitter * 2u) + 1u;
|
const uint32_t span = (jitter * 2u) + 1u;
|
||||||
const uint32_t rnd = random_uint32() % span; // 0..(2*jitter)
|
const uint32_t rnd = random_uint32() % span; // 0..(2*jitter)
|
||||||
const int32_t delta = (int32_t)rnd - (int32_t)jitter; // -jitter..+jitter
|
const int32_t delta = (int32_t) rnd - (int32_t) jitter; // -jitter..+jitter
|
||||||
int32_t next_sec = (int32_t)base_sec + delta;
|
int32_t next_sec = (int32_t) base_sec + delta;
|
||||||
if (next_sec < 1) next_sec = 1;
|
if (next_sec < 1) next_sec = 1;
|
||||||
|
|
||||||
ESP_LOGI("spray", "Next interval: base=%u s, jitter=%u%%, wait=%ld s",
|
ESP_LOGI("spray", "Next interval: base=%u s, jitter=%u%%, wait=%ld s",
|
||||||
@@ -536,11 +527,11 @@ script:
|
|||||||
id(next_spray_seconds).publish_state(sec);
|
id(next_spray_seconds).publish_state(sec);
|
||||||
uint32_t min = (sec + 59u) / 60u; // minutes, ceiling
|
uint32_t min = (sec + 59u) / 60u; // minutes, ceiling
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf), "%u min", (unsigned)min);
|
snprintf(buf, sizeof(buf), "%u min", (unsigned) min);
|
||||||
std::string countdown_txt(buf);
|
std::string countdown_txt(buf);
|
||||||
|
|
||||||
// Override text for specific modes
|
// Override text for specific modes
|
||||||
auto op = id(spray_operation).state;
|
auto op = id(spray_operation).current_option();
|
||||||
char await_buf[16];
|
char await_buf[16];
|
||||||
|
|
||||||
if (op == "Off") {
|
if (op == "Off") {
|
||||||
@@ -594,11 +585,11 @@ script:
|
|||||||
id(next_spray_seconds).publish_state(sec);
|
id(next_spray_seconds).publish_state(sec);
|
||||||
uint32_t min = (sec + 59u) / 60u; // minutes, ceiling
|
uint32_t min = (sec + 59u) / 60u; // minutes, ceiling
|
||||||
char buf[16];
|
char buf[16];
|
||||||
snprintf(buf, sizeof(buf), "%u min", (unsigned)min);
|
snprintf(buf, sizeof(buf), "%u min", (unsigned) min);
|
||||||
std::string countdown_txt(buf);
|
std::string countdown_txt(buf);
|
||||||
|
|
||||||
// Override text for specific modes
|
// Override text for specific modes
|
||||||
auto op = id(spray_operation).state;
|
auto op = id(spray_operation).current_option();
|
||||||
char await_buf[16];
|
char await_buf[16];
|
||||||
|
|
||||||
if (op == "Off") {
|
if (op == "Off") {
|
||||||
@@ -659,7 +650,7 @@ script:
|
|||||||
|
|
||||||
# 3) Check operation window; if allowed, attempt spray (cooldown enforced inside)
|
# 3) Check operation window; if allowed, attempt spray (cooldown enforced inside)
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
auto op = id(spray_operation).state;
|
auto op = id(spray_operation).current_option();
|
||||||
bool allowed = false;
|
bool allowed = false;
|
||||||
|
|
||||||
if (op == "Off") {
|
if (op == "Off") {
|
||||||
@@ -699,6 +690,3 @@ script:
|
|||||||
- script.execute: try_spray_now
|
- script.execute: try_spray_now
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -323,7 +323,12 @@ globals:
|
|||||||
- id: ev_energy_yesterday_kwh
|
- id: ev_energy_yesterday_kwh
|
||||||
type: float
|
type: float
|
||||||
restore_value: true
|
restore_value: true
|
||||||
initial_value: "0.0"
|
initial_value: "0.0"
|
||||||
|
# Track last day-of-year we snapped so it only happens once per day
|
||||||
|
- id: ev_last_snapshot_doy
|
||||||
|
type: int
|
||||||
|
restore_value: no
|
||||||
|
initial_value: '-1'
|
||||||
|
|
||||||
# Teleperiod = 60s: publish JSON and advance the window
|
# Teleperiod = 60s: publish JSON and advance the window
|
||||||
interval:
|
interval:
|
||||||
@@ -351,21 +356,25 @@ interval:
|
|||||||
snprintf(buf, sizeof(buf), "{\"EVChargerWhCount\":%.3f}", delta_wh);
|
snprintf(buf, sizeof(buf), "{\"EVChargerWhCount\":%.3f}", delta_wh);
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
|
|
||||||
##########################################################################################
|
# YESTERDAY ENERGY (device-side snapshot of today's total at end-of-day)
|
||||||
# YESTERDAY ENERGY (device-side snapshot of today's total at 23:59:59)
|
# Uses existing time id(sntp_time) from sntp_common.yaml
|
||||||
##########################################################################################
|
- interval: 60s
|
||||||
time:
|
then:
|
||||||
- platform: sntp
|
- lambda: |-
|
||||||
id: ev_time_for_ev_snap
|
auto now = id(sntp_time).now();
|
||||||
on_time:
|
if (!now.is_valid()) return;
|
||||||
- seconds: 59
|
|
||||||
minutes: 59
|
// Snapshot once per day at 23:59 (minute precision)
|
||||||
hours: 23
|
if (now.hour != 23 || now.minute != 59) return;
|
||||||
then:
|
|
||||||
- lambda: |-
|
// Prevent repeats if this runs multiple times during 23:59
|
||||||
// Snapshot today's kWh just before midnight reset
|
if (id(ev_last_snapshot_doy) == now.day_of_year) return;
|
||||||
if (isfinite(id(ev_energy_today_kwh).state)) {
|
|
||||||
id(ev_energy_yesterday_kwh) = id(ev_energy_today_kwh).state;
|
if (isfinite(id(ev_energy_today_kwh).state)) {
|
||||||
}
|
id(ev_energy_yesterday_kwh) = id(ev_energy_today_kwh).state;
|
||||||
|
}
|
||||||
|
|
||||||
|
id(ev_last_snapshot_doy) = now.day_of_year;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ substitutions:
|
|||||||
static_ip_address: !secret esp-garageentrylights_ip
|
static_ip_address: !secret esp-garageentrylights_ip
|
||||||
|
|
||||||
# Device Settings
|
# Device Settings
|
||||||
log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
|
log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
|
||||||
update_interval: "60s" # update time for for general sensors etc
|
update_interval: "60s" # update time for for general sensors etc
|
||||||
|
|
||||||
# Default relay restore mode
|
# Default relay restore mode
|
||||||
@@ -82,6 +82,15 @@ packages:
|
|||||||
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
||||||
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
||||||
|
|
||||||
|
# Package item removals
|
||||||
|
wifi:
|
||||||
|
min_auth_mode: !remove # The WPA2 only works on esp32/8266
|
||||||
|
reboot_timeout: 15min # override the selection from from the common package
|
||||||
|
fast_connect: false # (optional) force off, in case package vars change
|
||||||
|
|
||||||
|
mqtt:
|
||||||
|
keepalive: 15s # overriding the value from the common package
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
# ESPHome
|
# ESPHome
|
||||||
# https://esphome.io/components/esphome.html
|
# https://esphome.io/components/esphome.html
|
||||||
@@ -99,6 +108,9 @@ esphome:
|
|||||||
# then:
|
# then:
|
||||||
# - switch.turn_on: Relay_3
|
# - switch.turn_on: Relay_3
|
||||||
|
|
||||||
|
mdns:
|
||||||
|
disabled: true
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
# BUILD FOR BK CHIPSET
|
# BUILD FOR BK CHIPSET
|
||||||
# bk72xx
|
# bk72xx
|
||||||
|
|||||||
@@ -82,6 +82,15 @@ packages:
|
|||||||
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
||||||
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
||||||
|
|
||||||
|
# Package item removals
|
||||||
|
wifi:
|
||||||
|
min_auth_mode: !remove # The WPA2 only works on esp32/8266
|
||||||
|
reboot_timeout: 15min # override the selection from from the common package
|
||||||
|
fast_connect: false # (optional) force off, in case package vars change
|
||||||
|
|
||||||
|
mqtt:
|
||||||
|
keepalive: 15s # overriding the value from the common package
|
||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
# ESPHome
|
# ESPHome
|
||||||
# https://esphome.io/components/esphome.html
|
# https://esphome.io/components/esphome.html
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ switch:
|
|||||||
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
||||||
- platform: template
|
- platform: template
|
||||||
id: mosfet_ramp_switch
|
id: mosfet_ramp_switch
|
||||||
name: "${friendly_name} Fade Up/Down"
|
name: "${friendly_name} Fade Up-Down"
|
||||||
icon: mdi:led-strip-variant
|
icon: mdi:led-strip-variant
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return id(ramp_switch_target_on);
|
return id(ramp_switch_target_on);
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ switch:
|
|||||||
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
# Ramp-aware ON/OFF for HA (asymmetric, eased; no bounce)
|
||||||
- platform: template
|
- platform: template
|
||||||
id: mosfet_ramp_switch
|
id: mosfet_ramp_switch
|
||||||
name: "${friendly_name} Fade Up/Down"
|
name: "${friendly_name} Fade Up-Down"
|
||||||
icon: mdi:led-strip-variant
|
icon: mdi:led-strip-variant
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return id(ramp_switch_target_on);
|
return id(ramp_switch_target_on);
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_multi_click:
|
on_multi_click:
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,15 @@ packages:
|
|||||||
local_friendly_name: "${friendly_name}"
|
local_friendly_name: "${friendly_name}"
|
||||||
local_update_interval: "${update_interval}"
|
local_update_interval: "${update_interval}"
|
||||||
|
|
||||||
|
# Package item removals
|
||||||
|
wifi:
|
||||||
|
min_auth_mode: !remove # The WPA2 only works on esp32/8266
|
||||||
|
reboot_timeout: 15min # override the selection from from the common package
|
||||||
|
fast_connect: false # (optional) force off, in case package vars change
|
||||||
|
|
||||||
|
mqtt:
|
||||||
|
keepalive: 15s # overriding the value from the common package
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# ESPHome
|
# ESPHome
|
||||||
# https://esphome.io/components/esphome.html
|
# https://esphome.io/components/esphome.html
|
||||||
|
|||||||
@@ -385,7 +385,7 @@ logger:
|
|||||||
switch:
|
switch:
|
||||||
- platform: template
|
- platform: template
|
||||||
id: mosfet_ramp_switch_a
|
id: mosfet_ramp_switch_a
|
||||||
name: "${friendly_name} A Fade Up/Down"
|
name: "${friendly_name} A Fade Up-Down"
|
||||||
icon: mdi:led-strip-variant
|
icon: mdi:led-strip-variant
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return id(ramp_switch_target_on_A);
|
return id(ramp_switch_target_on_A);
|
||||||
@@ -402,7 +402,7 @@ switch:
|
|||||||
|
|
||||||
- platform: template
|
- platform: template
|
||||||
id: mosfet_ramp_switch_b
|
id: mosfet_ramp_switch_b
|
||||||
name: "${friendly_name} B Fade Up/Down"
|
name: "${friendly_name} B Fade Up-Down"
|
||||||
icon: mdi:led-strip-variant
|
icon: mdi:led-strip-variant
|
||||||
lambda: |-
|
lambda: |-
|
||||||
return id(ramp_switch_target_on_B);
|
return id(ramp_switch_target_on_B);
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # This pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ esphome:
|
|||||||
build_flags:
|
build_flags:
|
||||||
- "-Os" # optimize for size
|
- "-Os" # optimize for size
|
||||||
- "-Wl,--gc-sections" # drop unused code/data
|
- "-Wl,--gc-sections" # drop unused code/data
|
||||||
- "-fno-exceptions" # strip C++ exceptions
|
#- "-fno-exceptions" # strip C++ exceptions
|
||||||
- "-fno-rtti" # strip C++ RTTI
|
#- "-fno-rtti" # strip C++ RTTI
|
||||||
# on_boot:
|
# on_boot:
|
||||||
# priority: 200
|
# priority: 200
|
||||||
# then:
|
# then:
|
||||||
@@ -149,6 +149,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: false # GPO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: Extract Fan"
|
name: "Button 1: Extract Fan"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: "Relay_1"
|
- switch.toggle: "Relay_1"
|
||||||
|
|||||||
@@ -271,16 +271,6 @@ globals:
|
|||||||
restore_value: true
|
restore_value: true
|
||||||
initial_value: "2"
|
initial_value: "2"
|
||||||
|
|
||||||
####################################################
|
|
||||||
# current_mins is set if SNTP is invalid.
|
|
||||||
# We assume user powers on the device at 12:00 noon
|
|
||||||
# => 12 * 60 = 720 minutes from midnight.
|
|
||||||
####################################################
|
|
||||||
- id: current_mins
|
|
||||||
type: int
|
|
||||||
restore_value: false
|
|
||||||
initial_value: "720" # 720 is 12:00 Noon
|
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
# boost_timer: counts minutes in BOOST mode
|
# boost_timer: counts minutes in BOOST mode
|
||||||
# After 'boost_duration' minutes, revert to TIMER.
|
# After 'boost_duration' minutes, revert to TIMER.
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: False # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
@@ -135,6 +135,7 @@ binary_sensor:
|
|||||||
number: GPIO16
|
number: GPIO16
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
inverted: True
|
inverted: True
|
||||||
|
use_interrupt: False # GPIO16 pin doesn't support interrupts so use polling. Only supresses a warning.
|
||||||
name: "Button 1: ${switch_1_name}"
|
name: "Button 1: ${switch_1_name}"
|
||||||
on_press:
|
on_press:
|
||||||
- switch.toggle: Relay_1
|
- switch.toggle: Relay_1
|
||||||
|
|||||||
@@ -272,16 +272,6 @@ globals:
|
|||||||
restore_value: true
|
restore_value: true
|
||||||
initial_value: "2"
|
initial_value: "2"
|
||||||
|
|
||||||
####################################################
|
|
||||||
# current_mins is set if SNTP is invalid.
|
|
||||||
# We assume user powers on the device at 12:00 noon
|
|
||||||
# => 12 * 60 = 720 minutes from midnight.
|
|
||||||
####################################################
|
|
||||||
- id: current_mins
|
|
||||||
type: int
|
|
||||||
restore_value: true
|
|
||||||
initial_value: "720" # 720 is 12:00 Noon
|
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
# boost_timer: counts minutes in BOOST mode
|
# boost_timer: counts minutes in BOOST mode
|
||||||
# After 'boost_duration' minutes, revert to TIMER.
|
# After 'boost_duration' minutes, revert to TIMER.
|
||||||
|
|||||||
@@ -219,11 +219,21 @@ template:
|
|||||||
unique_id: ha_summary_addons
|
unique_id: ha_summary_addons
|
||||||
icon: mdi:puzzle
|
icon: mdi:puzzle
|
||||||
state: >-
|
state: >-
|
||||||
{% set a = states.update | selectattr('entity_id','in', integration_entities('hassio')) | list %}
|
{% set hassio_updates = (integration_entities('hassio') | list) %}
|
||||||
{% set b = states.update | selectattr('attributes.attribution','search','Supervisor') | list %}
|
{% set a = states.update
|
||||||
{{ (a + b) | unique | list
|
| selectattr('entity_id','in', hassio_updates)
|
||||||
| rejectattr('entity_id','search','^update\\.home_assistant_(core|supervisor|operating_system)_update$')
|
| map(attribute='entity_id')
|
||||||
| list | length }}
|
| list %}
|
||||||
|
{% set b = states.update
|
||||||
|
| selectattr('attributes.attribution','defined')
|
||||||
|
| selectattr('attributes.attribution','search','Supervisor')
|
||||||
|
| map(attribute='entity_id')
|
||||||
|
| list %}
|
||||||
|
{% set ids = (a + b)
|
||||||
|
| unique
|
||||||
|
| reject('search','^update\\.home_assistant_(core|supervisor|operating_system)_update$')
|
||||||
|
| list %}
|
||||||
|
{{ ids | length }}
|
||||||
|
|
||||||
# ---------- HACS updates available (proxy only) ----------
|
# ---------- HACS updates available (proxy only) ----------
|
||||||
- name: HA Summary - hacs updates
|
- name: HA Summary - hacs updates
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ template:
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{{ ns.e }}
|
{{ ns.e }}
|
||||||
names: >
|
names: >
|
||||||
@@ -75,6 +74,5 @@ template:
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{{ ns.n }}
|
{{ ns.n }}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
sensor:
|
sensor:
|
||||||
- platform: derivative
|
- platform: derivative
|
||||||
name: Main Bathroom Humidity Change Rate
|
name: Main Bathroom Humidity Change Rate
|
||||||
source: sensor.main_bathroom_environment_zth04_humidity
|
source: sensor.main_bathroom_environment_zth10_humidity_2
|
||||||
round: 1
|
round: 1
|
||||||
unit_time: s # the resulting "unit_of_measurement" will be %H/s if the sensor.temperate has set %H as its unit
|
unit_time: s # the resulting "unit_of_measurement" will be %H/s if the sensor.temperate has set %H as its unit
|
||||||
time_window: "00:00:10" # we look at the change over the last 10 seconds
|
time_window: "00:00:10" # we look at the change over the last 10 seconds
|
||||||
|
|||||||
Reference in New Issue
Block a user