yaml layout updates to v1.x
This commit is contained in:
+159
-161
@@ -1,56 +1,84 @@
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
# FLY SPRAYER - Sinilink XY-WFUSB (ESP8266/ESP8285) - ESPHome
|
||||
#:########################################################################################:#
|
||||
# TITLE: FLY SPRAYER - SINILINK XY-WFUSB
|
||||
# zorruno.com layout v1.1 2026
|
||||
#:########################################################################################:#
|
||||
# REPO:
|
||||
# https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-flysprayer1.yaml
|
||||
#:########################################################################################:#
|
||||
# VERSIONS:
|
||||
# v1.1 2026-02-25 Updated yaml to zorruno layout V1.1
|
||||
# v1.0 2025-05-30 Initial Version
|
||||
#:########################################################################################:#
|
||||
# HARDWARE:
|
||||
# - Sinilink XY-WFUSB (ESP8266/ESP8285)
|
||||
# - Device link: https://www.aliexpress.com/item/1005005815472269.html
|
||||
# - GPIO (from Tasmota template):
|
||||
# - Button = GPIO4
|
||||
# - Relay = GPIO5
|
||||
# - Led_i = GPIO14 (Red LED, inverted)
|
||||
# - LedLink= GPIO16 (Green LED, status)
|
||||
#:########################################################################################:#
|
||||
# OPERATION NOTES:
|
||||
# - Purpose:
|
||||
# - Pulse a MOSFET/relay with 5 V to trigger a fly spray can at selectable intervals.
|
||||
# - The sprayer has its own timers, but it fires whenever it is started up; we utilize that.
|
||||
# - Safety / Reliability:
|
||||
# - Cooldown is enforced so it never double-fires too quickly (sprayer has some memory).
|
||||
# - Interval can be randomized by +- a percentage (jitter) to avoid a perfectly regular pattern.
|
||||
# - Scheduling:
|
||||
# - Operation modes: Night only / Day only / 24 Hours / On / Off.
|
||||
# - Night window spans across midnight (night_start_h -> night_end_h).
|
||||
# - Indicators:
|
||||
# - Red LED (GPIO14, inverted) pulses slowly when idle; goes solid ON during spray.
|
||||
# - Green LED (GPIO16) is used as the ESPHome status LED.
|
||||
# - Counters / UI:
|
||||
# - Total spray count (resettable).
|
||||
# - Daily spray count (resets at local midnight when time is valid).
|
||||
# - Countdown until next spray (seconds + friendly text).
|
||||
#:########################################################################################:#
|
||||
# OFFLINE NOTES:
|
||||
# a) Home Assistant OFFLINE, WiFi OK
|
||||
# - Device continues operating locally (spray loop, cooldown, LEDs, counters).
|
||||
# - You can still trigger "Spray Now" via the local button; HA UI will update when HA returns.
|
||||
#
|
||||
# V1.0 2025-05-30 Initial Version
|
||||
# b) MQTT OFFLINE (or broker unreachable)
|
||||
# - No device-specific MQTT commands are used in this YAML (MQTT section is commented out),
|
||||
# so behavior is unchanged.
|
||||
#
|
||||
# Device: Sinilink XY-WFUSB module https://www.aliexpress.com/item/1005005815472269.html
|
||||
# GPIO: Tasmota template: Button=GPIO4, Relay=GPIO5, Led_i=GPIO14, LedLink=GPIO16
|
||||
#
|
||||
# Purpose:
|
||||
# - Pulse a MOSFET/relay with 5 V to trigger a fly spray can at selectable intervals.
|
||||
# - 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)
|
||||
# - Operation window select: Night only / Day only / 24 Hours / On / Off.
|
||||
# - 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.
|
||||
# - Green LED (GPIO16) as standard ESPHome status LED.
|
||||
# - Has a resettable total spray count, and a daily spray count
|
||||
# - has a countdown until next spray
|
||||
#
|
||||
##########################################################################################
|
||||
##########################################################################################
|
||||
# c) Entire WiFi/Network OFFLINE
|
||||
# - Accurate time IS needed for Night/Day modes and daily counter reset (SNTP required).
|
||||
# - If time is invalid, this YAML is conservative for Night/Day modes (skips those cycles).
|
||||
# 24 Hours / On still allows operation, but daily reset will not occur until time is valid.
|
||||
#:########################################################################################:#
|
||||
|
||||
##########################################################################################
|
||||
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
|
||||
|
||||
#:########################################################################################:#
|
||||
# SUBSTITUTIONS: Specific device variable substitutions
|
||||
# If NOT using a secrets file, just replace these with the passwords etc (in quotes)
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
substitutions:
|
||||
# Device Naming
|
||||
device_name: "esp-flysprayer1"
|
||||
friendly_name: "Fly Sprayer"
|
||||
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.
|
||||
description_comment: "Control of generic automatic fly sprayer on a configurable interval (Layout V1.1)"
|
||||
device_area: "Lounge"
|
||||
|
||||
# Project Naming
|
||||
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_name: "Generic ESP8266.XY-WFUSB"
|
||||
project_version: "v1.1"
|
||||
|
||||
# Passwords & Secrets
|
||||
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
|
||||
ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names
|
||||
api_key: !secret esp-api_key
|
||||
ota_pass: !secret esp-ota_pass
|
||||
static_ip_address: !secret esp-flysprayer1_ip
|
||||
#mqtt_local_command_main_topic: !secret mqtt_local_command_main_topic
|
||||
#mqtt_local_status_main_topic: !secret mqtt_local_status_main_topic
|
||||
|
||||
# If we are changing IP addresses, you must update the current IP address here, otherwise it remains
|
||||
# Don't forget to switch it back when changed.
|
||||
current_ip_address: ${static_ip_address}
|
||||
|
||||
# Device Settings
|
||||
log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
|
||||
update_interval: "60s" # update time for for general sensors etc
|
||||
|
||||
# MQTT Controls
|
||||
#mqtt_device_name: "lounge-flyspray"
|
||||
#mqtt_local_command_topic: "${mqtt_local_command_main_topic}/${mqtt_device_name}" # Topic we will use to command this locally without HA
|
||||
#mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # Topic we will use to view status locally without HA
|
||||
log_level: "INFO"
|
||||
update_interval: "60s"
|
||||
|
||||
# Hardware pins (XY-WFUSB per your Tasmota screen)
|
||||
pin_button: 4 # GPIO4 -> momentary button (optional local trigger)
|
||||
@@ -61,19 +89,19 @@ substitutions:
|
||||
|
||||
# Timing configuration
|
||||
relay_activation_ms: 5000 # Relay Activation Time (ms). Nominally 5 seconds.
|
||||
relay_cooldown_ms: 30000 # Relay Cool Down Period (ms). Minimum gap between sprays.
|
||||
relay_cooldown_ms: 30000 # Relay Cool Down Period (ms). Minimum gap between sprays.
|
||||
|
||||
# Operation windows (local 24h). Night is from night_start_h to night_end_h across midnight.
|
||||
night_start_h: 21 # 21:00 (9pm)
|
||||
night_end_h: 7 # 07:00 (7am)
|
||||
night_start_h: 21 # 21:00 (9pm)
|
||||
night_end_h: 7 # 07:00 (7am)
|
||||
|
||||
# Interval jitter (+- percent of selected interval)
|
||||
interval_jitter_pct: 10 # Default +-10%
|
||||
interval_jitter_pct: 10 # Default +-10%
|
||||
|
||||
#########################################################################################
|
||||
#:########################################################################################:#
|
||||
# PACKAGES: Included Common Packages
|
||||
# https://esphome.io/components/packages.html
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
packages:
|
||||
#### WIFI, Network (Static/DHCP/IPV6 etc), Fallback AP, Safemode ####
|
||||
common_wifi: !include
|
||||
@@ -82,6 +110,7 @@ packages:
|
||||
local_device_name: "${device_name}"
|
||||
local_static_ip_address: "${static_ip_address}"
|
||||
local_ota_pass: "${ota_pass}"
|
||||
local_current_ip_address: "${current_ip_address}"
|
||||
|
||||
#### HOME ASSISTANT API (choose encryption or no encryption options) ####
|
||||
common_api: !include
|
||||
@@ -96,21 +125,19 @@ packages:
|
||||
vars:
|
||||
local_device_name: "${device_name}"
|
||||
|
||||
#### WEB PORTAL ####
|
||||
#common_webportal: !include common/webportal_common.yaml
|
||||
#### SNTP (Only use if you want/need accurate timeclocks) ####
|
||||
common_sntp: !include common/sntp_common.yaml
|
||||
common_sntp: !include common/sntp_common.yaml
|
||||
|
||||
#### DIAGNOSTICS Sensors ####
|
||||
diag_basic: !include common/include_basic_diag_sensors.yaml
|
||||
diag_more: !include common/include_more_diag_sensors.yaml
|
||||
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
||||
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
||||
diag_basic: !include common/include_basic_diag_sensors.yaml
|
||||
diag_more: !include common/include_more_diag_sensors.yaml
|
||||
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
||||
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
||||
|
||||
##########################################################################################
|
||||
# ESPHome CORE CONFIGURATION
|
||||
#:########################################################################################:#
|
||||
# ESPHOME
|
||||
# https://esphome.io/components/esphome.html
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
esphome:
|
||||
name: "${device_name}"
|
||||
friendly_name: "${friendly_name}"
|
||||
@@ -142,105 +169,91 @@ esphome:
|
||||
id(next_spray_in_text).publish_state("Ready");
|
||||
- script.execute: spray_loop
|
||||
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# ESP PLATFORM AND FRAMEWORK
|
||||
# https://esphome.io/components/esp8266.html
|
||||
# https://esphome.io/components/esp32.html
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
esp8266:
|
||||
board: esp8285
|
||||
early_pin_init: false # Initialise pins early to known values. Recommended false where switches are involved. Defaults to True.
|
||||
board_flash_mode: dout # Default is dout
|
||||
early_pin_init: false
|
||||
board_flash_mode: dout
|
||||
|
||||
preferences:
|
||||
flash_write_interval: 20s
|
||||
|
||||
##########################################################################################
|
||||
# GLOBAL VARIABLES
|
||||
#:########################################################################################:#
|
||||
# GLOBALS
|
||||
# https://esphome.io/components/globals.html
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
globals:
|
||||
# millisecond tick when we last fired successfully
|
||||
# millisecond tick when we last fired successfully
|
||||
- id: last_fire_ms
|
||||
type: uint32_t
|
||||
restore_value: no
|
||||
initial_value: '0'
|
||||
initial_value: "0"
|
||||
|
||||
- id: last_wait_ms
|
||||
type: uint32_t
|
||||
restore_value: no
|
||||
initial_value: '60000'
|
||||
initial_value: "60000"
|
||||
|
||||
- id: window_allowed
|
||||
type: bool
|
||||
restore_value: no
|
||||
initial_value: 'false'
|
||||
initial_value: "false"
|
||||
|
||||
# absolute millis() when the next spray countdown ends
|
||||
- id: next_target_ms
|
||||
type: uint32_t
|
||||
restore_value: no
|
||||
initial_value: '0'
|
||||
initial_value: "0"
|
||||
|
||||
# total successful sprays (persists across reboots)
|
||||
- id: spray_count
|
||||
type: uint32_t
|
||||
restore_value: yes
|
||||
initial_value: '0'
|
||||
initial_value: "0"
|
||||
|
||||
# total sprays since local midnight
|
||||
- id: spray_count_today
|
||||
type: uint32_t
|
||||
restore_value: yes
|
||||
initial_value: '0'
|
||||
initial_value: "0"
|
||||
|
||||
# day-of-month snapshot to detect midnight rollover
|
||||
- id: last_day
|
||||
type: int
|
||||
restore_value: yes
|
||||
initial_value: '-1'
|
||||
initial_value: "-1"
|
||||
|
||||
##########################################################################################
|
||||
# LOGGER COMPONENT
|
||||
#:########################################################################################:#
|
||||
# LOGGER
|
||||
# https://esphome.io/components/logger.html
|
||||
# Logs all log messages through the serial port and through MQTT topics.
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
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
|
||||
level: "${log_level}"
|
||||
#baud_rate: 0
|
||||
|
||||
##########################################################################################
|
||||
# MQTT COMMANDS
|
||||
# This adds device-specific MQTT command triggers to the common MQTT configuration.
|
||||
##########################################################################################
|
||||
#mqtt:
|
||||
# on_message:
|
||||
# # Light control to ramp up
|
||||
# - topic: "${mqtt_local_command_topic}/light/set"
|
||||
# payload: "${mqtt_local_device_command_ON}"
|
||||
# then:
|
||||
# - switch.turn_on: mosfet_ramp_switch
|
||||
# # Light control to ramp down
|
||||
# - topic: "${mqtt_local_command_topic}/light/set"
|
||||
# payload: "${mqtt_local_device_command_OFF}"
|
||||
# then:
|
||||
# - switch.turn_off: mosfet_ramp_switch
|
||||
|
||||
#########################################################################################
|
||||
#:########################################################################################:#
|
||||
# STATUS LED
|
||||
# https://esphome.io/components/status_led.html
|
||||
#########################################################################################
|
||||
#:########################################################################################:#
|
||||
status_led:
|
||||
pin:
|
||||
number: ${pin_led_green}
|
||||
inverted: false
|
||||
|
||||
##########################################################################################
|
||||
# SWITCH COMPONENT
|
||||
#:########################################################################################:#
|
||||
# MQTT COMMANDS
|
||||
# (No device-specific MQTT triggers are enabled in this file currently)
|
||||
#:########################################################################################:#
|
||||
#mqtt:
|
||||
# on_message:
|
||||
|
||||
#:########################################################################################:#
|
||||
# SWITCH
|
||||
# https://esphome.io/components/switch/
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
switch:
|
||||
- platform: gpio
|
||||
id: relay_out
|
||||
@@ -264,10 +277,10 @@ switch:
|
||||
brightness: 50%
|
||||
effect: red_idle_pulse
|
||||
|
||||
#################################################################################################
|
||||
# BUTTON COMPONENT
|
||||
#:########################################################################################:#
|
||||
# BUTTON
|
||||
# https://esphome.io/components/button/index.html
|
||||
#################################################################################################
|
||||
#:########################################################################################:#
|
||||
button:
|
||||
- platform: template
|
||||
id: spray_now
|
||||
@@ -276,6 +289,7 @@ button:
|
||||
on_press:
|
||||
then:
|
||||
- script.execute: try_spray_now
|
||||
|
||||
- platform: template
|
||||
id: reset_spray_count
|
||||
name: "Reset Spray Count"
|
||||
@@ -286,10 +300,10 @@ button:
|
||||
id(spray_count) = 0;
|
||||
id(spray_count_sensor).publish_state(0);
|
||||
|
||||
#########################################################################################
|
||||
# SELECT COMPONENT
|
||||
#:########################################################################################:#
|
||||
# SELECT
|
||||
# https://esphome.io/components/select/index.html
|
||||
#########################################################################################
|
||||
#:########################################################################################:#
|
||||
select:
|
||||
- platform: template
|
||||
id: spray_interval
|
||||
@@ -333,12 +347,12 @@ select:
|
||||
args: [ 'id(spray_operation).current_option().c_str()' ]
|
||||
- script.execute: spray_loop
|
||||
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# BINARY SENSORS
|
||||
# https://esphome.io/components/binary_sensor/
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
binary_sensor:
|
||||
# Front panel/local button (GPIO4) - single press triggers a Spray Now (honors cooldown)
|
||||
# Front panel/local button (GPIO4) - triggers Spray Now (honors cooldown)
|
||||
- platform: gpio
|
||||
id: btn_local
|
||||
pin:
|
||||
@@ -352,10 +366,10 @@ binary_sensor:
|
||||
then:
|
||||
- button.press: spray_now
|
||||
|
||||
##########################################################################################
|
||||
# SENSOR COMPONENT
|
||||
#:########################################################################################:#
|
||||
# SENSORS
|
||||
# https://esphome.io/components/sensor/
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
sensor:
|
||||
# Next spray remaining time in seconds (updated by the scheduler)
|
||||
- platform: template
|
||||
@@ -364,7 +378,6 @@ sensor:
|
||||
icon: mdi:timer-sand
|
||||
unit_of_measurement: "s"
|
||||
accuracy_decimals: 0
|
||||
#entity_category: diagnostic
|
||||
update_interval: never
|
||||
|
||||
# Total sprays counter (persisted; updated on each spray and when reset)
|
||||
@@ -379,7 +392,7 @@ sensor:
|
||||
filters:
|
||||
- round: 0
|
||||
|
||||
# Sprays since local midnight (auto-resets at midnight)
|
||||
# Sprays since local midnight (auto-resets at midnight when time is valid)
|
||||
- platform: template
|
||||
id: spray_count_today_sensor
|
||||
name: "${friendly_name} Spray Count Today"
|
||||
@@ -391,36 +404,32 @@ sensor:
|
||||
filters:
|
||||
- round: 0
|
||||
|
||||
##########################################################################################
|
||||
# TEXT SENSOR COMPONENT
|
||||
#:########################################################################################:#
|
||||
# TEXT SENSORS
|
||||
# https://esphome.io/components/text_sensor/
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
text_sensor:
|
||||
- platform: template
|
||||
id: next_spray_in_text
|
||||
name: "Next Spray In"
|
||||
icon: mdi:clock-outline
|
||||
#entity_category: diagnostic
|
||||
update_interval: never
|
||||
|
||||
##########################################################################################
|
||||
# OUTPUT COMPONENT
|
||||
# https://esphome.io/components/light/index.html
|
||||
##########################################################################################
|
||||
# An OUTPUT can be binary (0,1) or float, which is any value between 0 and 1.
|
||||
# PWM Outputs such as "ledc" are float. https://esphome.io/components/output/ledc.html
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
# OUTPUT
|
||||
# https://esphome.io/components/output/
|
||||
#:########################################################################################:#
|
||||
output:
|
||||
- platform: esp8266_pwm
|
||||
id: red_led_pwm
|
||||
pin:
|
||||
number: ${pin_led_red}
|
||||
inverted: true # Tasmota showed Led_i on GPIO14
|
||||
inverted: true
|
||||
|
||||
##########################################################################################
|
||||
# LIGHT COMPONENT
|
||||
#:########################################################################################:#
|
||||
# LIGHT
|
||||
# https://esphome.io/components/light/
|
||||
##########################################################################################
|
||||
#:########################################################################################:#
|
||||
light:
|
||||
- platform: monochromatic
|
||||
id: red_led
|
||||
@@ -435,18 +444,10 @@ light:
|
||||
transition_length: 1500ms
|
||||
update_interval: 1500ms
|
||||
|
||||
##########################################################################################
|
||||
# NUMBER COMPONENT
|
||||
# https://esphome.io/components/number/
|
||||
##########################################################################################
|
||||
|
||||
##########################################################################################
|
||||
# SCRIPT COMPONENT
|
||||
#:########################################################################################:#
|
||||
# SCRIPTS
|
||||
# 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:
|
||||
# Cooldown-checked "Spray Now"
|
||||
- id: try_spray_now
|
||||
@@ -463,7 +464,7 @@ script:
|
||||
id(last_fire_ms) = millis();
|
||||
- script.execute: do_spray
|
||||
else:
|
||||
- logger.log: "Spray request ignored: Fired during cool down period."
|
||||
- logger.log: "Spray request ignored: fired during cool down period."
|
||||
|
||||
# Actual relay action for the configured activation time
|
||||
- id: do_spray
|
||||
@@ -473,7 +474,7 @@ script:
|
||||
id(spray_count)++;
|
||||
id(spray_count_sensor).publish_state((float) id(spray_count));
|
||||
id(spray_count_today)++;
|
||||
id(spray_count_today_sensor).publish_state(id(spray_count_today)); // publish as int
|
||||
id(spray_count_today_sensor).publish_state(id(spray_count_today));
|
||||
- switch.turn_on: relay_out
|
||||
- light.turn_on:
|
||||
id: red_led
|
||||
@@ -486,7 +487,7 @@ script:
|
||||
brightness: 50%
|
||||
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, checks window, then tries to spray
|
||||
- id: spray_loop
|
||||
mode: restart
|
||||
then:
|
||||
@@ -510,8 +511,9 @@ script:
|
||||
const uint32_t pct = ${interval_jitter_pct};
|
||||
const uint32_t jitter = (base_sec * pct) / 100;
|
||||
const uint32_t span = (jitter * 2u) + 1u;
|
||||
const uint32_t rnd = random_uint32() % span; // 0..(2*jitter)
|
||||
const int32_t delta = (int32_t) rnd - (int32_t) jitter; // -jitter..+jitter
|
||||
const uint32_t rnd = random_uint32() % span; // 0..(2*jitter)
|
||||
const int32_t delta = (int32_t) rnd - (int32_t) jitter; // -jitter..+jitter
|
||||
|
||||
int32_t next_sec = (int32_t) base_sec + delta;
|
||||
if (next_sec < 1) next_sec = 1;
|
||||
|
||||
@@ -521,11 +523,11 @@ script:
|
||||
id(last_wait_ms) = (uint32_t) next_sec * 1000u;
|
||||
id(next_target_ms) = millis() + id(last_wait_ms);
|
||||
|
||||
// Publish an initial countdown snapshot (minutes only for text; seconds kept for numeric sensor)
|
||||
// Publish an initial countdown snapshot
|
||||
uint32_t rem_ms = id(next_target_ms) > millis() ? (id(next_target_ms) - millis()) : 0;
|
||||
uint32_t sec = (rem_ms + 999u) / 1000u; // seconds, rounded up
|
||||
uint32_t sec = (rem_ms + 999u) / 1000u; // seconds, rounded up
|
||||
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];
|
||||
snprintf(buf, sizeof(buf), "%u min", (unsigned) min);
|
||||
std::string countdown_txt(buf);
|
||||
@@ -562,7 +564,7 @@ script:
|
||||
bool is_night;
|
||||
if (nh > eh) is_night = (hour >= nh) || (hour < eh);
|
||||
else is_night = (hour >= nh) && (hour < eh);
|
||||
in_window = !is_night; // day is the opposite of night window
|
||||
in_window = !is_night;
|
||||
}
|
||||
if (!in_window) {
|
||||
snprintf(await_buf, sizeof(await_buf), "%02d:00", ${night_end_h});
|
||||
@@ -581,14 +583,14 @@ script:
|
||||
then:
|
||||
- lambda: |-
|
||||
uint32_t rem_ms = id(next_target_ms) > millis() ? (id(next_target_ms) - millis()) : 0;
|
||||
uint32_t sec = (rem_ms + 999u) / 1000u; // seconds, rounded up
|
||||
uint32_t sec = (rem_ms + 999u) / 1000u;
|
||||
id(next_spray_seconds).publish_state(sec);
|
||||
uint32_t min = (sec + 59u) / 60u; // minutes, ceiling
|
||||
|
||||
uint32_t min = (sec + 59u) / 60u;
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%u min", (unsigned) min);
|
||||
std::string countdown_txt(buf);
|
||||
|
||||
// Override text for specific modes
|
||||
auto op = id(spray_operation).current_option();
|
||||
char await_buf[16];
|
||||
|
||||
@@ -637,10 +639,8 @@ script:
|
||||
auto n = id(sntp_time).now();
|
||||
int d = n.day_of_month;
|
||||
if (id(last_day) == -1) {
|
||||
// First valid time after boot: initialise without reset
|
||||
id(last_day) = d;
|
||||
id(last_day) = d; // first valid time after boot
|
||||
} else if (id(last_day) != d) {
|
||||
// New day -> reset today's counter
|
||||
id(last_day) = d;
|
||||
id(spray_count_today) = 0;
|
||||
id(spray_count_today_sensor).publish_state(0);
|
||||
@@ -659,16 +659,15 @@ script:
|
||||
allowed = true;
|
||||
} else {
|
||||
if (!id(sntp_time).now().is_valid()) {
|
||||
allowed = false; // no time yet; be conservative
|
||||
allowed = false; // no time yet; be conservative
|
||||
} else {
|
||||
auto n = id(sntp_time).now();
|
||||
int hour = n.hour; // 0..23
|
||||
int hour = n.hour;
|
||||
int nh = ${night_start_h};
|
||||
int eh = ${night_end_h};
|
||||
|
||||
bool is_night;
|
||||
if (nh > eh) {
|
||||
// window crosses midnight (e.g., 21:00..07:00)
|
||||
is_night = (hour >= nh) || (hour < eh);
|
||||
} else {
|
||||
is_night = (hour >= nh) && (hour < eh);
|
||||
@@ -683,10 +682,9 @@ script:
|
||||
else ESP_LOGI("spray", "Window blocked: skipping this cycle.");
|
||||
|
||||
id(window_allowed) = allowed;
|
||||
|
||||
- if:
|
||||
condition:
|
||||
lambda: "return id(window_allowed);"
|
||||
then:
|
||||
- script.execute: try_spray_now
|
||||
|
||||
|
||||
- script.execute: try_spray_now
|
||||
Reference in New Issue
Block a user