Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ the image below).

## How to use

### Minimal configuration for the stock hardware

Include following fragment to your ESPHome configuration (`sprinkler` name of
the package could be anything), it is recommended to use specific release
version (see
Expand All @@ -128,7 +130,6 @@ A temperature sensor is a prerequisite to the configuration, its ID should be
passed via `temperature_sensor_id` substitution - it is only used by display
component currently.


```yaml
substitutions:
temperature_sensor_id: temperature_sensor
Expand All @@ -148,10 +149,21 @@ packages:
The configuration could further be adjusted using substitutions, see
[main.yaml](main.yaml) for details.

You can also remove certain portions of the configuration marked as `Optional`
in [main.yaml](main.yaml) if you don't have particular hardware or need to use that
functionality.
### Full configuration including optional components

If you have optional hardware modifications (RTC, display) and would like to use it,
you would rather use `full.yaml` instead of `main.yaml`:

```yaml
packages:
sprinkler: github://hostcc/esphome-config-sprinkler/full.yaml@<release version>
```

### Further customization

You can also remove certain portions of the configuration marked as `Optional`
in [full.yaml](full.yaml) and [main.yaml](main.yaml) if you don't have particular
hardware or need to use that functionality.

## Sample installation

Expand Down
22 changes: 22 additions & 0 deletions buzzer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2023 Ilia Sotnikov
---
esphome:
platformio_options:
build_flags:
# Define the preprocessor macro indicating presence of buzzer
# components so that dependent code could be conditional
- '-DHAS_BUZZER'

switch:
- platform: output
name: Buzzer
output: buzzer
internal: true

output:
- platform: rp2040_pwm
pin: GPIO6
# This gives ~2KHz output, by a reason this frequency is not in Hz
frequency: 8000000
id: buzzer
24 changes: 19 additions & 5 deletions display.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ esphome:
- '-DHAS_DISPLAY'

spi:
id: display_spi
clk_pin: GPIO2
mosi_pin: GPIO3
interface: hardware
Expand Down Expand Up @@ -108,10 +109,20 @@ display:
);

// Symbols indicating state of water tank emptiness and rain sensor
#ifdef HAS_CUSTOM_INPUTS
it.printf(
42, 22, material, TextAlign::TOP_CENTER, "%s%s%s",
id(${water_tank_empty_id}).state ? "\U0000f6d5": "\U0000f6d6",
id(${rain_sensor_id}).state ? "\U0000f176" : "\U0000e81a",
30, 22, material, TextAlign::TOP_CENTER,
"%s%s",
${water_tank_empty_id}->state ? "\U0000f6d5": "\U0000f6d6",
${rain_sensor_id}->state ? "\U0000f176" : "\U0000e81a"
);
#endif // HAS_CUSTOM_INPUTS

// Symbol indicating state of peripherals power relay, same vertical
// position as the previous ones
it.printf(
66, 22, material, TextAlign::TOP_CENTER,
"%s",
id(${peripherals_power_off_relay_id}).state ? "\U0000e224" : ""
);

Expand Down Expand Up @@ -168,6 +179,7 @@ display:

- id: display_page2
lambda: |-
#ifdef USE_WIFI
#include <esphome/components/wifi/wifi_component.h>
using namespace esphome::wifi;

Expand All @@ -180,8 +192,10 @@ display:
84, 14, primary, TextAlign::CENTER_RIGHT, "%i dBm",
global_wifi_component->wifi_rssi()
);

} else {
} else
#endif // USE_WIFI
// Always show WiFi disconnected symbol if WiFi is not used
{
it.print(0, 14, material, TextAlign::CENTER_LEFT, "\U0000e648");
it.print(84, 14, primary, TextAlign::CENTER_RIGHT, " ");
}
Expand Down
13 changes: 13 additions & 0 deletions full.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2023 Ilia Sotnikov
---
packages:
minimal: !include main.yaml
# Optional packages, mostly for platform-specific or optional elements - the
# `main.yaml` being agnostic could also be used for tests on other platforms
# such as `host`
inputs: !include inputs.yaml
buzzer: !include buzzer.yaml
display: !include display.yaml
indicators: !include indicators.yaml
rtc: !include rtc.yaml
6 changes: 5 additions & 1 deletion indicators.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,16 @@ light:
call.perform();
return;
};
if (id(${rain_sensor_id}).state) {

#ifdef HAS_CUSTOM_INPUTS
if (${rain_sensor_id}->state) {
auto call = id(${led_id}).turn_on();
call.set_effect("pulse_slow");
call.set_color_brightness(${led_brightness});
call.set_rgb(0.4, 1.0, 0.9);
call.perform();
return;
};
#endif // HAS_CUSTOM_INPUTS

id(${led_id}).turn_on();
18 changes: 14 additions & 4 deletions inputs.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2023 Ilia Sotnikov
---
esphome:
platformio_options:
build_flags:
# Define the preprocessor macro indicating presence of custom inputs
# so that dependent code could be conditional
- '-DHAS_CUSTOM_INPUTS'

binary_sensor:
- platform: gpio
id: ${rain_sensor_id}
Expand All @@ -15,7 +22,8 @@ binary_sensor:
filters:
- delayed_on: 100ms
- delayed_off: 100ms
publish_initial_state: true
# Renamed from `publish_initial_state` in ESPHome 2025.7.0
trigger_on_initial_state: true
on_state:
then:
- lambda: !include
Expand All @@ -36,7 +44,8 @@ binary_sensor:
filters:
- delayed_on: 100ms
- delayed_off: 100ms
publish_initial_state: true
# Same as above
trigger_on_initial_state: true
on_state:
then:
- lambda: !include
Expand All @@ -55,7 +64,7 @@ binary_sensor:
filters:
- delayed_on: 100ms
- delayed_off: 100ms
publish_initial_state: true
trigger_on_initial_state: true
- platform: gpio
internal: true
pin:
Expand All @@ -68,4 +77,5 @@ binary_sensor:
filters:
- delayed_on: 100ms
- delayed_off: 100ms
publish_initial_state: true
# Same as above
trigger_on_initial_state: true
37 changes: 5 additions & 32 deletions main.yaml
Original file line number Diff line number Diff line change
@@ -1,42 +1,15 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2023 Ilia Sotnikov
---
substitutions:
run_duration_uom: s
run_duration_initial_value: '5'
rain_sensor_id: rain_sensor
rain_sensor_inverted: 'true'
water_tank_empty_id: water_tank_empty
water_tank_empty_inverted: 'true'
peripherals_power_off_relay_id: relay_7
pump_relay_id: relay_8
valve_overlap: 1s
pump_start_pump_delay: 1s
pump_stop_valve_delay: 1s
peripherals_power_refill_pulse_duration: 3s
scheduled_start_wait_tank_full_duration: 60s
led_id: led
led_brightness: '0.5'
display_backlight_id: display1_backlight
display_page_when_active: display_page1
display_page_show_duration: 3s
display_id: display1
display_rotation: '0'
rtc_id: rtc_time
timezone: UTC
temperature_sensor_id: temperature

packages:
substitutions: !include substitutions.yaml
outputs: !include outputs.yaml
inputs: !include inputs.yaml
schedule: !include schedule.yaml # Optional
display: !include display.yaml # Optional
indicators: !include indicators.yaml # Optional
controllers: !include controllers.yaml
status_sensors: !include status_sensors.yaml
schedule: !include schedule.yaml # Optional
time: !include time.yaml # Optional
rtc: !include rtc.yaml # Optional

# 2024.11.0 addresses security vulnerability
# 2025.7.0 introduced change from `publish_initial_state` to
# `trigger_on_initial_state` for `binary_sensor` component
esphome:
min_version: '2024.11.0'
min_version: '2025.7.0'
11 changes: 0 additions & 11 deletions outputs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,3 @@ switch:
pin: GPIO14
id: ${pump_relay_id}
internal: true
- platform: output
name: Buzzer
output: buzzer
internal: true

output:
- platform: rp2040_pwm
pin: GPIO6
# This gives ~2KHz output, by a reason this frequency is not in Hz
frequency: 8000000
id: buzzer
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
esphome==2025.9.1
esphome==2025.10.3
pillow==10.4.0
14 changes: 12 additions & 2 deletions schedule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,12 @@ dynamic_on_time:
level: 'INFO'
- wait_until:
condition:
binary_sensor.is_off: ${water_tank_empty_id}
lambda: |-
#ifdef HAS_CUSTOM_INPUTS
return !${water_tank_empty_id}->state;
#else
return true;
#endif
timeout: ${scheduled_start_wait_tank_full_duration}
- logger.log:
format: 'schedule: Starting full sprinkler cycle'
Expand All @@ -252,7 +257,12 @@ dynamic_on_time:
level: 'INFO'
- wait_until:
condition:
binary_sensor.is_off: ${water_tank_empty_id}
lambda: |-
#ifdef HAS_CUSTOM_INPUTS
return !${water_tank_empty_id}->state;
#else
return true;
#endif
timeout: ${scheduled_start_wait_tank_full_duration}
- logger.log:
format: 'schedule: Starting full sprinkler cycle'
Expand Down
8 changes: 5 additions & 3 deletions script_rain_water_tank_sensors_action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
return;
}

#ifdef HAS_CUSTOM_INPUTS
// Handle rain detected or water tank is empty
if (id(${rain_sensor_id}).state || id(${water_tank_empty_id}).state) {
if (${rain_sensor_id}->state || ${water_tank_empty_id}->state) {
ESP_LOGI(
"${triggered_by}",
"%s sprinklers and putting them in standby"
Expand All @@ -26,8 +27,8 @@
#else
"Pausing"
#endif
, ONOFF(id(${rain_sensor_id}).state)
, ONOFF(id(${water_tank_empty_id}).state)
, ONOFF(${rain_sensor_id}->state)
, ONOFF(${water_tank_empty_id}->state)
);

// Explicitly shutdown any running operation in case of rain, also turn on
Expand Down Expand Up @@ -66,6 +67,7 @@
// inactive
return;
}
#endif // HAS_CUSTOM_INPUTS

ESP_LOGI(
"${triggered_by}", "Putting sprinklers out of standby"
Expand Down
4 changes: 3 additions & 1 deletion script_refill_tank.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ if:
// Ignore the fragment being triggered during 'sprinkler' component
// setup when its switches are turned off initially (would be redundant)
&& (id(${sprinkler}).get_component_state() & COMPONENT_STATE_LOOP)
#ifdef HAS_CUSTOM_INPUTS
// Ignore attempt to refill the tank when it has already been reported
// as empty (would be redundant)
&& !id(${water_tank_empty_id}).state
&& !${water_tank_empty_id}->state
#endif // HAS_CUSTOM_INPUTS
// Ignore attempt to refill the tank if controller is in standby
&& !id(${sprinkler}).standby();
then:
Expand Down
25 changes: 25 additions & 0 deletions substitutions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
substitutions:
run_duration_uom: s
run_duration_initial_value: '5'
rain_sensor_id: rain_sensor
rain_sensor_inverted: 'true'
water_tank_empty_id: water_tank_empty
water_tank_empty_inverted: 'true'
peripherals_power_off_relay_id: relay_7
pump_relay_id: relay_8
valve_overlap: 1s
pump_start_pump_delay: 1s
pump_stop_valve_delay: 1s
peripherals_power_refill_pulse_duration: 3s
scheduled_start_wait_tank_full_duration: 60s
led_id: led
led_brightness: '0.5'
display_backlight_id: display1_backlight
display_page_when_active: display_page1
display_page_show_duration: 3s
display_id: display1
display_rotation: '0'
rtc_id: rtc_time
timezone: UTC
temperature_sensor_id: temperature
2 changes: 1 addition & 1 deletion tests/rp2040w.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ sensor:

packages:
main: !include
file: ../main.yaml
file: ../full.yaml