ESPHome Config File
This is the ESPHome based config file for my custom sprinkler controller. It is built around a modified implementation of the esphome sprinkler controller component.
I wanted more flexibility to select the days of the week to run certain zones so the code below is designed to primarily work with the sprinkler controller queue function.
While I have heavily integrated this device into my Home Assistant (HA) instance, it can also run independently from HA. Zone start & stop times are all executed directly from the device.
substitutions: # set up unique values for this hardware instance
name_of_device: nachio
id_prefix: nachio
name_prefix: Nachio
api_key: kHC70+TJJ4ZeYkstfj/KBYVLFUczMrb0PdacV9Khq1M=
#ota_password: "paste_OTA_password_here"
ap_password: 5050badass08
sensor_update_frequency: 1s
uom: Min # this overrides the uom in sprinkler -> run_duration
esphome:
name: $name_of_device
friendly_name: ${name_prefix}
min_version: 2024.11.0
name_add_mac_suffix: false
on_boot:
priority: -100
then:
# # Set default state for Valve Status
# - text_sensor.template.publish:
# id: valve_status
# state: "Idle"
# Set multiplier to 60, convert seconds to minutes
- sprinkler.set_multiplier:
id: ${name_of_device}_sprinklers
multiplier: 60
esp32:
board: esp32dev
framework:
type: esp-idf
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: $api_key
reboot_timeout: 1min
services:
- service: start_valve
then:
- script.execute: start_valve_dynamic
# Allow Over-The-Air updates
ota:
- platform: esphome
wifi:
ssid: Aether
password: $ap_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Nachio Fallback Hotspot"
password: $ap_password
captive_portal:
# Status LED
light:
- platform: status_led
name: "Nachio LED"
restore_mode: ALWAYS_OFF
pin:
number: GPIO23
globals:
- id: zone_index
type: int
restore_value: no
initial_value: '0'
- id: zone_duration
type: float
restore_value: no
initial_value: '0'
- id: sprinkler_queue_time_remaining
type: int # seconds
initial_value: '0'
#These are all used to determine the queue size
- id: sprinkler_queue_size
type: int
initial_value: '0'
- id: valve_1_active
type: bool
initial_value: 'false'
- id: valve_2_active
type: bool
initial_value: 'false'
- id: valve_3_active
type: bool
initial_value: 'false'
- id: valve_4_active
type: bool
initial_value: 'false'
- id: valve_5_active
type: bool
initial_value: 'false'
- id: valve_6_active
type: bool
initial_value: 'false'
- id: valve_7_active
type: bool
initial_value: 'false'
- id: valve_8_active
type: bool
initial_value: 'false'
number:
- platform: template
id: var_run_duration_minutes
name: "Var Run Duration Minutes"
min_value: 1
max_value: 20
step: 1
unit_of_measurement: "min"
mode: box
optimistic: true
- platform: template
name: "Sprinkler Valve Number"
id: valve_number_input
min_value: 0
max_value: 7 # Adjust to match your number of valves minus 1
step: 1
mode: box
optimistic: true
sprinkler:
- id: ${id_prefix}_sprinklers
main_switch: "Sprinkler Cycle Active"
auto_advance_switch: "Auto Advance"
queue_enable_switch: "Enable Queue"
standby_switch: "System Standby" #To be used for rain skips
valve_overlap: 3s
valves:
- valve_switch: "Zone 1 Active"
#enable_switch: "Enable z1"
run_duration_number:
id: zone_1_run_duration
name: "Zone 1 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve01
- valve_switch: "Zone 2 Active"
#enable_switch: "Enable z2"
run_duration_number:
id: zone_2_run_duration
name: "Zone 2 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve02
- valve_switch: "Zone 3 Active"
#enable_switch: "Enable z3"
run_duration_number:
id: zone_3_run_duration
name: "Zone 3 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve03
- valve_switch: "Zone 4 Active"
#enable_switch: "Enable z4"
run_duration_number:
id: zone_4_run_duration
name: "Zone 4 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve04
- valve_switch: "Zone 5 Active"
#enable_switch: "Enable z5"
run_duration_number:
id: zone_5_run_duration
name: "Zone 5 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve05
- valve_switch: "Zone 6 Active"
#enable_switch: "Enable z6"
run_duration_number:
id: zone_6_run_duration
name: "Zone 6 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve06
- valve_switch: "Zone 7 Active"
#enable_switch: "Enable z7"
run_duration_number:
id: zone_7_run_duration
name: "Zone 7 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve07
- valve_switch: "Zone 8 Active"
#enable_switch: "Enable z8"
run_duration_number:
id: zone_8_run_duration
name: "Zone 8 Run Duration"
icon: "mdi:timer-outline"
initial_value: 1
unit_of_measurement: min
valve_switch_id: ${id_prefix}_valve08
button:
- platform: template
name: "Pause Sprinkler"
on_press:
- sprinkler.pause: ${id_prefix}_sprinklers
- platform: template
name: "Resume Sprinkler"
on_press:
- sprinkler.resume: ${id_prefix}_sprinklers
#########################################################
# BEGIN SWITCHES
#########################################################
# 8 relay outputs
#internal: true causes these switches to not show in HA
switch:
- platform: gpio
pin: GPIO32
name: ${id_prefix}_valve01
id: ${id_prefix}_valve01
on_turn_on:
then:
- lambda: |-
id(valve_1_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_1_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_1_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_1_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: gpio
pin: GPIO33
name: ${id_prefix}_valve02
id: ${id_prefix}_valve02
on_turn_on:
then:
- lambda: |-
id(valve_2_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_2_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_2_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_2_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: gpio
pin: GPIO25
name: ${id_prefix}_valve03
id: ${id_prefix}_valve03
on_turn_on:
then:
- lambda: |-
id(valve_3_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_3_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_3_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_3_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: gpio
pin: GPIO26
name: ${id_prefix}_valve04
id: ${id_prefix}_valve04
on_turn_on:
then:
- lambda: |-
id(valve_4_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_4_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_4_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_4_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: gpio
pin: GPIO27
name: ${id_prefix}_valve05
id: ${id_prefix}_valve05
on_turn_on:
then:
- lambda: |-
id(valve_5_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_5_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_5_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_5_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: gpio
pin: GPIO14
name: ${id_prefix}_valve06
id: ${id_prefix}_valve06
on_turn_on:
then:
- lambda: |-
id(valve_6_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_6_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_6_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_6_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: gpio
pin: GPIO12
name: ${id_prefix}_valve07
id: ${id_prefix}_valve07
on_turn_on:
then:
- lambda: |-
id(valve_7_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_7_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_7_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_7_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: gpio
pin: GPIO13
name: ${id_prefix}_valve08
id: ${id_prefix}_valve08
on_turn_on:
then:
- lambda: |-
id(valve_8_active) = true;
on_turn_off:
then:
- lambda: |-
if (id(valve_8_active)) {
id(sprinkler_queue_size) -= 1;
float runtime_min = id(zone_8_run_duration).state;
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) -= runtime_sec;
if (id(sprinkler_queue_time_remaining) < 0)
id(sprinkler_queue_time_remaining) = 0;
id(valve_8_active) = false;
}
restore_mode: ALWAYS_OFF
internal: true
- platform: shutdown
name: "Nachio Shutdown"
entity_category: config
#RAIN SKIP Switch
- platform: template
name: "Rain Skip Lock"
id: ${id_prefix}_rain_skip_lock
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
#########################################################
# Begin day of week switches per zone
#########################################################
# Per-zone day-of-week switches
# Zone 1 - Front Lawn
- platform: template
id: ${id_prefix}_z1_0_sun
name: z1_0 run sun
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z1_1_mon
name: z1_1 run mon
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z1_2_tue
name: z1_2 run tue
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z1_3_wed
name: z1_3 run wed
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z1_4_thu
name: z1_4 run thu
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z1_5_fri
name: z1_5 run fri
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z1_6_sat
name: z1_6 run sat
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z1_adjust_duration
name: z1 - Adjust Duration
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
# Zone 2 - Front Patio
- platform: template
id: ${id_prefix}_z2_0_sun
name: z2_0 run sun
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_1_mon
name: z2_1 run mon
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_2_tue
name: z2_2 run tue
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_3_wed
name: z2_3 run wed
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_4_thu
name: z2_4 run thu
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_5_fri
name: z2_5 run fri
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_6_sat
name: z2_6 run sat
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_adjust_duration
name: z2 - Adjust Duration
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
# Zone 3 - Back Lawn1
- platform: template
id: ${id_prefix}_z3_0_sun
name: z3_0 run sun
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_1_mon
name: z3_1 run mon
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_2_tue
name: z3_2 run tue
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_3_wed
name: z3_3 run wed
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_4_thu
name: z3_4 run thu
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_5_fri
name: z3_5 run fri
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_6_sat
name: z3_6 run sat
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_adjust_duration
name: z3 - Adjust Duration
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
# Zone 4 - Back Lawn2
- platform: template
id: ${id_prefix}_z4_0_sun
name: z4_0 run sun
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_1_mon
name: z4_1 run mon
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_2_tue
name: z4_2 run tue
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_3_wed
name: z4_3 run wed
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_4_thu
name: z4_4 run thu
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_5_fri
name: z4_5 run fri
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_6_sat
name: z4_6 run sat
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_adjust_duration
name: z4 - Adjust Duration
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
# Zone 5 - Roses & side Yard
- platform: template
id: ${id_prefix}_z5_0_sun
name: z5_0 run sun
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_1_mon
name: z5_1 run mon
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_2_tue
name: z5_2 run tue
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_3_wed
name: z5_3 run wed
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_4_thu
name: z5_4 run thu
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_5_fri
name: z5_5 run fri
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_6_sat
name: z5_6 run sat
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_adjust_duration
name: z5 - Adjust Duration
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
# Zone 6 - Garden & back fence
- platform: template
id: ${id_prefix}_z6_0_sun
name: z6_0 run sun
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_1_mon
name: z6_1 run mon
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_2_tue
name: z6_2 run tue
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_3_wed
name: z6_3 run wed
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_4_thu
name: z6_4 run thu
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_5_fri
name: z6_5 run fri
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_6_sat
name: z6_6 run sat
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_adjust_duration
name: z6 - Adjust Duration
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
# Zone 7 - Left Driveway
- platform: template
id: ${id_prefix}_z7_0_sun
name: z7_0 run sun
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_1_mon
name: z7_1 run mon
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_2_tue
name: z7_2 run tue
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_3_wed
name: z7_3 run wed
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_4_thu
name: z7_4 run thu
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_5_fri
name: z7_5 run fri
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_6_sat
name: z7_6 run sat
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_adjust_duration
name: z7 - Adjust Duration
icon: mdi:calendar-range
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
# Switches to disable zones
- platform: template
id: ${id_prefix}_z1_disable
name: z1 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z2_disable
name: z2 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z3_disable
name: z3 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z4_disable
name: z4 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z5_disable
name: z5 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z6_disable
name: z6 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z7_disable
name: z7 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
- platform: template
id: ${id_prefix}_z8_disable
name: z8 - Disable
icon: mdi:water-off
entity_category: config
restore_mode: RESTORE_DEFAULT_OFF
optimistic: true
#########################################################
# END ALL SWITCHES
#########################################################
#datetimes are used to specify the daily start time
datetime:
- platform: template
name: 01 mon Start Time
entity_category: config
id: ${id_prefix}_mon_st
type: time
optimistic: true
restore_value: true
- platform: template
name: 02 tue Start Time
entity_category: config
id: ${id_prefix}_tue_st
type: time
optimistic: true
restore_value: true
- platform: template
name: 03 wed Start Time
entity_category: config
id: ${id_prefix}_wed_st
type: time
optimistic: true
restore_value: true
- platform: template
name: 04 thu Start Time
entity_category: config
id: ${id_prefix}_thu_st
type: time
optimistic: true
restore_value: true
- platform: template
name: 05 fri Start Time
entity_category: config
id: ${id_prefix}_fri_st
type: time
optimistic: true
restore_value: true
- platform: template
name: 06 sat Start Time
entity_category: config
id: ${id_prefix}_sat_st
type: time
optimistic: true
restore_value: true
- platform: template
name: 00 sun Start Time
entity_category: config
id: ${id_prefix}_sun_st
type: time
optimistic: true
restore_value: true
#########################################################
# BEGIN SENSORS
#########################################################
sensor:
- platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
name: "WiFi Signal dB"
id: wifi_signal_db
update_interval: 60s
entity_category: "diagnostic"
- platform: copy # Reports the WiFi signal strength in %
source_id: wifi_signal_db
name: "WiFi Signal Percent"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "%"
entity_category: "diagnostic"
- platform: uptime
id: uptime_seconds
name: Uptime
entity_category: "diagnostic"
#########################################################
# BEGIN rain skip sensors
#########################################################
- platform: homeassistant
id: forecasted_rain
entity_id: sensor.rain_forecast_san_jose
name: "${id_prefix} Rain Forecast San Jose"
accuracy_decimals: 2
internal: false # This makes it visible in HA
- platform: homeassistant
id: actual_rain
entity_id: sensor.rain_today_san_jose
name: "${id_prefix} Rain Today San Jose"
accuracy_decimals: 2
internal: false
#########################################################
# BEGIN Temperature Sensors
#########################################################
- platform: homeassistant
id: hi_temp_today
entity_id: sensor.max_temperature_san_jose_forecast0
name: "${id_prefix} Max Temperature San Jose Forecast0"
accuracy_decimals: 0
internal: false
- platform: homeassistant
id: hi_temp_tomorrow
entity_id: sensor.max_temperature_san_jose_forecast1
name: "${id_prefix} Max Temperature San Jose Forecast1"
accuracy_decimals: 0
internal: false
- platform: homeassistant
id: hi_temp_2days
entity_id: sensor.max_temperature_san_jose_forecast2
name: "${id_prefix} Max Temperature San Jose Forecast2"
accuracy_decimals: 0
internal: false
- platform: homeassistant
id: temp_now
entity_id: sensor.outdoor_temperature_merged
name: "${id_prefix} Outdoor Temperature Merged"
accuracy_decimals: 1
internal: false
- platform: template
name: "Weighted Avg Temp"
id: weighted_avg_temp
#unit_of_measurement: "min"
update_interval: 15min
lambda: |-
float fcst_today = id(hi_temp_today).state;
float fcst_t1 = id(hi_temp_tomorrow).state;
float fcst_t2 = id(hi_temp_2days).state;
float weighted_avg = (fcst_today * 0.5) + (fcst_t1 * 0.3) + (fcst_t2 * 0.2);
return weighted_avg;
- platform: template
name: "Duration Adjustment"
id: run_duration_adjustment
unit_of_measurement: "min"
update_interval: 15min
lambda: |-
float weighted_avg = id(weighted_avg_temp).state;
float adjustment = 0.0;
// Adjustment based on weighted avg of today & next two day's forecast
if (weighted_avg > 82) {
adjustment += floor((weighted_avg - 82) / 4.0); // +1 min per 4°F over 82
} else if (weighted_avg < 72) {
adjustment -= floor((72 - weighted_avg) / 4.0) * 2; // -2 min per 4°F under 72
} else {
adjustment += 0.0; // No adjustment for temperatures between 72–82
}
return adjustment;
#### END Temperature Sensors ####
#This needs a conditional to check if zone is using the adjustment
- platform: template
name: "Active Valve Total Runtime"
id: active_valve_total_runtime
unit_of_measurement: "min"
update_interval: 10s
lambda: |-
float adj = id(run_duration_adjustment).state;
if (id(nachio_valve01).state) return max(1.0f, min((id(zone_1_run_duration).state + adj), 30.0f));
if (id(nachio_valve02).state) return max(1.0f, min((id(zone_2_run_duration).state + adj), 30.0f));
if (id(nachio_valve03).state) return max(1.0f, min((id(zone_3_run_duration).state + adj), 30.0f));
if (id(nachio_valve04).state) return max(1.0f, min((id(zone_4_run_duration).state + adj), 30.0f));
if (id(nachio_valve05).state) return max(1.0f, min((id(zone_5_run_duration).state + adj), 30.0f));
if (id(nachio_valve06).state) return max(1.0f, min((id(zone_6_run_duration).state + adj), 30.0f));
if (id(nachio_valve07).state) return max(1.0f, min((id(zone_7_run_duration).state + adj), 30.0f));
return 0.0f;
# These manage queue info
#- platform: template
# id: sprinkler_queue_count
# name: "Sprinkler Queue Count"
# unit_of_measurement: "zones"
# icon: "mdi:format-list-numbered"
# update_interval: 10s
# lambda: |-
# return id(sprinkler_queue_size);
- platform: template
name: "Sprinkler Queue Count"
accuracy_decimals: 0
lambda: |-
return id(sprinkler_queue_size);
update_interval: 10s
- platform: template
name: "Sprinkler Queue Time Remaining"
unit_of_measurement: "min"
accuracy_decimals: 1
lambda: |-
return id(sprinkler_queue_time_remaining) / 60.0;
update_interval: 10s
binary_sensor:
- platform: status
name: "Connection Status"
# set up time and check every minute (or second) for scheduled actions
time:
- platform: homeassistant
id: ha_time
timezone: America/Los_Angeles
on_time:
# Every 1 minute
- seconds: 0
minutes: /1
then:
- script.execute: script1_trigger
#Rain Skip
- seconds: 0
minutes: /15 # Evaluate every 15 minutes
then:
- script.execute: check_rain_skip_conditions
on_time_sync:
then:
- logger.log: "Synchronized system clock"
##### Begin RAIN SKIP #####
#- platform: homeassistant
# id: ha_time
# on_time:
# - seconds: 0
# minutes: /15 # Evaluate every 15 minutes
# then:
# - script.execute: check_rain_skip_conditions
##### End RAIN SKIP #####
script:
# Step1: Check to see of the day today and the time now, match a predefined weekday start time
- id: script1_trigger
then:
lambda: |-
int dow = id(ha_time).now().day_of_week;
int hour = id(ha_time).now().hour;
int minute = id(ha_time).now().minute;
ESP_LOGD("custom", "beginning script1");
bool run_now = false;
if (dow == 1) run_now = (hour == id(${id_prefix}_sun_st).hour && minute == id(${id_prefix}_sun_st).minute);
if (dow == 2) run_now = (hour == id(${id_prefix}_mon_st).hour && minute == id(${id_prefix}_mon_st).minute);
if (dow == 3) run_now = (hour == id(${id_prefix}_tue_st).hour && minute == id(${id_prefix}_tue_st).minute);
if (dow == 4) run_now = (hour == id(${id_prefix}_wed_st).hour && minute == id(${id_prefix}_wed_st).minute);
if (dow == 5) run_now = (hour == id(${id_prefix}_thu_st).hour && minute == id(${id_prefix}_thu_st).minute);
if (dow == 6) run_now = (hour == id(${id_prefix}_fri_st).hour && minute == id(${id_prefix}_fri_st).minute);
if (dow == 7) run_now = (hour == id(${id_prefix}_sat_st).hour && minute == id(${id_prefix}_sat_st).minute);
ESP_LOGD("custom", "Today is day %d (0=Sun, 1=Mon, ..., 6=Sat)", dow);
ESP_LOGD("custom", "Current time: %02d:%02d:%02d", hour, minute, id(ha_time).now().second);
ESP_LOGD("custom", "tue scheduled time: %02d:%02d", id(${id_prefix}_tue_st).hour, id(${id_prefix}_tue_st).minute);
if (run_now) {
ESP_LOGD("custom", "completed script1, moving to script2");
id(script2_1_check_active_zones_today).execute();
}
#Step2: Identify zones that are set to run today
- id: script2_1_check_active_zones_today
then:
- lambda: |-
auto weekday = id(ha_time).now().day_of_week; // 0=sun, 1=mon, ..., 6=sat
bool should_run = false;
if (weekday == 1) { // sun
should_run = (
id(nachio_z1_0_sun).state || id(nachio_z2_0_sun).state ||
id(nachio_z3_0_sun).state || id(nachio_z4_0_sun).state ||
id(nachio_z5_0_sun).state || id(nachio_z6_0_sun).state ||
id(nachio_z7_0_sun).state
);
} else if (weekday == 2) { // tue
should_run = (
id(nachio_z1_1_mon).state || id(nachio_z2_1_mon).state ||
id(nachio_z3_1_mon).state || id(nachio_z4_1_mon).state ||
id(nachio_z5_1_mon).state || id(nachio_z6_1_mon).state ||
id(nachio_z7_1_mon).state
);
} else if (weekday == 3) { // tue
should_run = (
id(nachio_z1_2_tue).state || id(nachio_z2_2_tue).state ||
id(nachio_z3_2_tue).state || id(nachio_z4_2_tue).state ||
id(nachio_z5_2_tue).state || id(nachio_z6_2_tue).state ||
id(nachio_z7_2_tue).state
);
} else if (weekday == 4) { // wed
should_run = (
id(nachio_z1_3_wed).state || id(nachio_z2_3_wed).state ||
id(nachio_z3_3_wed).state || id(nachio_z4_3_wed).state ||
id(nachio_z5_3_wed).state || id(nachio_z6_3_wed).state ||
id(nachio_z7_3_wed).state
);
} else if (weekday == 5) { // thu
should_run = (
id(nachio_z1_4_thu).state || id(nachio_z2_4_thu).state ||
id(nachio_z3_4_thu).state || id(nachio_z4_4_thu).state ||
id(nachio_z5_4_thu).state || id(nachio_z6_4_thu).state ||
id(nachio_z7_4_thu).state
);
} else if (weekday == 6) { // fri
should_run = (
id(nachio_z1_5_fri).state || id(nachio_z2_5_fri).state ||
id(nachio_z3_5_fri).state || id(nachio_z4_5_fri).state ||
id(nachio_z5_5_fri).state || id(nachio_z6_5_fri).state ||
id(nachio_z7_5_fri).state
);
} else if (weekday == 7) { // sat
should_run = (
id(nachio_z1_6_sat).state || id(nachio_z2_6_sat).state ||
id(nachio_z3_6_sat).state || id(nachio_z4_6_sat).state ||
id(nachio_z5_6_sat).state || id(nachio_z6_6_sat).state ||
id(nachio_z7_6_sat).state
);
}
if (should_run) {
ESP_LOGD("custom", "At least one zone is active for today. Executing script2_2_check_zone_day");
id(script2_2_check_zone_day).execute();
id(script3_start_queue).execute();
} else {
ESP_LOGD("custom", "No zones active for today.");
}
- id: script2_2_check_zone_day
then:
- lambda: |-
int weekday = id(ha_time).now().day_of_week;
switch (weekday) {
case 1:
id(script2_2_check_zone_sun).execute();
break;
case 2:
id(script2_2_check_zone_mon).execute();
break;
case 3:
id(script2_2_check_zone_tue).execute();
break;
case 4:
id(script2_2_check_zone_wed).execute();
break;
case 5:
id(script2_2_check_zone_thu).execute();
break;
case 6:
id(script2_2_check_zone_fri).execute();
break;
case 7:
id(script2_2_check_zone_sat).execute();
break;
}
- id: script2_2_check_zone_sun
then:
- lambda: |-
if (id(nachio_z1_0_sun).state && !id(nachio_z1_disable).state) {
id(zone_index) = 0;
if (id(nachio_z1_adjust_duration).state) {
id(zone_duration) = (id(zone_1_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_1_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z2_0_sun).state && !id(nachio_z2_disable).state) {
id(zone_index) = 1;
if (id(nachio_z2_adjust_duration).state) {
id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_2_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z3_0_sun).state && !id(nachio_z3_disable).state) {
id(zone_index) = 2;
if (id(nachio_z3_adjust_duration).state) {
id(zone_duration) = (id(zone_3_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_3_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z4_0_sun).state && !id(nachio_z4_disable).state) {
id(zone_index) = 3;
if (id(nachio_z4_adjust_duration).state) {
id(zone_duration) = (id(zone_4_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_4_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z5_0_sun).state && !id(nachio_z5_disable).state) {
id(zone_index) = 4;
if (id(nachio_z5_adjust_duration).state) {
id(zone_duration) = (id(zone_5_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_5_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z6_0_sun).state && !id(nachio_z6_disable).state) {
id(zone_index) = 5;
if (id(nachio_z6_adjust_duration).state) {
id(zone_duration) = (id(zone_6_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_6_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z7_0_sun).state && !id(nachio_z7_disable).state) {
id(zone_index) = 6;
if (id(nachio_z7_adjust_duration).state) {
id(zone_duration) = (id(zone_7_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_7_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
//if (id(nachio_z8_0_sun).state) {
// id(zone_index) = 7;
// id(zone_duration) = id(zone_8_run_duration).state * 60;
// id(script2_3_queue_zone).execute();
//}
- id: script2_2_check_zone_mon
then:
- lambda: |-
if (id(nachio_z1_1_mon).state && !id(nachio_z1_disable).state) {
id(zone_index) = 0;
if (id(nachio_z1_adjust_duration).state) {
id(zone_duration) = (id(zone_1_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_1_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z2_1_mon).state && !id(nachio_z2_disable).state) {
id(zone_index) = 1;
if (id(nachio_z2_adjust_duration).state) {
id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_2_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z3_1_mon).state && !id(nachio_z3_disable).state) {
id(zone_index) = 2;
if (id(nachio_z3_adjust_duration).state) {
id(zone_duration) = (id(zone_3_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_3_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z4_1_mon).state && !id(nachio_z4_disable).state) {
id(zone_index) = 3;
if (id(nachio_z4_adjust_duration).state) {
id(zone_duration) = (id(zone_4_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_4_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z5_1_mon).state && !id(nachio_z5_disable).state) {
id(zone_index) = 4;
if (id(nachio_z5_adjust_duration).state) {
id(zone_duration) = (id(zone_5_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_5_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z6_1_mon).state && !id(nachio_z6_disable).state) {
id(zone_index) = 5;
if (id(nachio_z6_adjust_duration).state) {
id(zone_duration) = (id(zone_6_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_6_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z7_1_mon).state && !id(nachio_z7_disable).state) {
id(zone_index) = 6;
if (id(nachio_z7_adjust_duration).state) {
id(zone_duration) = (id(zone_7_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_7_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
//if (id(nachio_z8_1_mon).state && !id(nachio_z8_disable).state) {
// id(zone_index) = 7;
// if (id(nachio_z2_adjust_duration).state) {
// id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
//} else {
// id(zone_duration) = id(zone_2_run_duration).state * 60;
//}
// id(script2_3_queue_zone).execute();
//}
- id: script2_2_check_zone_tue
then:
- lambda: |-
if (id(nachio_z1_2_tue).state && !id(nachio_z1_disable).state) {
id(zone_index) = 0;
if (id(nachio_z1_adjust_duration).state) {
id(zone_duration) = (id(zone_1_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_1_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z2_2_tue).state && !id(nachio_z2_disable).state) {
id(zone_index) = 1;
if (id(nachio_z2_adjust_duration).state) {
id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_2_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z3_2_tue).state && !id(nachio_z3_disable).state) {
id(zone_index) = 2;
if (id(nachio_z3_adjust_duration).state) {
id(zone_duration) = (id(zone_3_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_3_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z4_2_tue).state && !id(nachio_z4_disable).state) {
id(zone_index) = 3;
if (id(nachio_z4_adjust_duration).state) {
id(zone_duration) = (id(zone_4_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_4_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z5_2_tue).state && !id(nachio_z5_disable).state) {
id(zone_index) = 4;
if (id(nachio_z5_adjust_duration).state) {
id(zone_duration) = (id(zone_5_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_5_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z6_2_tue).state && !id(nachio_z6_disable).state) {
id(zone_index) = 5;
if (id(nachio_z6_adjust_duration).state) {
id(zone_duration) = (id(zone_6_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_6_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z7_2_tue).state && !id(nachio_z7_disable).state) {
id(zone_index) = 6;
if (id(nachio_z7_adjust_duration).state) {
id(zone_duration) = (id(zone_7_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_7_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
//if (id(nachio_z8_2_tue).state) {
// id(zone_index) = 7;
// id(zone_duration) = id(zone_8_run_duration).state * 60;
// id(script2_3_queue_zone).execute();
//}
- id: script2_2_check_zone_wed
then:
- lambda: |-
if (id(nachio_z1_3_wed).state && !id(nachio_z1_disable).state) {
id(zone_index) = 0;
if (id(nachio_z1_adjust_duration).state) {
id(zone_duration) = (id(zone_1_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_1_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z2_3_wed).state && !id(nachio_z2_disable).state) {
id(zone_index) = 1;
if (id(nachio_z2_adjust_duration).state) {
id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_2_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z3_3_wed).state && !id(nachio_z3_disable).state) {
id(zone_index) = 2;
if (id(nachio_z3_adjust_duration).state) {
id(zone_duration) = (id(zone_3_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_3_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z4_3_wed).state && !id(nachio_z4_disable).state) {
id(zone_index) = 3;
if (id(nachio_z4_adjust_duration).state) {
id(zone_duration) = (id(zone_4_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_4_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z5_3_wed).state && !id(nachio_z5_disable).state) {
id(zone_index) = 4;
if (id(nachio_z5_adjust_duration).state) {
id(zone_duration) = (id(zone_5_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_5_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z6_3_wed).state && !id(nachio_z6_disable).state) {
id(zone_index) = 5;
if (id(nachio_z6_adjust_duration).state) {
id(zone_duration) = (id(zone_6_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_6_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z7_3_wed).state && !id(nachio_z7_disable).state) {
id(zone_index) = 6;
if (id(nachio_z7_adjust_duration).state) {
id(zone_duration) = (id(zone_7_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_7_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
//if (id(nachio_z8_3_wed).state) {
// id(zone_index) = 7;
// id(zone_duration) = id(zone_8_run_duration).state * 60;
// id(script2_3_queue_zone).execute();
//}
- id: script2_2_check_zone_thu
then:
- lambda: |-
if (id(nachio_z1_4_thu).state && !id(nachio_z1_disable).state) {
id(zone_index) = 0;
if (id(nachio_z1_adjust_duration).state) {
id(zone_duration) = (id(zone_1_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_1_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z2_4_thu).state && !id(nachio_z2_disable).state) {
id(zone_index) = 1;
if (id(nachio_z2_adjust_duration).state) {
id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_2_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z3_4_thu).state && !id(nachio_z3_disable).state) {
id(zone_index) = 2;
if (id(nachio_z3_adjust_duration).state) {
id(zone_duration) = (id(zone_3_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_3_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z4_4_thu).state && !id(nachio_z4_disable).state) {
id(zone_index) = 3;
if (id(nachio_z4_adjust_duration).state) {
id(zone_duration) = (id(zone_4_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_4_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z5_4_thu).state && !id(nachio_z5_disable).state) {
id(zone_index) = 4;
if (id(nachio_z5_adjust_duration).state) {
id(zone_duration) = (id(zone_5_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_5_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z6_4_thu).state && !id(nachio_z6_disable).state) {
id(zone_index) = 5;
if (id(nachio_z6_adjust_duration).state) {
id(zone_duration) = (id(zone_6_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_6_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z7_4_thu).state && !id(nachio_z7_disable).state) {
id(zone_index) = 6;
if (id(nachio_z7_adjust_duration).state) {
id(zone_duration) = (id(zone_7_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_7_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
//if (id(nachio_z8_4_thu).state) {
// id(zone_index) = 7;
// id(zone_duration) = id(zone_8_run_duration).state * 60;
// id(script2_3_queue_zone).execute();
//}
- id: script2_2_check_zone_fri
then:
- lambda: |-
if (id(nachio_z1_5_fri).state && !id(nachio_z1_disable).state) {
id(zone_index) = 0;
if (id(nachio_z1_adjust_duration).state) {
id(zone_duration) = (id(zone_1_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_1_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z2_5_fri).state && !id(nachio_z2_disable).state) {
id(zone_index) = 1;
if (id(nachio_z2_adjust_duration).state) {
id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_2_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z3_5_fri).state && !id(nachio_z3_disable).state) {
id(zone_index) = 2;
if (id(nachio_z3_adjust_duration).state) {
id(zone_duration) = (id(zone_3_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_3_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z4_5_fri).state && !id(nachio_z4_disable).state) {
id(zone_index) = 3;
if (id(nachio_z4_adjust_duration).state) {
id(zone_duration) = (id(zone_4_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_4_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z5_5_fri).state && !id(nachio_z5_disable).state) {
id(zone_index) = 4;
if (id(nachio_z5_adjust_duration).state) {
id(zone_duration) = (id(zone_5_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_5_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z6_5_fri).state && !id(nachio_z6_disable).state) {
id(zone_index) = 5;
if (id(nachio_z6_adjust_duration).state) {
id(zone_duration) = (id(zone_6_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_6_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z7_5_fri).state && !id(nachio_z7_disable).state) {
id(zone_index) = 6;
if (id(nachio_z7_adjust_duration).state) {
id(zone_duration) = (id(zone_7_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_7_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
//if (id(nachio_z8_5_fri).state) {
// id(zone_index) = 7;
// id(zone_duration) = id(zone_8_run_duration).state * 60;
// id(script2_3_queue_zone).execute();
//}
- id: script2_2_check_zone_sat
then:
- lambda: |-
if (id(nachio_z1_6_sat).state && !id(nachio_z1_disable).state) {
id(zone_index) = 0;
if (id(nachio_z1_adjust_duration).state) {
id(zone_duration) = (id(zone_1_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_1_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z2_6_sat).state && !id(nachio_z2_disable).state) {
id(zone_index) = 1;
if (id(nachio_z2_adjust_duration).state) {
id(zone_duration) = (id(zone_2_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_2_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z3_6_sat).state && !id(nachio_z2_disable).state) {
id(zone_index) = 2;
if (id(nachio_z3_adjust_duration).state) {
id(zone_duration) = (id(zone_3_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_3_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z4_6_sat).state && !id(nachio_z4_disable).state) {
id(zone_index) = 3;
if (id(nachio_z4_adjust_duration).state) {
id(zone_duration) = (id(zone_4_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_4_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z5_6_sat).state && !id(nachio_z5_disable).state) {
id(zone_index) = 4;
if (id(nachio_z5_adjust_duration).state) {
id(zone_duration) = (id(zone_5_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_5_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z6_6_sat).state && !id(nachio_z6_disable).state) {
id(zone_index) = 5;
if (id(nachio_z6_adjust_duration).state) {
id(zone_duration) = (id(zone_6_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_6_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
if (id(nachio_z7_6_sat).state && !id(nachio_z7_disable).state) {
id(zone_index) = 6;
if (id(nachio_z7_adjust_duration).state) {
id(zone_duration) = (id(zone_7_run_duration).state + id(run_duration_adjustment).state)* 60;
} else {
id(zone_duration) = id(zone_7_run_duration).state * 60;
}
id(script2_3_queue_zone).execute();
}
//if (id(nachio_z8_6_sat).state) {
// id(zone_index) = 7;
// id(zone_duration) = id(zone_8_run_duration).state * 60;
// id(script2_3_queue_zone).execute();
//}
# Add zone to queue
- id: script2_3_queue_zone
mode: queued
then:
- lambda: |-
id(sprinkler_queue_size) += 1;
// Assuming the zone runtime is stored as minutes
float runtime_min = id(zone_duration);
int runtime_sec = (int)(runtime_min * 60.0);
id(sprinkler_queue_time_remaining) += runtime_sec;
- sprinkler.queue_valve:
id: nachio_sprinklers
valve_number: !lambda |-
return id(zone_index);
run_duration: !lambda |-
return id(zone_duration);
# start the sprinkler queue
- id: script3_start_queue
then:
#- lambda: |-
# auto time = id(ha_time).now();
# char buffer[32];
# snprintf(buffer, sizeof(buffer), "%04d-%02d-%02d %02d:%02d:%02d",
# time.year, time.month, time.day_of_month,
# time.hour, time.minute, time.second);
# id(_last_run_str) = std::string(buffer);
- sprinkler.start_from_queue: ${id_prefix}_sprinklers
- lambda: |-
ESP_LOGI("main", "Sprinkler queue has begun!");
#Used to manually run a zone from Home Assistant
- id: start_valve_dynamic
then:
- lambda: |-
id(sprinkler_queue_size) += 1;
auto sprinkler = id(${id_prefix}_sprinklers);
int valve_num = (int) id(valve_number_input).state;
int duration = (int) id(var_run_duration_minutes).state * 60;
sprinkler->start_single_valve(valve_num, duration);
#### BEGIN Rain Skip related scripts ######
- id: check_rain_skip_conditions
mode: queued
then:
- lambda: |-
float forecast = id(forecasted_rain).state;
float actual = id(actual_rain).state;
if (forecast >= 0.2 || actual >= 0.2) {
id(${id_prefix}_rain_skip_lock).turn_on();
if (actual >= 0.8) {
id(rain_skip_duration_48h).execute();
} else {
id(rain_skip_duration_24h).execute();
}
}
- id: rain_skip_duration_24h
then:
- delay: 24h
- switch.turn_off: ${id_prefix}_rain_skip_lock
- id: rain_skip_duration_48h
then:
- delay: 48h
- switch.turn_off: ${id_prefix}_rain_skip_lock
##### END Rain Skip related scripts ######
###############################################
# Text sensors with general information.
###############################################
text_sensor:
# - platform: version # Expose ESPHome version as sensor.
# name: $name_of_device ESPHome Version
# hide_timestamp: false
- platform: wifi_info
ip_address:
name: "${name_of_device}_IP"
ssid:
name: "${name_of_device}_SSID"
bssid:
name: "${name_of_device}_BSSID"
- platform: template
name: "Uptime (Formatted)"
lambda: |-
int seconds = (int) id(uptime_seconds).state;
int days = seconds / 86400;
int hours = (seconds % 86400) / 3600;
int minutes = (seconds % 3600) / 60;
return to_string(days) + "d " + to_string(hours) + "h " + to_string(minutes) + "m";
entity_category: "diagnostic"
- platform: template
name: "Active Sprinkler Zone"
id: active_valve_name
update_interval: 10s
lambda: |-
if (id(nachio_valve01).state) return std::string("Front Lawn (z1)");
if (id(nachio_valve02).state) return std::string("Front Patio (z2)");
if (id(nachio_valve03).state) return std::string("Back Lawn1 (z3)");
if (id(nachio_valve04).state) return std::string("Back Lawn2 (z4)");
if (id(nachio_valve05).state) return std::string("Roses Side Yard (z5)");
if (id(nachio_valve06).state) return std::string("Garden Rear Fence (z6)");
if (id(nachio_valve07).state) return std::string("Left Driveway (z7)");
if (id(nachio_valve08).state) return std::string("Unassigned (z8)");
return std::string("None");
- platform: template
id: time_remaining
name: "Current Zone Time Remaining"
update_interval: 10s
icon: "mdi:timer-sand"
lambda: |-
int remaining = id(nachio_sprinklers).time_remaining_active_valve().value_or(0);
int days = remaining / 86400;
int hours = (remaining % 86400) / 3600;
int minutes = (remaining % 3600) / 60;
int seconds = remaining % 60;
char buffer[32];
snprintf(buffer, sizeof(buffer), "%s%s%dm %ds",
(days > 0 ? (std::to_string(days) + "d ").c_str() : ""),
(hours > 0 ? (std::to_string(hours) + "h ").c_str() : ""),
minutes, seconds
);
return std::string(buffer);