ESPHome Sprinkler controller

Many thanks!

I’m just trying to sort out individual sprinkler times myself. Would you mind posting your end result ESPhome code?

EDIT: I have it working but since the default for the valve_run_time is in seconds and the number entity to change it via the UI is in minutes there is a bit of a bug on startup of the ESP. It tries to use the valve run time I have set to 20s but displays in the UI as 20 Mins due to the number entity… Testing will see how this pans out.

Hello @sparkydave, Substitutions are included at the head of the file, one of which is UOM:. In my case, I’ve set this to ‘Min’ as I don’t see value in using seconds. This change only impacts the UI. It doesn’t convert seconds to minutes. There’s a section of code under “esphome:” that executes at startup. In that section I set the multiplier to 60. It’s default is 1.

Here is the section of code that performs the conversion;

  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:
          multiplier: 60

here is the entire code;

# Based on ESPHome Sprinkler Controller - https://esphome.io/components/sprinkler.html

# Change Log
# 2022 10 24 v01
  # - Initial Build
# 2022 10 26 v02
  # - Added Status Led
  # - Add Previous Button
  # - Add Next Button

# Establish Substitutions
substitutions:
# Modify only the following eight lines.
  software_version: 2022 10 26 v02
  zone_1_name: Front Lawn
  zone_2_name: Front Garden
  zone_3_name: South Garden
  zone_4_name: Rear Garden
  zone_5_name: Rear Lawn
  zone_6_name: North Garden
  zone_7_name: Drip Line A
  zone_8_name: Drip Line B
# DO NOT CHANGE ANYTHING BELOW THIS LINE ###
  zone_1_valve_id: valve_0
  zone_2_valve_id: valve_1
  zone_3_valve_id: valve_2
  zone_4_valve_id: valve_3
  zone_5_valve_id: valve_4
  zone_6_valve_id: valve_5
  zone_7_valve_id: valve_6
  zone_8_valve_id: valve_7
  esphome_name: irrigation-valve-ctrl-unit
  esphome_platform: ESP32
  esphome_board: nodemcu-32s
  esphome_comment: Eight Valve Irrigation Control
  esphome_project_name: Robert.Eight Valve Irrigation Control
  esphome_project_version: Eight Valve Irrigation Ctrl, $software_version
  devicename: irrigation_valve_controller
  upper_devicename: Eight Valve Irrigation Ctrl
  sensor_update_frequency: 10s
  uom: Min

#Define Project Details and ESP Board Type
esphome:
  name: $esphome_name
  platform: $esphome_platform
  board: $esphome_board
  comment: $esphome_comment
  project:
    name: $esphome_project_name
    version: $esphome_project_version
  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:
          multiplier: 60

# WiFi connection, replace these with values for your WiFi.
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

# Enable logging
logger:
  
# Enable over-the-air updates.
ota:
  password: !secret ota_password

# Enable Web server.
web_server:
  port: 80

# Sync time with Home Assistant.
time:
  - platform: homeassistant
    id: homeassistant_time

# Text sensors with general information.
text_sensor:
  # Expose ESPHome version as sensor.
  - platform: version
    name: Version

  # Expose WiFi information as sensor.
  - platform: wifi_info
    ip_address:
      name: $devicename IP
    ssid:
      name: $devicename SSID
    bssid:
      name: $devicename BSSID

  # Expose Time Remaining as a sensor.
  - platform: template
    id: time_remaining
    name: "Time Remaining"
    update_interval: $sensor_update_frequency
    icon: "mdi:timer-sand"
    lambda: |-
      int seconds = round(id($devicename).time_remaining().value_or(0));
      int days = seconds / (24 * 3600);
      seconds = seconds % (24 * 3600);
      int hours = seconds / 3600;
      seconds = seconds % 3600;
      int minutes = seconds /  60;
      seconds = seconds % 60;
        return {
          ((days ? String(days) + "d " : "") +
          (hours ? String(hours) + "h " : "") +
          (minutes ? String(minutes) + "m " : "") +
          (String(seconds) + "s")
          ).c_str()};

  # Expose Progress Percent as a sensor.
  - platform: template
    id: progress_percent
    name: "Progress %"
    update_interval: $sensor_update_frequency
    icon: "mdi:progress-clock"
    lambda: |-
      int progress_percent = round(((id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0)) - id($devicename).time_remaining().value_or(0)) * 100 / id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0))));
      std::string progress_percent_as_string = esphome::to_string(progress_percent);
      return progress_percent_as_string;

  # Expose Valve Status as a sensor.
  - platform: template
    id: valve_status
    name: "Status"
    update_interval: never
    icon: "mdi:information-variant"

