Irrigation Unlimited Integration

Hello,
I am new to Home Assistant and have installed and run irrigation unlimited.
I would need some input on the configuration.
I have a system with 6 zones and currently I use all 6 zones as a schedule 30 minutes before sunrise.
Now I would like to diversify the schedules as follows:
Zone 1 and 6 always 30’ before sunrise on alternate days
Zone 2,3,4,5 always 30’ before sunrise every day 2 times a day.
Could you help me with the configuration?

Thanks

The best thing you can do at this stage is to read the very comprehensive documentation.

Is there a way to repeat a sequence with a delay between the sequence instead of a delay between the zones?

I have new grass in the back yard and I would like to water all zones there back to back and repeat that sequence every 4 hours.

Add a dummy zone to the end of the sequence.

Thanks. I will try that.

FYI: Here’s an issue I ran into using a history_stats sensors when watering spans a day.

I’m trying to track daily water usage by tracking how long each valve is on. But, at times I’m getting very high usage number that don’t match the physical water meter. I tracked down why.

I created history_stats sensors like this to track total time on during each day:

- platform: history_stats
  name: History Sprinkler 26
  entity_id: switch.sprinkler_controller_3_2
  unique_id: sprinkler_26
  state: "on"
  type: time
  start: "{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}"
  end: "{{ now() }}"

As it turned out, that sprinkler valve turned off at midnight, but the history stats sensor kept on adding up the time, even though the entity had turned off. (Sounds like a bug in the HA history_stats code?)

Below, you can see the valve (switch.sprinkler_controller_3_2) turned on at 23:45:05 and off at 2024-06-13 00:00:00.

Immediately after that you can see that the sensor.history_sprinkler_26 was reset to zero because of the time span on the sensor’s configuration (above).

But, the history stats sensor (sensor.history_sprinkler_26) just kept on adding on time as if the valve was still on.

