Garden Irrigation

Hi @sparkydave

I tried your code to the T and whenever i set the runtime it doesn’t seem like the automation actually kick off the script to turn on the Retic Station 1 Valve. Instead of ESPHome code on NodeMCU i’m trying to get the automation to call the script script.retic_program1_run to turn on the switch that uses mqtt as referred to in some of your older posts. https://community.home-assistant.io/t/garden-irrigation/1950/167?u=irishinsanity

Have you had any issues with the automation not kicking off the scripts? I trying to figure out if i should remove the automation: !include automations.yaml from the configuration.yaml file and use all of your code as is including the automations in /config/packages/reticulation.yaml or if your automation bit of the code should be in the automations.yaml file.

I REAALY want to get this going. I’ve spent the good of 2 days trying to work this out.
Going to have another crack at this tomorrow again and can paste some of the code here.

Your will be appreciated.

Hello Philippe, I looked at the config of your github files and some configs seem to be missing. I can’t seem to find the sensor config for input_boolean.cycle2_enable, run_time, manual_run, morning and afternoon cycle status, timer.cycle1_zone_duration etc etc. Is it anyway possible we could have a chat perhaps? I tried using the config from your github page but certain information i can’t seem to find in your .yaml files.

I recently change the entire irrigation flow / automation. So if you want to to have a chat you can contact me on discord.

Hi @phdelodder , can you email me your discord details? My email address is [email protected]. Thank you very much for responding.

@klogg Your work is absolutely amazing. This helped me so much. I got everything working as explained. I was wondering. Is there by ANY chance a way you could give advice how to remove the “Daily” and “Alternate” for that for days of the week? I’ve been staring at this code for two days straight and for the love of me i can’t work out how to switch the pieces with some code from Dave. Any help will be appreciated.

  • platform: template # determine if today is selected as a watering day for program 1
    sensors:
    retic_program1_watering_day:
    value_template: >
    {% set sensor_names = [ ‘monday’, ‘tuesday’, ‘wednesday’,‘thursday’,‘friday’,‘saturday’,‘sunday’] %}
    {% set today_name = sensor_names[now().weekday()] %}
    {% set entity_id = ‘input_boolean.retic_program1_’+today_name %}
    {{ is_state(entity_id, ‘on’) }}

    retic_program2_watering_day:
      value_template:  >
        {% set sensor_names = [ 'monday', 'tuesday', 'wednesday','thursday','friday','saturday','sunday'] %}
        {% set today_name = sensor_names[now().weekday()] %}
        {% set entity_id = 'input_boolean.retic_program2_'+today_name %}
        {{ is_state(entity_id, 'on') }}
    

input_boolean:
retic_program1_monday: # watering day selections for program 1
name: Monday

retic_program1_tuesday:
name: Tuesday

retic_program1_wednesday:
name: Wednesday

retic_program1_thursday:
name: Thursday

retic_program1_friday:
name: Friday

retic_program1_saturday:
name: Saturday

retic_program1_sunday:
name: Sunday

Thanks for the compliment…

Firstly, because I had a few people interested in this I created a separate thread to split my project away from here. You might like to look there as there have been a few changes based on input and help from others.

Regarding your specific question, if I understand correctly it would not be possible as I have only allowed for two different cycles. One or both cycles will run on the days chosen which as it stands is every day or alternate days.

If you want different cycles on different days I suggest you try using the code by @sparkydave which others here seem have used to very good effect and looks pretty good to me (of course I looked at it to see if I could steal any ideas learn from it :wink: )

It works fine for me. I’m not using MQTT (as per early posts) because I’m using the ESPhome native API for HA. Using my most recent code posting above should work fine once you change any relevant entity_id’s for your own.

You can have:

automation: !include automations.yaml

as well as the package. Just make sure you are also referencing packages as per the docs.

