additional esphome devices and fixes

This commit is contained in:
root
2026-05-23 23:53:04 +12:00
parent 5e941eea06
commit 7eb81efd93
61 changed files with 7756 additions and 354 deletions
+73 -40
View File
@@ -1,104 +1,129 @@
############################################################################################
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
# If NOT using a secrets file, just replace
# these with the values (in quotes)
###########################################################################################
#:########################################################################################:#
# TITLE: COMMON SNTP TIME SOURCE
# zorruno.com common ESPHome include
#:########################################################################################:#
# FILE:
# common/sntp_common.yaml
#:########################################################################################:#
# VERSIONS:
# V1.1 2026-05-23 Fixed offline fallback clock so it increments from assumed noon boot time
# V1.0 Initial common SNTP time source and diagnostic sensors
#:########################################################################################:#
# PURPOSE:
# - Provides an SNTP time source for ESPHome devices.
# - Stores the current time as minutes since midnight in current_mins.
# - Provides a simple fallback clock if SNTP is not available.
# - Publishes diagnostic text sensors for last restart, current/internal time, and sync status.
#:########################################################################################:#
# OPERATION NOTES:
# - SNTP time is stored in id(sntp_time).
# - Current minutes since midnight are stored in id(current_mins).
# - If SNTP is valid, current_mins follows the real SNTP time.
# - If SNTP is invalid, current_mins increments once per minute from the assumed boot time.
# - The fallback assumes the device was powered on at 12:00 noon.
# - If accurate offline time is needed, power-cycle the device at 12:00 noon.
#:########################################################################################:#
#:########################################################################################:#
# SUBSTITUTIONS: Specific SNTP variable substitutions
# If NOT using a secrets file, replace these values directly in quotes.
#:########################################################################################:#
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_update_interval: 6h
# 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
###########################################################################################
# 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: Internal clock fallback support
#:########################################################################################:#
globals:
- id: current_mins
type: int
restore_value: no
initial_value: "720" # 720 is 12:00 Noon
restore_value: false
initial_value: "720" # 720 minutes from midnight is 12:00 noon.
#:########################################################################################:#
# INTERVAL: Keep current_mins updated
#:########################################################################################:#
interval:
- interval: 60s
then:
- lambda: |-
// If SNTP valid, store minutes since midnight.
// If SNTP is valid, store real 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);
// Fallback: increment from the assumed startup time.
// Initial value is 720, so offline boot assumes 12:00 noon.
id(current_mins) = (id(current_mins) + 1) % 1440;
}
###########################################################################################
# Real time clock time source for ESPHome
# If it's invalid, we fall back to an internal clock
#:########################################################################################:#
# TIME: Real time clock source for ESPHome
# 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.
state: "SNTP clock synced"
# Update last restart time once only, after the first successful SNTP sync.
- if:
condition:
lambda: 'return id(device_last_restart).state == "";'
lambda: |-
return id(device_last_restart).state.empty();
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");'
state: !lambda |-
// grab the current SNTP time
auto now = id(sntp_time).now();
// format it as e.g. "Fri 23 May 2025 - 03:45:12 PM"
return now.strftime("%a %d %b %Y - %I:%M:%S %p");
#:########################################################################################:#
# TEXT SENSOR COMPONENT:
# https://esphome.io/components/text_sensor/
#:########################################################################################:#
text_sensor:
# Creates a sensor showing when the device was last restarted
# Shows when the device was last restarted, based on the first successful SNTP sync.
- platform: template
name: "Time: Last Restart"
id: device_last_restart
icon: mdi:clock
entity_category: diagnostic
#device_class: timestamp
update_interval: never
# Shows the current SNTP time if valid, otherwise the internal fallback time.
- platform: template
name: "Time: Internal Time"
id: time_text
update_interval: "1min"
icon: mdi:clock-outline
update_interval: 1min
entity_category: diagnostic
lambda: |-
// If SNTP time is valid, show real time/date.
if (id(sntp_time).now().is_valid()) {
auto t = id(sntp_time).now().strftime("%H:%M:%S - %d-%m-%Y");
return { t };
}
// Fallback: show internal clock based on current_mins (minutes from midnight).
int mins = id(current_mins);
if (mins < 0) mins = 0;
if (mins >= 1440) mins = mins % 1440;
@@ -110,8 +135,16 @@ text_sensor:
snprintf(buff, sizeof(buff), "%02d:%02d (fallback)", hour, minute);
return { std::string(buff) };
# Shows whether the device is using SNTP or the fallback clock.
- platform: template
name: "Time: Sync Status"
id: time_sync
update_interval: "1min"
icon: mdi:clock-check-outline
update_interval: 1min
entity_category: diagnostic
lambda: |-
if (id(sntp_time).now().is_valid()) {
return { std::string("SNTP clock synced") };
}
return { std::string("Using fallback internal clock") };