sqlite> select state_id,m.entity_id, state, DATETIME(last_updated_ts, 'unixepoch', 'localtime') as last_updated, DATETIME(last_reported_ts, 'unixepoch', 'localtime') as last_reported from states s join states_meta m on s.metadata_id = m.metadata_id where (m.entity_id = 'sensor.history_sprinkler_26' or m.entity_id = 'switch.sprinkler_controller_3_2') and state_id >= 19563057 order by last_updated,1 limit 100;
state_id  entity_id                        state                last_updated         last_reported
--------  -------------------------------  -------------------  -------------------  -------------------
19563057  switch.sprinkler_controller_3_2  on                   2024-06-12 23:45:05  2024-06-12 23:45:05
19563112  sensor.history_sprinkler_26      0.00533106499248081  2024-06-12 23:45:24  2024-06-12 23:45:24
19563113  switch.sprinkler_controller_3_2  unavailable          2024-06-12 23:45:24  2024-06-12 23:45:24
19563125  sensor.history_sprinkler_26      0.00516385416189829  2024-06-12 23:45:27  2024-06-12 23:45:27
19563126  switch.sprinkler_controller_3_2  on                   2024-06-12 23:45:27  2024-06-13 00:00:00
19563240  sensor.history_sprinkler_26      0.021830520828565    2024-06-12 23:46:27  2024-06-12 23:46:27
19563350  sensor.history_sprinkler_26      0.0384971874952316   2024-06-12 23:47:27  2024-06-12 23:47:27
19563456  sensor.history_sprinkler_26      0.0554416319396761   2024-06-12 23:48:28  2024-06-12 23:48:28
19563559  sensor.history_sprinkler_26      0.0721082986063427   2024-06-12 23:49:28  2024-06-12 23:49:28
19563655  sensor.history_sprinkler_26      0.0887749652730094   2024-06-12 23:50:28  2024-06-12 23:50:28
19563760  sensor.history_sprinkler_26      0.105441631939676    2024-06-12 23:51:28  2024-06-12 23:51:28
19563859  sensor.history_sprinkler_26      0.122108298606343    2024-06-12 23:52:28  2024-06-12 23:52:28
19563961  sensor.history_sprinkler_26      0.138774965273009    2024-06-12 23:53:28  2024-06-12 23:53:28
19564062  sensor.history_sprinkler_26      0.155441631939676    2024-06-12 23:54:28  2024-06-12 23:54:28
19564153  sensor.history_sprinkler_26      0.172108298606343    2024-06-12 23:55:28  2024-06-12 23:55:28
19564248  sensor.history_sprinkler_26      0.188774965273009    2024-06-12 23:56:28  2024-06-12 23:56:28
19564354  sensor.history_sprinkler_26      0.205441631939676    2024-06-12 23:57:28  2024-06-12 23:57:28
19564458  sensor.history_sprinkler_26      0.222108298606343    2024-06-12 23:58:28  2024-06-12 23:58:28
19564587  sensor.history_sprinkler_26      0.238774965273009    2024-06-12 23:59:28  2024-06-12 23:59:28
19564639  switch.sprinkler_controller_3_2  off                  2024-06-13 00:00:00
19564642  sensor.history_sprinkler_26      0.0                  2024-06-13 00:00:00  2024-06-13 00:00:00
19564754  sensor.history_sprinkler_26      0.0166666666666667   2024-06-13 00:01:00  2024-06-13 00:01:00
19564865  sensor.history_sprinkler_26      0.0333333333333333   2024-06-13 00:02:00  2024-06-13 00:02:00
19564967  sensor.history_sprinkler_26      0.05                 2024-06-13 00:03:00  2024-06-13 00:03:00
19565070  sensor.history_sprinkler_26      0.0666666666666667   2024-06-13 00:04:00  2024-06-13 00:04:00
19565164  sensor.history_sprinkler_26      0.0833333333333333   2024-06-13 00:05:00  2024-06-13 00:05:00
19565253  sensor.history_sprinkler_26      0.1                  2024-06-13 00:06:00  2024-06-13 00:06:00
19565347  sensor.history_sprinkler_26      0.116666666666667    2024-06-13 00:07:00  2024-06-13 00:07:00
19565442  sensor.history_sprinkler_26      0.133333333333333    2024-06-13 00:08:00  2024-06-13 00:08:00
19565521  sensor.history_sprinkler_26      0.15                 2024-06-13 00:09:00  2024-06-13 00:09:00

And still going…

19598492  sensor.history_sprinkler_26      9.90027777777778     2024-06-13 09:54:01  2024-06-13 09:54:01
19598545  sensor.history_sprinkler_26      9.91694444444444     2024-06-13 09:55:01  2024-06-13 09:55:01
19598601  sensor.history_sprinkler_26      9.93361111111111     2024-06-13 09:56:01  2024-06-13 09:56:01
19598664  sensor.history_sprinkler_26      9.95027777777778     2024-06-13 09:57:01  2024-06-13 09:57:01
19598718  sensor.history_sprinkler_26      9.96694444444444     2024-06-13 09:58:01  2024-06-13 09:58:01
19598776  sensor.history_sprinkler_26      9.98361111111111     2024-06-13 09:59:01  2024-06-13 09:59:01
19598832  sensor.history_sprinkler_26      10.0002777777778     2024-06-13 10:00:01

There’s other oddities I’m running into using history stats so I might use an automation and manually track usage that way.

In order to track daily, monthly and yearly water usage for each circuit (16 total) here is what i did.
First of all define a template sensor based on volume attribute of each specific zone:

    - unique_id: irrigation_volume_id2
      name: '{{ "irrigation_volume_id2" if this.state == "unknown" else "Irrigation Consommation Kfé François" }}'
      state: '{{state_attr("binary_sensor.irrigation_unlimited_c1_z2","volume")}}'
      state_class: measurement
      unit_of_measurement: "l"