Hi, @sparkydave thanks for providing the code to us, i would like to know if you have implemented the moisture sensor into your code. I do have a MiFlora setup already having this value to my HA setup and i suppose i should include this as a condition to your automation eg if not lower that 35% then to not run the irrigation. but also i would like to have the forecasted rain and delay the schedule, have you done any progress in that front ?

thank you

Hi John, I don’t currently use local moisture sensors for my irrigation system, only weather data. Currently my code uses a combination of actual rainfall on the current day, expected rainfall on current day and % chance of rainfall for current day to decide if watering should occur or not. I use a couple of sliders to set my cut-off limits for those parameters in the lovelace screen so I have an easy way to make changes.

latest code package:

########################################
#
#   This is a full reticulation
#   control package using ESPHOMEYAML
#   as the soleniod control via a NodeMCU
#
########################################

homeassistant:
  customize:
    switch.retic_station_1_valve:
      icon: mdi:water-pump
    switch.retic_station_2_valve:
      icon: mdi:water-pump
    input_boolean.retic_program1_enable:
      icon: mdi:traffic-light
    input_boolean.retic_program2_enable:
      icon: mdi:traffic-light



      
sensor:
  - platform: template    # determine if today is selected as a watering day for program 1
    sensors:
      retic_program1_watering_day:
        entity_id: input_boolean.retic_program1_monday, input_boolean.retic_program1_tuesday, input_boolean.retic_program1_wednesday, input_boolean.retic_program1_thursday, input_boolean.retic_program1_friday, input_boolean.retic_program1_saturday, input_boolean.retic_program1_sunday, sensor.time
        value_template:  >
          {% set sensor_names = [ 'monday', 'tuesday', 'wednesday','thursday','friday','saturday','sunday'] %}
          {% set today_name = sensor_names[now().weekday()] %}
          {% set entity_id = 'input_boolean.retic_program1_'+today_name %}
          {{ is_state(entity_id, 'on') }}

      retic_program2_watering_day:
        entity_id: input_boolean.retic_program2_monday, input_boolean.retic_program2_tuesday, input_boolean.retic_program2_wednesday, input_boolean.retic_program2_thursday, input_boolean.retic_program2_friday, input_boolean.retic_program2_saturday, input_boolean.retic_program2_sunday, sensor.time
        value_template:  >
          {% set sensor_names = [ 'monday', 'tuesday', 'wednesday','thursday','friday','saturday','sunday'] %}
          {% set today_name = sensor_names[now().weekday()] %}
          {% set entity_id = 'input_boolean.retic_program2_'+today_name %}
          {{ is_state(entity_id, 'on') }}







    
input_datetime:
  retic_program1_start_time_1:    # program start time control
    name: Program 1 Start Time 1
    has_date: false
    has_time: true

  retic_program1_start_time_2:
    name: Program 1 Start Time 2
    has_date: false
    has_time: true

  retic_program2_start_time_1:
    name: Program 2 Start Time 1
    has_date: false
    has_time: true

  retic_program2_start_time_2:
    name: Program 2 Start Time 2
    has_date: false
    has_time: true


input_number:
  retic_program1_station1_run_time:   # station run time control
    name: Station 1 Run Time
    min: 0
    max: 30
    step: 1
    icon: mdi:camera-timer

  retic_program1_station2_run_time:
    name: Station 2 Run Time
    min: 0
    max: 30
    step: 1
    icon: mdi:camera-timer

  retic_program2_station1_run_time:
    name: Station 1 Run Time
    min: 0
    max: 30
    step: 1
    icon: mdi:camera-timer

  retic_program2_station2_run_time:
    name: Station 2 Run Time
    min: 0
    max: 30
    step: 1
    icon: mdi:camera-timer  

  actual_rainfall_last_24h:
    name: 'Actual Rainfall Last 24h'  # way of keeping todays rainfall figure saved for calculations tomorrow
    min: 0
    max: 100
#    step: 0.1
    icon: mdi:cup-water