# Enable On-Board Status LED.
light:
  - platform: status_led
    pin: GPIO2
    id: led_status_light
    restore_mode: ALWAYS_ON
    internal: true
    effects:
    - strobe:
        name: "Slow Blink" # 0.1s on, 2s off
        colors:
          - state: true
            brightness: 100%
            duration: 100ms
          - state: false
            duration: 2s
    on_turn_on:
      - light.turn_on:
          id: led_status_light
          effect: "Slow Blink"

sensor:
  # Uptime sensor.
  - platform: uptime
    name: $upper_devicename Uptime

  # WiFi Signal sensor.
  - platform: wifi_signal
    name: $upper_devicename WiFi Signal
    update_interval: 60s

# Enable Home Assistant APIs
api:
#  encryption:
#    key: !secret api_encryption
#  password: !secret api_password

number:
  - platform: template
    id: $zone_1_valve_id
    name: $zone_1_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(0);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 0
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_2_valve_id
    name: $zone_2_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(1);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 1
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_3_valve_id
    name: $zone_3_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(2);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 2
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_4_valve_id
    name: $zone_4_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(3);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 3
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_5_valve_id
    name: $zone_5_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(3);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 4
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_6_valve_id
    name: $zone_6_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(3);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 5
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_7_valve_id
    name: $zone_7_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(3);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 6
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_8_valve_id
    name: $zone_8_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: $uom
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(3);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 7
          run_duration: !lambda 'return x;'

sprinkler:
  - id: $devicename
    main_switch:
      name: "Start/Stop/Resume"
      id: main_switch
          
    auto_advance_switch: "Auto Advance"
    valve_open_delay: 2s
    valves:
      - valve_switch: $zone_1_name
        enable_switch: Enable $zone_1_name
        run_duration: 20s
        valve_switch_id: ${devicename}_1
      - valve_switch: $zone_2_name
        enable_switch: Enable $zone_2_name
        run_duration: 20s
        valve_switch_id: ${devicename}_2
      - valve_switch: $zone_3_name
        enable_switch: Enable $zone_3_name
        run_duration: 20s
        valve_switch_id: ${devicename}_3
      - valve_switch: $zone_4_name
        enable_switch: Enable $zone_4_name
        run_duration: 20s
        valve_switch_id: ${devicename}_4
      - valve_switch: $zone_5_name
        enable_switch: Enable $zone_5_name
        run_duration: 20s
        valve_switch_id: ${devicename}_5
      - valve_switch: $zone_6_name
        enable_switch: Enable $zone_6_name
        run_duration: 20s
        valve_switch_id: ${devicename}_6
      - valve_switch: $zone_7_name
        enable_switch: Enable $zone_7_name
        run_duration: 20s
        valve_switch_id: ${devicename}_7
      - valve_switch: $zone_8_name
        enable_switch: Enable $zone_8_name
        run_duration: 20s
        valve_switch_id: ${devicename}_8

button:

  - platform: template
    id: sprinkler_pause
    name: "Pause"
    icon: "mdi:pause"
    on_press:
      then:
        - text_sensor.template.publish:
            id: valve_status
            state: "Paused"
        - sprinkler.pause: $devicename

  - platform: template
    id: sprinkler_next
    name: "Next"
    icon: mdi:skip-next
    on_press:
      then:
        - sprinkler.next_valve: $devicename

  - platform: template
    id: sprinkler_previous
    name: "Previous"
    icon: mdi:skip-previous
    on_press:
      then:
        - sprinkler.previous_valve: $devicename

switch:

# Hidden switches.
# Switches that control sprinkler valve relays
  - platform: gpio
    name: Relay Board Pin IN1 - Relay Board A
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_1
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_1_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 19
      number: 19
      inverted: true
  - platform: gpio
    name: Relay Board Pin IN2 - Relay Board A
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_2
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_2_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 21
      number: 21
      inverted: true
  - platform: gpio
    name: Relay Board Pin IN3 - Relay Board A
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_3
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_3_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 22
      number: 22
      inverted: true
  - platform: gpio
    name: Relay Board Pin IN4 - Relay Board A
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_4
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_4_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 23
      number: 23
      inverted: true
  - platform: gpio
    name: Relay Board Pin IN1 - Relay Board B
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_5
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_5_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 27
      number: 27
      inverted: true
  - platform: gpio
    name: Relay Board Pin IN2 - Relay Board B
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_6
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_6_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 26
      number: 26
      inverted: true
  - platform: gpio
    name: Relay Board Pin IN3 - Relay Board B
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_7
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_7_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 33
      number: 33
      inverted: true
  - platform: gpio
    name: Relay Board Pin IN4 - Relay Board B
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_8
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_8_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin:
      # GPIO 32
      number: 32
      inverted: true

On a slightly different note; I use a number of “substitutions:” in my code. One of which is “sensor_update_frequency: 10s”. The value reflects how often the display is updated. I’ve set it to 10s which means Time Remaining and Progress % update every 10 seconds. The value can be set to anything you wish. setting it to 1s would cause the UI to update every second instead of every 10 seconds. I’m using 10s as I don’t want the device to flood the network with messages every second for as long as the device is powered on. Ideally I’d like Time Remaining and Progress % to update once per second but only when a sprinkler is active. I haven’t figured out how to do that yet.

1 Like

@rcblackwell I have this problem with this part of code:

text_sensor:
  - platform: template
    id: progress_percent_controller_irrigazione
    name: "Progress % (controller_irrigazione)"
    update_interval: 2s
    icon: "mdi:progress-clock"
    lambda: |-
      int progress_percent = round(((id(controller_irrigazione).valve_run_duration_adjusted(id(controller_irrigazione).active_valve().value_or(0)) - id(controller_irrigazione).time_remaining().value_or(0)) * 100 / id(controller_irrigazione).valve_run_duration_adjusted(id(controller_irrigazione).active_valve().value_or(0))));
      std::string progress_percent_as_string = std::to_string(progress_percent);
      return progress_percent_as_string;

ERROR:

Compiling /data/esp-irrigazione/.pioenvs/esp-irrigazione/src/main.cpp.o
/config/esphome/esp-irrigazione.yaml: In lambda function:
/config/esphome/esp-irrigazione.yaml:133:48: error: 'to_string' is not a member of 'std'
       std::string progress_percent_as_string = std::to_string(progress_percent);
                                                ^
/config/esphome/esp-irrigazione.yaml:133:48: note: suggested alternatives:
In file included from src/esphome/components/api/proto.h:5:0,
                 from src/esphome/components/api/api_pb2.h:5,
                 from src/esphome/components/api/api_connection.h:4,
                 from src/esphome.h:3,
                 from src/main.cpp:3:
src/esphome/core/helpers.h:259:20: note:   'esphome::to_string'
 inline std::string to_string(const std::string &val) { return val; }
                    ^
src/esphome/core/helpers.h:259:20: note:   'esphome::to_string'
*** [/data/esp-irrigazione/.pioenvs/esp-irrigazione/src/main.cpp.o] Error 1
========================= [FAILED] Took 11.29 seconds =========================

And this…

text_sensor:
 - platform: template
    id: time_remaining_controller_irrigazione
    name: "Time Remaining (controller_irrigazione)"
    update_interval: 3s
    icon: "mdi:timer-sand"
    lambda: |-
      int seconds = round(id(controller_irrigazione).time_remaining().value_or(0));
      int days = seconds / (24 * 3600);
      seconds = seconds % (24 * 3600);
      int hours = seconds / 3600;
      seconds = seconds % 3600;
      int minutes = seconds /  60;
      seconds = seconds % 60;
        return {
          ((days ? String(days) + "d " : "") +
          (hours ? String(hours) + "h " : "") +
          (minutes ? String(minutes) + "m " : "") +
          (String(seconds) + "s")
          ).c_str()};