You may have noticed that volume attribute value is for one watering cycle, in other words it crosses day boundary.

Then define water meters accordingly to get daily, monthly and yearly consumptions:

  water_meter_id2_day:
    name: Consommation eau Kfé francois
    source: sensor.irrigation_volume_id2
    unique_id: "water_meter_id2_day"
    cycle: daily
  water_meter_id2_month:
    source: sensor.irrigation_volume_id2
    unique_id: "water_meter_id2_month"
    cycle: monthly
  water_meter_id2_year:
    source: sensor.irrigation_volume_id2
    unique_id: "water_meter_id2_year"
    cycle: yearly

I hope it helps, let us know

hi sorry I’ve tried to copy the code for this graphs but I see a blank graph.


my code is

type: custom:apexcharts-card
header:
  show: true
  title: Watering timeline
  show_states: false
graph_span: 10d
span:
  start: day
  offset: '-7day'
all_series_config:
  type: column
  group_by:
    duration: 1d
    func: sum
    fill: 'null'
  show:
    as_duration: minute
now:
  show: true
  label: Today
series:
  - entity: binary_sensor.irrigation_unlimited_c1_z1
    data_generator: |
      return entity.attributes.timeline.map((item) => {
        const sd = new Date(item.start);
        const ed = new Date(item.end);
        return [sd, (ed - sd) / 60000];
      });
  - entity: binary_sensor.irrigation_unlimited_c1_z3
    data_generator: |
      return entity.attributes.timeline.map((item) => {
        const sd = new Date(item.start);
        const ed = new Date(item.end);
        return [sd, (ed - sd) / 60000];
      });
  - entity: binary_sensor.irrigation_unlimited_c1_z2
    data_generator: |
      return entity.attributes.timeline.map((item) => {
        const sd = new Date(item.start);
        const ed = new Date(item.end);
        return [sd, (ed - sd) / 60000];
      });
yaxis:
  - decimals: 0
    apex_config:
      title:
        text: minutes
apex_config:
  tooltip:
    enabled: true
    x:
      format: dd MMM

Hi,
Using your add on for 2 years now. Great piece of software!
Another add on for home assistant is EMHASS, an energy management system. It would be a nice feature to be able to use EMHASS output to set the time for an irrigation sequence.
An idea?

This appears to be an awesome tool! Great work @rgc99!

I have a basic setup working -

  1. One controller
  2. 8 zones with min and max durations specified
  3. 1 sequence which I am thinking is the definition of a playlist for watering my 8 zones one by one. Currently my irrigation system controller will only allow one zone to be ON at one time.

This workes great. However, I am now trying to integrate this with my existing HASmartIrrigation (version 2) setup which provides me with an updated duration for each zone based on weather. And so far, I am stuck here.

I did come across this repo that @kolia created - GitHub - Kolia56/irrigation: Home assistant: Irrigation unlimited and Smart irrigation integration. However, I am still not understanding the logic behind how to best achieve the workflow.

Ideally, one of the schedules should be all zones getting watered based on duration specified by HASmartIrrigation sensors everyday at 3AM. The strength of irrigation_unlimited to me is going to come from the ability to create sequences/schedules on the fly!

I also see that the author of HASmartIrrigation posted some blueprints - HAsmartirrigation/blueprints at master · jeroenterheerdt/HAsmartirrigation · GitHub that can maybe help with what I want to achieve. But I really first want to understand how the logic should work for my case. Can someone please comment to explain how these two can work together?