#    unit_of_measurement: mm

  allowable_rain_quantity:
    name: 'Allowed Rain (mm)'  # amount of rain we will allow to fall today and still water the garden
    min: 0
    max: 5
    step: 0.1
    icon: mdi:cup-water
#    unit_of_measurement: mm

  allowable_rain_percentage:  # percentage chance of rain today we will allow today and still water the garden
    name: 'Allowed Rain (%)'
    min: 0
    max: 100
    step: 1
    icon: mdi:water-percent
#    unit_of_measurement: %



input_boolean:
  retic_program1_monday:   # watering day selections for program 1
    name: Monday

  retic_program1_tuesday:
    name: Tuesday

  retic_program1_wednesday:
    name: Wednesday

  retic_program1_thursday:
    name: Thursday
    
  retic_program1_friday:
    name: Friday

  retic_program1_saturday:
    name: Saturday
    
  retic_program1_sunday:
    name: Sunday

  retic_program2_monday:   # watering day selections for program 2
    name: Monday

  retic_program2_tuesday:
    name: Tuesday

  retic_program2_wednesday:
    name: Wednesday

  retic_program2_thursday:
    name: Thursday
    
  retic_program2_friday:
    name: Friday

  retic_program2_saturday:
    name: Saturday
    
  retic_program2_sunday:
    name: Sunday


  retic_program1_enable:   # enable program to run
    name: Enable
  
  retic_program1_start_time1_enable:
    name: Enable
  
  retic_program1_start_time2_enable:
    name: Enable
  
  retic_program2_enable:
    name: Enable

  retic_program2_start_time1_enable:
    name: Enable
  
  retic_program2_start_time2_enable:
    name: Enable

  retic_station_1_run:
    name: Station 1 Run
  
  retic_station_2_run:
    name: Station 2 Run


  retic_rain_parameters_met:   # set to ON if rain today values are below levels set in input_numbers
    name: Rain Parameters Met
    icon: mdi:water
  retic_rain_override:         # set to ON to run retic even if rain parameters are not met
    name: Rain Override
    icon: mdi:water

group:                  # frontend interface setup
  retic_manual:
    control: hidden
    name: 'Manual Control'
    entities:
      - switch.retic_station_1_valve
      - switch.retic_station_2_valve
  
  retic_program1:
    control: hidden
    name: 'Program 1'
    entities:
      - input_boolean.retic_program1_enable
      - script.retic_program1_run
      - input_datetime.retic_program1_start_time_1
      - group.retic_program1_watering_days
      - group.retic_program1_run_times
    
  retic_program2:
    control: hidden
    name: 'Program 2'
    entities:
      - input_boolean.retic_program2_enable
      - script.retic_program2_run
      - input_datetime.retic_program2_start_time_1
      - group.retic_program2_watering_days
      - group.retic_program2_run_times

  retic_program1_watering_days:
    control: hidden
    name: 'Watering days'
    icon: mdi:calendar-multiple-check
    entities:
      - input_boolean.retic_program1_monday
      - input_boolean.retic_program1_tuesday
      - input_boolean.retic_program1_wednesday
      - input_boolean.retic_program1_thursday
      - input_boolean.retic_program1_friday
      - input_boolean.retic_program1_saturday
      - input_boolean.retic_program1_sunday

  retic_program2_watering_days:
    control: hidden
    name: 'Watering days'
    icon: mdi:calendar-multiple-check
    entities:
      - input_boolean.retic_program2_monday
      - input_boolean.retic_program2_tuesday
      - input_boolean.retic_program2_wednesday
      - input_boolean.retic_program2_thursday
      - input_boolean.retic_program2_friday
      - input_boolean.retic_program2_saturday
      - input_boolean.retic_program2_sunday

  retic_program1_run_times:
    control: hidden
    name: 'Run times'
    icon: mdi:camera-timer
    entities:
      - input_number.retic_program1_station1_run_time
      - input_number.retic_program1_station2_run_time

  retic_program2_run_times:
    control: hidden
    name: 'Run times'
    icon: mdi:camera-timer
    entities:
      - input_number.retic_program2_station1_run_time
      - input_number.retic_program2_station2_run_time