ERROR:

INFO Reading configuration /config/esphome/esp-irrigazione.yaml...
ERROR Error while reading config: Invalid YAML syntax:

mapping values are not allowed here
  in "/config/esphome/esp-irrigazione.yaml", line 127, column 7:
        id: time_remaining_controller_irri ... 
          ^

@KameDomotics , Based on the error, I’m assuming use of an ESP32 device. The code you’ve used works with an ESP8266. It doesn’t work with the ESP32. I’ve subsequently changed this section of code so that it also works with the latter. Please see the change as posted in this message.

The spacing in your code is incorrect! The “id:” and all subsequent lines in that section are indented one space to many. Try;

text_sensor:
  - platform: template
    id: time_remaining_controller_irrigazione
    name: "Time Remaining (controller_irrigazione)"
    update_interval: 3s
    icon: "mdi:timer-sand"
    lambda: |-
      int seconds = round(id(controller_irrigazione).time_remaining().value_or(0));
      int days = seconds / (24 * 3600);
      seconds = seconds % (24 * 3600);
      int hours = seconds / 3600;
      seconds = seconds % 3600;
      int minutes = seconds /  60;
      seconds = seconds % 60;
      return {
        ((days ? String(days) + "d " : "") +
        (hours ? String(hours) + "h " : "") +
        (minutes ? String(minutes) + "m " : "") +
        (String(seconds) + "s")
        ).c_str()};

Ok, now it works thanks!

In the “progress_percent” text sensor is there the possibility to put the unit of measure next to the number? Now I see 100 for example, can I put 100%?
I tried with unit_of_measurement:% but it didn’t work.

And also another question: in the “Time remaining” sensor I see the time of each single valve running, can I see the total time of the valves as a sum? (e.g. valve 1 10s, valve 2 10s, valve 3 20s - Time remaining: 40s)

The value of “Progress %” is passed to HA as a chr string, not a number. It’s for this reason adding unit_of_measurement:% to your code didn’t work. Having said that, it is possible to add the “%” sign to the right of the number. In the section tittled " # Expose Progress Percent as a sensor.", you’ll need to add;

  + "%"

to the end of the line reading;

      std::string progress_percent_as_string = esphome::to_string(progress_percent);

The new line would read;

      std::string progress_percent_as_string = esphome::to_string(progress_percent) + "%";

Your may also wish to revise the name to read;

    name: "Progress"

rather than;

    name: "Progress %"

Here’s the full section of the code that outputs the percentage complete value;

  # Expose Progress Percent as a sensor.
  - platform: template
    id: progress_percent
    name: "Progress"
    update_interval: $sensor_update_frequency
    icon: "mdi:progress-clock"
    lambda: |-
      int progress_percent = round(((id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0)) - id($devicename).time_remaining().value_or(0)) * 100 / id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0))));
      std::string progress_percent_as_string = esphome::to_string(progress_percent) + "%";
      return progress_percent_as_string;

Thank you for the idea! I’ve amended my code accordingly.

I’m sure that’s possible however I haven’t developed code that would do so. Might be an interesting aspect to take on! Give me a week or so to see what I can do.

1 Like

Sorry to dig this thread up again however I have discovered an issue when using these individual valve run times.

If I set one of the valve run times to zero, the sprinkler system fails to run at all when I call the service: esphome.retic_controller_poe_start_full_cycle , being the controller name in ESPhome.

Has anyone else tried this?

Sorry for jumping into this thread a bit late:

I don’t understand how your configuration preserves the valve durations across restarts of the controller. You have the durations in the sprinkler compoment set to 20s, and number components which can be used to change them, but I don’t see any place where the chosen durations are stored and restored on reboot.

Do you have some other mechanism which is handling that?

@kpfleming, Kevin,

Unfortunately I’ve been unable to come up with a solution for that scenario. It’s something I’ve been struggling with for some time. If i ever find a solution, I will post on the forum.

I’m working on something now… if I get it working I’ll PM if you if that’s OK and you can review it.