I will not upgrade to Smart irrigation v2, since I get ET from my Davis VP2 and new version does not add anything usefull in my specific case. So I’m currently running 0.8. If you wish to better understand what I did, you’d better select 0.8 tag on HA Smart Irrigation (HASI) github to access the related readme.
I defined how much watering I need for the lawn based on this article.
I empirically defined a nominal budget watering time for all other zones that are drip lines that turns to be correct based on experience.
2’ before watering sequence starts an automation is fired asking HASI to compute watering time for the lawn. In other words I do not let HASI decide when it computes this value.
1’ before watering sequence starts, controller is adjusted accordingly with the value returned above to nominal watering time (2600 secondes or 40 minutes). It is caped to 150% and if less that 5% it is set to 0, hence there won’t be no watering.
At the end of the sequence, it watering occurred, bucket is reset, ie set to 0.

  - id: c6b40384-a7bd-4cf9-82f8-fc07f15905e5
    alias: Smart Irrigation adjustment
    description: Adjust watering times based on ET - Bucket reset
    trigger:
      - platform: template
        value_template: >
          {{ now().timestamp() | timestamp_custom('%H:%M') 
            == (state_attr('input_datetime.watering_s1_start', 'timestamp') - 120) | timestamp_custom('%H:%M', false) }}
        id: watering_duration_compute
      - platform: template
        value_template: >
          {{ now().timestamp() | timestamp_custom('%H:%M') 
            == (state_attr('input_datetime.watering_s1_start', 'timestamp') - 60) | timestamp_custom('%H:%M', false) }}
        id: watering_duration_set
      - platform: event
        event_type: irrigation_unlimited_finish
        id: "Finished"        
    # condition:
    #   condition: and
    #   conditions:
    #     - "{{ states('sensor.smart_irrigation_id7_daily_adjusted_run_time') | float(-1) >= 0 }}"
    condition: >
      {{has_value("sensor.smart_irrigation_id7_daily_adjusted_run_time")}}
    action:
      - choose:
        - conditions:
          - condition: trigger
            id: watering_duration_compute
          sequence:
          - service: smart_irrigation.smart_irrigation_id7_calculate_daily_adjusted_run_time
            data: {}
          # - service: notify.persistent_notification
          #   data:
          #     title: "Irrigation - calcul du temps d'arrosage"
          #     message: |
          #       Time: {{ as_local(now()).strftime('%c') }}            
        - conditions:
          - condition: trigger
            id: watering_duration_set
          sequence:
          - service: input_text.set_value
            target: 
              entity_id: input_text.smart_irrigation_id7_adjust_time
            data: # 2600 secondes = 00:40:00 nominal duration for lawn watering
            # all other circuits (drip line) are proportional to lawn watering
              value: >
                {{ timedelta(seconds=states('sensor.smart_irrigation_id7_daily_adjusted_run_time') | int(0)) }} - 
                {{(states('sensor.smart_irrigation_id7_daily_adjusted_run_time')| int(0) / 2600) | multiply (100) | round (0) }}%
          # - service: notify.persistent_notification
          #   data:
          #     title: "Irrigation - application du nouveau temps d'arrosage"
          #     message: |
          #       Time: {{ as_local(now()).strftime('%c') }}            
          - condition: state
            entity_id: input_boolean.irrigation_duration_smart
            state: "on"
          - service: input_number.set_value
            target:
              entity_id: input_number.arrosage_variation
            data:
              value: >
                {% set pct = (states('sensor.smart_irrigation_id7_daily_adjusted_run_time')| int(0) / 2600) | multiply (100) | round (0) %}
                {% if pct >= 150 %}
                  150
                {% elif pct <= 5 %}
                  0
                {% else %}
                  {{pct}}
                {% endif %}
        - conditions:
          - condition: and
            conditions:
              - condition: trigger
                id: Finished
              - condition: template
                value_template: >
                  {{trigger.event.data.schedule.index is integer and trigger.event.data.schedule.index + 1 == 1 }}
              - condition: numeric_state
                above: '0'
                entity_id: sensor.smart_irrigation_id7_daily_adjusted_run_time
          sequence:
          - service: smart_irrigation.smart_irrigation_id7_reset_bucket
          - service: notify.persistent_notification
            data:
              title: "Irrigation - Bucket reset"
              message: |
                Time: {{ as_local(now()).strftime('%c') }}             

    mode: single