automation:
  - alias: Save last 24h rainfall figure    # save the rainfall figure to an input_number to use later
    initial_state: 'on'
    trigger:
      - platform: time
        at: "08:50:00"
    action:
      - service: input_number.set_value
        data_template:
          entity_id: input_number.actual_rainfall_last_24h
          value: "{{ states('sensor.bom_perth_rain_today') }}"


  - alias: Check rain parameters     # check that todays rain doesnt need to disable the retic from running   ### LOOK AT CHANGING THIS TO A BINARY_SENSOR TEMPLATE
    initial_state: 'on'
    trigger:
      - platform: template
        value_template: "{{ states('sensor.time') == ((states.input_datetime.retic_program1_start_time_1.attributes.timestamp - 600) | int | timestamp_custom('%H:%M', False)) }}"
      - platform: template
        value_template: "{{ states('sensor.time') == ((states.input_datetime.retic_program1_start_time_2.attributes.timestamp - 600) | int | timestamp_custom('%H:%M', False)) }}"
      - platform: template
        value_template: "{{ states('sensor.time') == ((states.input_datetime.retic_program2_start_time_1.attributes.timestamp - 600) | int | timestamp_custom('%H:%M', False)) }}"
      - platform: template
        value_template: "{{ states('sensor.time') == ((states.input_datetime.retic_program2_start_time_2.attributes.timestamp - 600) | int | timestamp_custom('%H:%M', False)) }}"
      - platform: state
        entity_id: input_number.allowable_rain_quantity
      - platform: state
        entity_id: input_number.allowable_rain_percentage
      - platform: time_pattern
        minutes: '/30'

    action:

      - service_template: >
          input_boolean.turn_{{'on' if states('sensor.bom_perth_rain_today') <= states('input_number.allowable_rain_quantity') and 
                                       states('sensor.bom_perth_forecast_chance_of_rain_0') <= states('input_number.allowable_rain_percentage')  else 'off'}}
        entity_id: input_boolean.retic_rain_parameters_met



  - alias: Reticulation Run Program 1     # start program 1 at designated time if it is enabled and today is selected as a watering day
    initial_state: 'on'
    trigger:
      - platform: template
        value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program1_start_time_1.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
      - platform: template
        value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program1_start_time_2.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
    condition:
      - condition: state
        entity_id: input_boolean.retic_program1_enable
        state: 'on'
      - condition: state
        entity_id: sensor.retic_program1_watering_day
        state: 'True'
      - condition: or
        conditions:
          - condition: and
            conditions:
              - condition: template
                value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program1_start_time_1.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
              - condition: state
                entity_id: input_boolean.retic_program1_start_time1_enable
                state: 'on'
          - condition: and
            conditions:
              - condition: template
                value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program1_start_time_2.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
              - condition: state
                entity_id: input_boolean.retic_program1_start_time2_enable
                state: 'on'
      - condition: or
        conditions:
          - condition: state
            entity_id: input_boolean.retic_rain_parameters_met
            state: 'on'
          - condition: state
            entity_id: input_boolean.retic_rain_override
            state: 'on'
    action:
      - service: script.turn_on
        entity_id: script.retic_program1_run

  - alias: Reticulation Run Program 2     # start program 2 at designated time if it is enabled and today is selected as a watering day
    initial_state: 'on'
    trigger:
      - platform: template
        value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program2_start_time_1.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
      - platform: template
        value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program2_start_time_2.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
    condition:
      - condition: state
        entity_id: input_boolean.retic_program2_enable
        state: 'on'
      - condition: state
        entity_id: sensor.retic_program2_watering_day
        state: 'True'
      - condition: or
        conditions:
          - condition: and
            conditions:
              - condition: template
                value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program2_start_time_1.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
              - condition: state
                entity_id: input_boolean.retic_program2_start_time1_enable
                state: 'on'
          - condition: and
            conditions:
              - condition: template
                value_template: "{{ states('sensor.time') == (states.input_datetime.retic_program2_start_time_2.attributes.timestamp | int | timestamp_custom('%H:%M', False)) }}"
              - condition: state
                entity_id: input_boolean.retic_program2_start_time2_enable
                state: 'on'
      - condition: or
        conditions:
          - condition: state
            entity_id: input_boolean.retic_rain_parameters_met
            state: 'on'
          - condition: state
            entity_id: input_boolean.retic_rain_override
            state: 'on'




    action:
      - service: script.turn_on
        entity_id: script.retic_program2_run

  - alias: Reticulation Station 1 Run
    initial_state: 'on'
    trigger:
      platform: state
      entity_id: input_boolean.retic_station_1_run
    action:
      - service_template: >
          {% if is_state('input_boolean.retic_station_1_run', 'on') %}
            script.retic_station_1_run
          {% else %}
            script.retic_station_1_stop
          {% endif %}
      
  - alias: Reticulation Station 2 Run
    initial_state: 'on'
    trigger:
      platform: state
      entity_id: input_boolean.retic_station_2_run
    action:
      - service_template: >
          {% if is_state('input_boolean.retic_station_2_run', 'on') %}
            script.retic_station_2_run
          {% else %}
            script.retic_station_2_stop
          {% endif %}

  - alias: Reticulation Controller Offline Alert
    initial_state: 'on'
    trigger:
      platform: state
      entity_id: binary_sensor.retic_controller_status
      to: 'off'
      for:
        minutes: 5
    action:
      - service: notify.pushbullet
        data:
          message: 'Retic Controller Offline!'