Would be greatly appreciated. Thanks

HI.
Is it possible, for each sprinkler, to select the days in which they must work? Now I can choose time and duration, can I add days? (for example sprinkler 2 active only on Monday - Wednesday - Friday)
Thanks



sprinkler:
  - id: controller_irrigazione
    main_switch: "Irrigatori"
    auto_advance_switch: "Irrigatori Auto Advance"
    reverse_switch: "Irrigatori Reverse"
    valve_open_delay: 0s
    valves:
      - valve_switch: "Irrigatore 1"
        enable_switch: "Enable Irrigatore 1"
        pump_switch_id: sprinkler_pump_sw
        run_duration: 1s
        valve_switch_id: sprinkler_valve_sw1
      - valve_switch: "Irrigatore 2"
        enable_switch: "Enable Irrigatore 2"
        pump_switch_id: sprinkler_pump_sw
        run_duration: 1s
        valve_switch_id: sprinkler_valve_sw2
      - valve_switch: "Irrigatore 3"
        enable_switch: "Enable Irrigatore 3"
        pump_switch_id: sprinkler_pump_sw
        run_duration: 1s
        valve_switch_id: sprinkler_valve_sw3

switch:
  - platform: gpio
    id: sprinkler_pump_sw
    pin: 12
    inverted: true
    icon: mdi:water-pump
  - platform: gpio
    id: sprinkler_valve_sw1
    pin: 0
    inverted: true
    icon: mdi:sprinkler-variant
  - platform: gpio
    id: sprinkler_valve_sw2
    pin: 2
    inverted: true
    icon: mdi:sprinkler-variant
  - platform: gpio
    id: sprinkler_valve_sw3
    pin: 4
    inverted: true
    icon: mdi:sprinkler-variant
    
number:
  - platform: template
    id: sprinkler_valve_1_timer
    name: "Sprinkler Timer Controller Sw1"
    icon: mdi:timer-outline
    min_value: 5
    max_value: 120
    step: 1
    mode: box
    unit_of_measurement: s
    lambda: "return id(controller_irrigazione).valve_run_duration(0);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: controller_irrigazione
          valve_number: 0
          run_duration: !lambda 'return x;'   

  - platform: template
    id: sprinkler_valve_2_timer
    name: "Sprinkler Timer Controller Sw2"
    icon: mdi:timer-outline
    min_value: 5
    max_value: 120
    step: 1
    mode: box
    unit_of_measurement: s
    lambda: "return id(controller_irrigazione).valve_run_duration(1);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: controller_irrigazione
          valve_number: 1
          run_duration: !lambda 'return x;'  

  - platform: template
    id: sprinkler_valve_3_timer
    name: "Sprinkler Timer Controller Sw3"
    icon: mdi:timer-outline
    min_value: 5
    max_value: 120
    step: 1
    mode: box
    unit_of_measurement: s
    lambda: "return id(controller_irrigazione).valve_run_duration(2);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: controller_irrigazione
          valve_number: 2
          run_duration: !lambda 'return x;'   

No, ESPHome doesn’t have any concept of timers or calendars. You’d need to create automations in Home Assistant to do what you want here.

Note that you can’t even choose the time for the program to run in ESPHome; only the durations.

Does anyone know if it is possible to use multiple esp devices with the built in sprinkler control? My use case is that my bore pump control is a significant distance from my irrigation control gear and I would rather use a $10 wireless device than dig trenches and run cable :slight_smile:

For some reason I thought it would be simple to call a switch on/off on another esp home device with the sprinkler controller to start the pump… but maybe not?

Cheers,

Cam

ESPHome doesn’t have any mechanism to communicate directly between devices. You’d probably have to come up with some sort of fake switch which can be triggered by the sprinkler component, then react to that state change in Home Assistant and trigger the switch in the other ESPHome device.

Fair enough - at that point it is probably convoluted enough to just use an automation.

Now that I think about it, there are some options:

  1. You could use the HTTP client component to trigger an API action on the other device; constructing the payload could be a bit challenging though.

  2. You could use the MQTT client component to publish messages on a topic from one device, and listen for them on the other device.