script:
  retic_program1_run:             #run retic program 1 through each station for selected time
    alias: Program 1 Run
    sequence:
      - service: switch.turn_on
        data:
          entity_id: switch.retic_station_1_valve
      - delay: "00:00:01"
      - service: switch.turn_on
        data:
          entity_id: switch.retic_bore_control
      - delay: "00:{{ states('input_number.retic_program1_station1_run_time')|int }}:00"
      - service: switch.turn_off
        data:
          entity_id: switch.retic_station_1_valve
      - service: switch.turn_on
        data:
          entity_id: switch.retic_station_2_valve
      - delay: "00:{{ states('input_number.retic_program1_station2_run_time')|int }}:00"
      - service: switch.turn_off
        data:
          entity_id: switch.retic_bore_control
      - delay: "00:00:01"
      - service: switch.turn_off
        data:
          entity_id: switch.retic_station_2_valve
      
  retic_program2_run:             #run retic program 2 through each station for selected time
    alias: Program 2 Run
    sequence:
      - service: switch.turn_on
        data:
          entity_id: switch.retic_station_1_valve
      - delay: "00:00:01"
      - service: switch.turn_on
        data:
          entity_id: switch.retic_bore_control
      - delay: "00:{{ states('input_number.retic_program2_station1_run_time')|int }}:00"
      - service: switch.turn_off
        data:
          entity_id: switch.retic_station_1_valve
      - service: switch.turn_on
        data:
          entity_id: switch.retic_station_2_valve
      - delay: "00:{{ states('input_number.retic_program2_station2_run_time')|int }}:00"
      - service: switch.turn_off
        data:
          entity_id: switch.retic_bore_control
      - delay: "00:00:01"
      - service: switch.turn_off
        data:
          entity_id: switch.retic_station_2_valve

  retic_station_1_run:
    alias: Station 1 Run
    sequence:
      - service: switch.turn_on
        data:
          entity_id: switch.retic_station_1_valve
      - delay: "00:00:01"
      - condition: state
        entity_id: switch.retic_station_1_valve
        state: 'on'
      - service: switch.turn_on
        data:
          entity_id: switch.retic_bore_control
  
  retic_station_1_stop:
    alias: Station 1 Stop
    sequence:
      - service: switch.turn_off
        data:
          entity_id: switch.retic_bore_control
      - delay: "00:00:01"
      - condition: state
        entity_id: switch.retic_bore_control
        state: 'off'
      - service: switch.turn_off
        data:
          entity_id: switch.retic_station_1_valve

  retic_station_2_run:
    alias: Station 2 Run
    sequence:
      - service: switch.turn_on
        data:
          entity_id: switch.retic_station_2_valve
      - delay: "00:00:01"
      - condition: state
        entity_id: switch.retic_station_2_valve
        state: 'on'
      - service: switch.turn_on
        data:
          entity_id: switch.retic_bore_control
  
  retic_station_2_stop:
    alias: Station 2 Stop
    sequence:
      - service: switch.turn_off
        data:
          entity_id: switch.retic_bore_control
      - delay: "00:00:01"
      - condition: state
        entity_id: switch.retic_bore_control
        state: 'off'
      - service: switch.turn_off
        data:
          entity_id: switch.retic_station_2_valve

thank you for uploading your updated code, i have already changed the old one and incorporated my MiFlora moisture sensors , and i have everything setup , for me the actual rainfall input (actual_rainfall_last_24h) won’t be used since i check the moisture before running the automation . thank you for all your help and ideas.

Hi @sparkydave, thanks for sharing your code. I have about 11 watering zones in total for font and back yards, and so I expanded your code for the extra zones which wasn’t hard. For one of the watering programs however, I have a bunch of zones which don’t get used. Because of the structure of the code, these unused zones get pulsed for one second each as the script iterates through each zone until it gets to a zone which is used for x number of minutes. Maybe it’s not a big deal and just a ‘nice to have’, but feels less than ideal to have unused zones pulsed on for that second, especially when there’s quite a few (at least it sounds quite odd when you’re outside). I’ve been trying to add a condition where unused zones get skipped altogether but haven’t managed to get that working. I guess maybe if I removed the 1 second delay between zones it might go away. Any suggestions?

Definitely. The delay I have is to ensure the valve is definitely open before the bore is started. If you don’t have a bore you can certainly remove this. In reality I don’t need it either since the bore is going to take a few seconds to build up pressure anyway.

@sparkydave I had another look at the code and remembered this is happening without any 1 second delays; as I didn’t duplicate that part. So even though the time is set to 0, the valves come on for a split second, and that’s why I was trying to put a condition in to skip unused valves. I think this is because there is the command to turn on the valve and this command gets executed no matter what, and then there is some inherent tiny delay between executing the next command which is the delay command before the valve is turned off. So it’s not a 1 second delay, it’s something in the order of maybe 100 milliseconds, but the valves do come on.

Yep, it’s definitely a flaw in my code. Unfortunately you can only have one condition=false in a script and then everything after that is ignored. What I wish HA would allow is ‘nested’ blocks of code where a condition only applies to that block and the script continues with the rest of the code either way

Oh yes please!
It’s been a pet hate of mine since almost day one of using it, that HA can’t do this

I’ve just set up a smart irrigation controller using a 4 channel relay module with an ESP8266 chip running Tasmota and Home Assistant. Scheduling is informed by Google calendar entries. I’ve written a blog post here with more details.

3 Likes

Hi @srk23. I’m trying to solve the same problem (switching between tap water and rain collecting tanks). Did you arrive to some sensible solution?

I never quite got round to it last year…will be a project for this spring.

I think I came to the conclusion that it might require a water butt pump to provide enough pressure. It might be possible to switch between the two and just fire up the pump when there is water in the butt?

You might require WHAT?? :rofl: SCNR

I didn’t make it up - they exist!