rgc99 / irrigation_unlimited

♒Irrigation controller for Home Assistant
MIT License
332 stars 49 forks source link

Suspend does not suspend irrigation time/duration: add pause/continue or freeze/unfreeze to zones, sequences, controllers #142

Closed evercape closed 6 months ago

evercape commented 1 year ago

Describe the bug When using the suspend function in the companion card (or via the service call), although the controller stops (and closes the valves) the actual timer keeps on running. When resume, it does not resume at the run time when suspended.

To Reproduce Steps to reproduce the behavior:

  1. start controller with 1 zone set duration 30min
  2. run either manually or at test time
  3. after 5 min the timer shows 00:25:00 (pending granularity)
  4. press suspend for 00:03:00 so three minutes. as expected, controller suspends and valve of zone closes.
  5. about 3 minutes later the controller resumes, valve opens but the timer shows 00:22:00 instead of 00:25:00.

Expected behavior What I am looking for is effectively a pause/resume function like in a song/playlist. the resume should continue at the time where stopped.

My (admittedly very personal) use case is that all irrigation zones are powered by a borehole pump, which also fills domestic water tank which requires re-filling at completely random times (pending consumption). pressure is not enough to run fill and irrigation at the same time, so I would have to stop the irrigation schedule/sequence whilst the tank is filling and then resume, however, without losing the time that is dedicated to the specific zone that is currently irrigated at the time I want it the controller to be temporarily suspended .

Additional context On that note, the enable/disable function shows similar behaviour: When the controller is manually disabled and later enabled again, it continues at a progressed time.

I think it would be great to have a "proper" playlist pause & resume function if that is technically possible.

My alternative resolution is to calculate the "max time required to fill the tank" and to suspend with that max time.

However, there are plenty of other use case scenarios to temporarily suspend and to resume with flexible time, without losing out on irrigation time.

Thanks for one of the most amazing integrations I have ever been exposed on Home Assistant.

Rgds Martin

evercape commented 1 year ago

I been playing around the suspend function and what I hope it would be able to achieve: all playlists pause, and resume.

Unfortunately, my proposed workaround above is not working, since during suspension time the "clock keeps on ticking".

So I tried the following:

  1. service call adjust time +20 minutes
  2. suspend for 20 minutes.

This works but only on controller level, and not on "system" level ie pause any controller that might run in the next 20 minutes.

One would have to do some more complex scripting on the lines of:

  1. find out which controller is running, or running with in the next 20 minutes (or whatever time it takes to fill borehole pump, or whatever time one requires the full system to be "on break").
  2. if that time is <20 minutes then adjust 20 minutes minus that time, and then suspend by the same time. Also running into problems if the first zone is less than that period of time.

All in all, it seems rather complex to do this in YAML or templating.

Would it not be possible to create a "proper" playlist pause & resume function in python that becomes part of irrigation unlimited on system, controller and zone level, effectively pushing out everything that is due to happen by the time of the pause?

Thanks Martin

rgc99 commented 1 year ago

The missing time is an unintended side effect of the enable/disable function. Suspend is really a timed disable. It was envisaged that disable was to take the zone out of commission perhaps for maintenance, end of season, long period of rain etc. The disable would be issued when the system was not operating or if it was then to take effect after the cycle had completed. This is more or less "stop after the current has finished".

Would a pause just affect a running cycle? What happens if the system is paused and a schedule is due to start? If left long enough schedules could start to pile up.

evercape commented 1 year ago

Hi Robert, thanks for responding - all valid questions.

So we have the following - can you pls advice if my interpretation is correct?

Enable/Disable - Works on Controller, Zone, Sequence. Same as Suspend but with unlimited time (until manual interaction).

Suspend - Works on Controller, Zone, Sequence. Same as Cancel but with timer to start again.

Cancel - Works on Controller, Zone but not on sequence.

Adjust - Works on Controller, Zone, Sequence. Can be negative.

In all cases, the clock keeps on running, ie even if something is stopped, cancelled, disabled, the clock continues which means that zone/these zones during pause will not get watered.

I somehow still feel that a pause & resume would make sense, for instance due to irregular times relating to maintenance, garden service, pressure drops, electrical mains issues, other functions like tank filling.

From a programming point of view, if one wanted to either build this functionality, I think the following needs to be taken into consideration:

1) if there is a virtual internal clock, pause it and resume so the clock (independent from system time) just changes.

2) Alternatively upon resumption take a measurement of the down time and adjust those zones that were missed. Admittedly, sequenced starting times will shift, and maybe some scheduled starting times if the start time falls in the window of the down time.

3) Maybe the pause & resume function could have a parameter that prevents from shifting beyond hours, or beyond midnight, or...

Food for thought.

Coming back to my very specific requirement to fill our water tanks, I can only come up with the tank filling being a static zone and then slotting it at certain times e.g. morning, lunch, afternoon into existing irrigation scheduled sequences. I do know the time it take to refill, and have statistical data of consumption.

Worst case the tank still requires filling, and then that one zone that might be affected will have to close. Do you agree or are there any other/better solutions?

The other scenario that I would like to build into functionality is a pressure sensor for the main borehole supply line. Upon drop of pressure (ie someone manually using water through taps), pause & resume irrigation_unlimited. I think this functionality would definitely be a good use case for a farm or small holding (we live on one). Any fluctuating pressure will also reduce the volume output (which I now measure via the more parameter. Again, any more ideas or thoughts on this use case?

Lastly, let me know if you ever need help with translation. Happy to do the German one.

Thanks Martin

rgc99 commented 1 year ago

For the record enable/disable/suspend/adjust also work on sequence zones.

In the beginning there was a running clock and this was the basis for the granularity: setting. The lower the setting, the more CPU it required but allowed smaller time increments. Now there is no clock instead waking up when something needs to be done. Granularity is fixed at one second and runs 10x faster. Runs are allocated and placed in a queue kind of like an appointment diary.

What needs to be done is keep track of the down time during a pause and extend out the end time. Probably not so difficult for running zones but gets a little complicated for schedules that come into play during a pause. If left in the pause state they would start but never finish. There could be a lot of runs waiting in the wings. A resume would probably cause the whole system to come on as the logger jam is cleared. As you suggest some sort of end of life might be a solution.

You might be interested in another FR. Here the goal is to track water usage and adjust the run time to meet a volume requirement. We are currently tracking volume usage which looks promising. More to consider...

Have fun Robert

evercape commented 1 year ago

Thanks Robert, the water volume driven duration is obviously the correct way to go for any watering system, so I fully agree with this approach.

I will order a Sensus meter with either KNX or probably better ESPHome or modbus connectivity so that I have very accurate data, and will add that to the borehole and then figure out what the expected throughput is per zone.

On another note, is there anyway that your system (within python) is calculating a future timeline of controller/zone/start time or sequenced schedule, and if so, output this as JSON onto the Irrigation Unlimited Controller helper entity?

If not, I obviously have access to my own configuration's raw data and should be able to compute myself. Just don't want to redo if you have done it elegantly already. Thanks Martin

rgc99 commented 1 year ago

In the zone entity you can turn on the timeline feature. In each zone entity you will get a timeline attribute which is a list of past, present and future runs. Find some info here. Take a look at the code behind the markdown card to get an idea on how to process the data. See if that is the type of information you are looking for.

evercape commented 11 months ago

Hi Robert - just to let you know that I haven't looked into this, but will do so in due course. Been busy learning a bit of Python and did one custom integration (with a bit of help) in order to get better at HA related coding. Once I looked more into the timeline object will let you know. I still think that volume as targets (instead of time) is the way to go. Cheers Martin

evercape commented 10 months ago

Referencing Robert's comment in this issue which deals with the pause/resume or freeze/unfreeze of sequences, zones etc:

Sequences now have an associated entity i.e. binary_sensor.irrigation_unlimited_c1_s1. There is an experimental service call pause on this new entity. Turned out to be more of a freeze rather than a pause. First call will pause and the second call will resume, toggle like behaviour. There are no other options on this service call, just send it to the entity. It's more of a freeze because the state remains as is. If it is on it will remain so until another pause service call is issued. In my mind a pause should turn off any running zones (including master) and wait. Code is ready for release. Feel free to update from the repository and let me know of any issues.

Hi Robert,

Thanks for implementing this.

I have updated from master repository (via HACS) and can see the new service call as well as the new sequence entities.

Feedback:

1) The service call pause does not yet permit selecting sequences or entities from the UI. See screenshot ui_pause

2) I started a zone manually (since I missed this morning's time slot for a sequence) and tried to then run the service call however that did not stop it. I assume it might be because a zone entity was run manually. See log files below that confirm that the manual run works but it seems to run on sequence 0:

2024-01-19 11:03:22.396 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-01-19 11:03:22] service: manual_run, controller: 1, zone: 1, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c1_z1"], "time": "0:45:00"}
2024-01-19 11:03:23.001 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:03:23] controller: 1, zone: 0, state: 1
2024-01-19 11:03:23.001 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:03:23] controller: 1, zone: 1, state: 1, data: 1.0.0.0.0

Maybe consider for manual runs of zones something like sequence 0 or sequence M ?

3) Then I did a manual run for a sequence via UI: followed by service call pause:

alias: test IU pause on sequence 1
sequence:
  - service: irrigation_unlimited.pause
    metadata: {}
    data:
      entity_id: binary_sensor.irrigation_unlimited_c1_s1
mode: single

here are the logs: 2024-01-19 11:09:15.434 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-01-19 11:09:15] service: manual_run, controller: 1, zone: 0, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c1_m"], "sequence_id": 1, "time": "0:10:00"} 2024-01-19 11:09:16.070 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:09:16] controller: 1, zone: 0, state: 1 2024-01-19 11:09:16.070 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:09:16] controller: 1, zone: 1, state: 1, data: 1.0.1.1.1 2024-01-19 11:10:22.001 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:10:22] controller: 1, zone: 2, state: 1, data: 2.0.1.2.2 2024-01-19 11:10:24.002 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:10:24] controller: 1, zone: 1, state: 0 2024-01-19 11:10:24.035 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-01-19 11:10:24] service: cancel, controller: 1, zone: 1, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c1_z1"]} 2024-01-19 11:10:57.348 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-01-19 11:10:57] service: pause, controller: 1, zone: 0, sequence: 1, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c1_s1"]} 2024-01-19 11:11:51.351 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-01-19 11:11:51] service: pause, controller: 1, zone: 0, sequence: 1, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c1_s1"]} 2024-01-19 11:12:22.001 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:12:22] controller: 1, zone: 3, state: 1, data: 3.0.1.3.2 2024-01-19 11:12:24.001 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:12:24] controller: 1, zone: 2, state: 0 2024-01-19 11:12:24.033 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-01-19 11:12:24] service: cancel, controller: 1, zone: 2, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c1_z2"]} 2024-01-19 11:13:28.002 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:13:28] controller: 1, zone: 1, state: 1, data: 1.0.1.1.2 2024-01-19 11:13:30.002 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-01-19 11:13:30] controller: 1, zone: 3, state: 0 2024-01-19 11:13:30.038 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-01-19 11:13:30] service: cancel, controller: 1, zone: 3, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c1_z3"]}

Tthe sequence icon in the UI changed to the pause icon and the sequence and zone/entity timer increases while being paused (see blue). However, the icon on the actual zone part of the sequence did not change, whilst the timer of the zone increased. however, the irrigation did not stop so the actual switch command was not received by the solenoid. Martin_Testing_–_Home_Assistant

So in a nutshell whatever the pause is doing on sequence seems to work in principle with the icon on sequence. The time increase is 'weird' as it should rather freeze since the UI shows the time remaining, not the end time (which indeed would be an increase).

What is missing is that the sequence.pause service call must be passed down to the zones that part of this sequence.

Hope this makes sense?

I have not yet tested the above on sequences automatically run by the yaml configuration.

My current yaml is pasted below, although I doubt you need it.

Thanks Martin

#IRRIGATION CONTROLLER
  irrigation_unlimited:
    history:
      span: 7
    refresh_interval: 5
    controllers:
      - name: Lawn Areas
        enabled: true
        check_back:
          states: none
        all_zones_config:
          show:
            timeline: true
            config: true
          future_span: 3
        zones:
          - name: "Lawn Berms"
            show:
              timeline: true
            entity_id: switch.g0272_irrigation_lawn_front_of_berms
            user:
              entity_id: switch.g0272_irrigation_lawn_front_of_berms
              type: lawn
              group: g0272
              manifold: Back of Pump Room
              actuator: AKK-0816.02-A
              db_board: Utility Room
          - name: "Lawn Kitchen"
            entity_id: switch.g0273_irrigation_lawn_between_pool_and_kitchen
            user:
              entity_id: switch.g0273_irrigation_lawn_between_pool_and_kitchen
              type: lawn
              group: g0273
              manifold: Back of Pump Room
              actuator: AKK-0816.02-B
              db_board: Utility Room
          - name: "Lawn Pool Tiles"
            entity_id: switch.g0280_irrigation_lawn_along_pool_tiling
            user:
              entity_id: switch.g0280_irrigation_lawn_along_pool_tiling
              type: lawn
              group: g0280
              manifold: West Wall
              actuator: AKS-2016.03-01-A
              db_board: Electric Fence
          - name: "Lawn Guest Patio"
            entity_id: switch.g0386_irrigation_lawn_gh_pool_and_patio
            user:
              entity_id: switch.g0386_irrigation_lawn_gh_pool_and_patio
              type: lawn
              group: g0386
              manifold: GH Septic Tank
              actuator: AKS-2016.03-01-L
              db_board: Electric Fence
          - name: "Lawn Guest Right"
            entity_id: switch.g0391_irrigation_gh_lawn_driveway_right
            user:
              entity_id: switch.g0391_irrigation_gh_lawn_driveway_right
              type: lawn
              group: g0391
              manifold: Pedestrian Gate Ground
              actuator: AKS-2016.03-01-Q
              db_board: Electric Fence
          - name: "Lawn Guest Left"
            entity_id: switch.g0392_irrigation_gh_lawn_driveway_left
            user:
              entity_id: switch.g0392_irrigation_gh_lawn_driveway_left
              type: lawn
              group: g0391
              manifold: Pedestrian Gate Ground
              actuator: AKS-2016.03-01-Q
              db_board: Electric Fence

        sequences:
          - name: "Lawn: Main House"
            duration: "00:15"
            delay: "-00:00:02"
            repeat: 3
            schedules:
              - name: "Lawn 1"
                time: "05:30"
                anchor: start
                weekday: [mon, wed, fri]
                month: [oct, nov, dec, jan, feb, mar, apr]
            zones:
              - zone_id: 1
              - zone_id: 2
              - zone_id: 3
          - name: "Lawn: Guest House"
            delay: "-00:00:02"
            duration: "00:15"
            repeat: 3
            schedules:
              - name: "Lawn 2"
                time: "05:30"
                anchor: start
                weekday: [tue, thu, sat]
                month: [oct, nov, dec, jan, feb, mar, apr]
            zones:
              - zone_id: 4
              - zone_id: 5
              - zone_id: 6

      - name: Verges Road
        enabled: true
        check_back:
          states: none
        all_zones_config:
          show:
            timeline: true
            config: true
          future_span: 3
        zones:
          - name: "Main Driveway"
            show:
              timeline: true
            entity_id: switch.g0254_irrigation_verge_main_driveway
            user:
              entity_id: switch.g0254_irrigation_verge_main_driveway
              type: verge
              group: G0254
              manifold: Driveway
              actuator: AKS-0816.03-01-E
              db_board: Driveway Hut
          - name: "Pedestrian Gate"
            show:
              timeline: true
            entity_id: switch.g0286_irrigation_bel_ombre_pedestrian_gate_to_camera
            user:
              entity_id: switch.g0286_irrigation_bel_ombre_pedestrian_gate_to_camera
              type: verge
              group: G0286
              manifold: West Wall
              actuator: AKS-2016.03-01-G
              db_board: Electric Fence
          - name: "XXX"
            show:
              timeline: true
            entity_id: switch.XXX
            user:
              entity_id: switch.XXX
              type: XXX
              group: XXX
              manifold: XXX
              actuator: XXX
              db_board: XXX
          - name: "XXX"
            show:
              timeline: true
            entity_id: switch.XXX
            user:
              entity_id: switch.XXX
              type: XXX
              group: XXX
              manifold: XXX
              actuator: XXX
              db_board: XXX
          - name: "XXX"
            show:
              timeline: true
            entity_id: switch.XXX
            user:
              entity_id: switch.XXX
              type: XXX
              group: XXX
              manifold: XXX
              actuator: XXX
              db_board: XXX

        sequences:
          - name: "Verges"
            duration: "00:15"
            delay: "-00:00:02"
            repeat: 1
            schedules:
              - name: "Verges"
                time: "16:00"
                anchor: start
                weekday: [mon, wed, fri]
                month: [oct, nov, dec, jan, feb, mar, apr]
            zones:
              - zone_id: 1
              - zone_id: 2
rgc99 commented 9 months ago

Hi Martin, Thanks for the help in testing.

The full options for the cancel service call has been added to services.yaml. From the Developer Tools you can select to cancel out a running sequence.

Pause needs more work and perhaps a re-think. Putting on the back burner for a bit to get the release out the door.

evercape commented 9 months ago

Thanks Robert, and thanks for the new release. I will wait until you had a re-think on sequences with the pause/continue or freeze/unfreeze option.

Thanks Martin

rgc99 commented 7 months ago

The pause service call has been reworked. It now shuts down running zones and controller while honouring pre and post amble periods. It all gets a bit tricky depending on when in the sequence the pause is issued.

Please install from the repository and give it a go.

evercape commented 7 months ago

The pause service call has been reworked. It now shuts down running zones and controller while honouring pre and post amble periods. It all gets a bit tricky depending on when in the sequence the pause is issued.

Please install from the repository and give it a go.

Thanks Robert.

I am struggling to load from master. Pls see attached screenshot. No errors in logs. Any idea what I am doing wrong? Have rebooted but no updated repo is loaded? Thanks Martin Developer_tools_–_Home_Assistant

evercape commented 7 months ago

Hi Robert,

I manually copied services.yamland irrigation_unlimited.py to the integration folder.

When calling the service call pause, nothing happens. See log files I tried to pause on either the controller or the actual entity:

2024-04-14 19:30:03.002 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-04-14 19:30:03] controller: 3, zone: 0, state: 1
2024-04-14 19:30:03.002 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-04-14 19:30:03] controller: 3, zone: 4, state: 1, data: 4.1.1.4.4
2024-04-14 20:00:03.003 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-04-14 20:00:03] controller: 3, zone: 4, state: 0
2024-04-14 20:00:03.003 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-04-14 20:00:03] controller: 3, zone: 0, state: 0
2024-04-14 20:00:03.040 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-04-14 20:00:03] service: cancel, controller: 3, zone: 4, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c3_z4"]}
2024-04-14 20:00:04.001 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-04-14 20:00:04] controller: 3, zone: 0, state: 1
2024-04-14 20:00:04.001 INFO (MainThread) [custom_components.irrigation_unlimited] EVENT [2024-04-14 20:00:04] controller: 3, zone: 5, state: 1, data: 5.1.1.5.5
2024-04-14 20:14:57.214 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-04-14 20:14:57] service: pause, controller: 3, zone: 0, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c3_m"]}
2024-04-14 20:15:22.032 INFO (MainThread) [custom_components.irrigation_unlimited] CALL [2024-04-14 20:15:22] service: pause, controller: 3, zone: 5, sequence: 0, data: {"entity_id": ["binary_sensor.irrigation_unlimited_c3_z5"]}

Also, shouldn't there either be a pause and resume service call, or just a toggle?

Thanks Martin

rgc99 commented 7 months ago

The pause service is a toggle. It currently suspends a running sequence. The entity_id should be the sequence i.e. binary_sensor.irrigation_unlimited_c3_s1.

Cheers

evercape commented 7 months ago

Morning Robert,

Thanks, I tested it and it works. My bad, I assumed it worked on controller or zone level.

I wonder if there is merit in changing service name to toggle or pause_resume as the same call toggles between pause and resume.

Lastly, is there a way to list/pull all the current sequences that are actively running ie have at least one zone one? In my particular case I only ever run one zone due to pressure.

My use case is that if I am filling the tanks for fresh water of the house (we supply both house and garden with borehole which is best quality drinking water) but the pressure is not enough for the irrigation whilst freshwater tank is (otherwise slowly) filling.

Alternatively, maybe the pause service call could be extended to controller level or even complete system level if no parameter is given.

Again, thanks for your work to implement this, one if not the best integration I use.

Thanks Martin

rgc99 commented 7 months ago

Hi Martin,

Glad it's working for you.

I think it would be best to have pause and resume service calls. One of the reasons is if the sequence is not running then the service call is ignored. This could cause confusion on the callers side by assuming an incorrect state.

Interesting idea to allow a global pause/resume on the controller. Pause any running sequence or resume any paused sequences. I will have a look into it. Should be interesting.

Regards Robert

evercape commented 7 months ago

Thanks Robert.

Agree with the two service calls, makes sense. And it would be easy to create a toggle one (myself) if needed by calling the pause and resume if needed. The status of each sequence is easy to get.

With regards to the global pause/resume - I think that is relatively straight forward as it simply requires a loop through all service calls for all sequences on each controller (for the controller one), and a further loop through all controllers on system level.

I think you built one if not the most advanced/complex/flexible irrigation controllers I have ever come across. The big guys (Hunter, Rainbird, ...) are no where close to what you achieved ;-)

Thanks M

rgc99 commented 7 months ago

Hi Martin,

The pause toggle has been made into pause and resume. The master entity now allows these service calls and has a sequence_id: parameter (0=all). Grab the files from the repro and have a try.

Regards Robert

evercape commented 7 months ago

Thanks Robert, currently traveling will test over weekend when back. Thanks a lot.

evercape commented 6 months ago

Hi Robert,

Thanks - that is working perfectly.

A few things to consider (or not) before final release:

alias: testing UI pause on multiple controllers ==> THIS WORKS
sequence:
  - service: irrigation_unlimited.pause
    metadata: {}
    data:
      sequence_id: 0
      entity_id: binary_sensor.irrigation_unlimited_c1_m
  - service: irrigation_unlimited.pause
    metadata: {}
    data:
      entity_id: binary_sensor.irrigation_unlimited_c2_m
      sequence_id: 0
  - service: irrigation_unlimited.pause
    metadata: {}
    data:
      entity_id: binary_sensor.irrigation_unlimited_c3_m
      sequence_id: 0
mode: single
icon: mdi:sprinkler-variant

as opposed to:

alias: testing UI pause on multiple controllers ==> THIS DOES NOT WORK
sequence:
  - service: irrigation_unlimited.pause
    metadata: {}
    data:
      sequence_id: 0
      entity_id: 
        - binary_sensor.irrigation_unlimited_c1_m
        - binary_sensor.irrigation_unlimited_c2_m
        - binary_sensor.irrigation_unlimited_c3_m
mode: single
icon: mdi:sprinkler-variant

Ona another note, the companion card could subsequently do with an update permitting pause/resume once the controller is updated and this enhancement is pushed out with the next new release. I have one further request/suggestion to companion card that could be helpful so will open a new ticket for that.

Thanks again - this is a really cool feature to have. Rgds Martin

evercape commented 6 months ago

Hi Robert,

one other thing that I would recommend:

When a controller is paused via 0=all, its status changes to 'off' whereas the underlying sequence(s) status is changed to 'paused'.

It would be great to do the same on controller level.

Thanks Martin

evercape commented 6 months ago

Hi Robert,

here is some code that creates a play/resume button for all controllers. I am using a GROUP which actually works well on your service call ui.pause and ui.resume (not sure if intentional or not).

First, create a group for all controller main entities:

group:
  irrigation_controllers:
        name: Irrigation Controllers
        entities:
          - binary_sensor.irrigation_unlimited_c1_m
          - binary_sensor.irrigation_unlimited_c2_m
          - binary_sensor.irrigation_unlimited_c3_m
          - binary_sensor.irrigation_unlimited_c4_m
          - binary_sensor.irrigation_unlimited_c5_m
          - binary_sensor.irrigation_unlimited_c6_m

Then a script that toggles between pause/resume based on the fact if there are any sequences that are paused and not all controllers are off. Note that the group of all controllers is the target, not individual controllers. Sequence_id is 0 in order to include all sequences that might be paused.

script:
  toggle_irrigation:
    alias: "Irrigation: Pause/Resume all irrigation unlimited controllers"
    sequence:
      - choose:
          - conditions:
              - condition: template
                value_template: >-
                  {% set paused_sensors = states.binary_sensor 
                      | selectattr('entity_id', 'search', 'irrigation_unlimited_c') 
                      | selectattr('attributes.status', 'equalto', 'paused') 
                      | map(attribute='entity_id') 
                      | list %}
                  {{ paused_sensors | length > 0 }}
            sequence:
              - service: irrigation_unlimited.resume
                data:
                  entity_id: group.irrigation_controllers
                  sequence_id: 0
          - conditions:
              - condition: template
                value_template: >-
                  {% set paused_sensors = states.binary_sensor 
                      | selectattr('entity_id', 'search', 'irrigation_unlimited_c') 
                      | selectattr('attributes.status', 'equalto', 'paused') 
                      | map(attribute='entity_id') 
                      | list %}
                  {{ paused_sensors | length == 0 and states('group.irrigation_controllers') == 'on' }}
            sequence:
              - service: irrigation_unlimited.pause
                data:
                  entity_id: group.irrigation_controllers
                  sequence_id: 0
    icon: mdi:play-circle-outline

Then define a button template which can be used with Lovelace to pause and resume controllers' sequences accordingly:

template:   
  - button:
      - unique_id: "irrigation_pause_resume"
        name: >-
          {% set paused_sensors = states.binary_sensor 
              | selectattr('entity_id', 'search', 'irrigation_unlimited_c') 
              | selectattr('attributes.status', 'equalto', 'paused') 
              | map(attribute='entity_id') 
              | list %}                            
          {% if states('group.irrigation_controllers') == 'on' or paused_sensors | length > 0 %}
            {% if paused_sensors | length > 0 %}
              {{ paused_sensors | length }} sensor currently paused
            {% else %}
              click to pause
            {% endif %}            
          {% else %}
            Idle
          {% endif %}
        icon: >-
          {% set paused_sensors = states.binary_sensor 
              | selectattr('entity_id', 'search', 'irrigation_unlimited_c') 
              | selectattr('attributes.status', 'equalto', 'paused') 
              | map(attribute='entity_id') 
              | list %}                            
          {% if states('group.irrigation_controllers') == 'on' or paused_sensors | length > 0 %}
            {% if paused_sensors | length > 0 %}
              mdi:play-circle-outline
            {% else %}
              mdi:pause-circle-outline
            {% endif %}            
          {% else %}
            mdi:stop-circle-outline
          {% endif %}
        press:
          service: script.toggle_irrigation

As a result one gets a button that shows one or more zone paused or a button that permits to pause any controllers currently running.

This is the functionality that I was looking for and that is now working, thanks to your implementation of the additional service calls. Maybe a consideration for further implementation into the companion card.

Thanks a lot, Martin

Martin_Testing_–_Home_Assistant Martin_Testing_–_Home_Assistant Martin_Testing_–_Home_Assistant

evercape commented 6 months ago

Sorry Robert to bother again - it seems there was a case just now where the main controller's attribute {{ state_attr('binary_sensor.irrigation_unlimited_c3_m', 'status') }} has the value 'paused' which normally does not happen when using the service call pause it goes to off and with resume to on.

Is there maybe something in your code where it works sometimes but not all the times?

I couldn't figure it out when it happened, just noticed it.

I think it would be prudent to have both status attributes and icons/color on both controller and sequence in sync. Thanks M

evercape commented 6 months ago

Best is to change the above yaml code for paused sensors from:

{% set paused_sensors = states.binary_sensor 
              | selectattr('entity_id', 'search', 'irrigation_unlimited_c') 
              | selectattr('attributes.status', 'equalto', 'paused') 
              | map(attribute='entity_id') 
              | list %}  

to:

{% set paused_sensors = states.binary_sensor 
                | selectattr('entity_id', 'match', '^binary_sensor\.irrigation_unlimited_c\d+_s\d+$') 
                | selectattr('attributes.status', 'equalto', 'paused') 
                | map(attribute='entity_id') 
                | list %}
{{ paused_sensors }}

then it does not matter if the main controller entity's status is set to paused or off (which was a bit random).

rgc99 commented 6 months ago

The sequence has seven different icons/status; Blocked, Disabled, Suspended, Off, Pause, Delay, On. The delay status is when the sequence is waiting in between zones because of the delay: directive. Pause is when the pause service call has been used. The original status for the delay state used to be pause but it made more sense to rename this to delay with the introduction of the pause/resume functionality.

The controller has five different icons/status; Disabled, Suspended, Off, Pause, On. The pause state is when any of the sequences is in the delay state (which used to be known as pause).

The icon/status for the controller in the delay state should be changed to match the sequence. This however may cause automations to break if users have been monitoring this state. Not sure about the introduction of a state where a sequence is in the pause/resume situation.

You probably saw the controller status in pause because a sequence was in the delay state albeit for only a couple of seconds.

Confused, I think we have to bite the bullet and change the controller status from pause to delay.

The controller and sequences/zones work independently of each other. Because of pre and post amble periods which could be positive or negative, the controller could be on or off before or after the zone. This was one of the main challenges of the pause/resume functionality to correctly manage shutdown and restart times.

evercape commented 6 months ago

Morning Robert, from my side (after changing above Jinja code to use regex) I am fine as I am now only checking on possible pause status on sequences. So if it helps don't touch the controller. Also not too worried about the icon as the icon and color of the sequence behaves correctly during pause.

What would be nice is if I could programmatically trigger that the sequence that is paused shows on the companion card, ie, by default I have all zones and sequences disabled in the view (always_show_zones: false always_show_sequences: false) and when I press my pause button (or have it trigger by automation) automatically show that particular sequence.

Any idea how to trigger that in the front end? Almost need a hook for that button to show zone?

See screenshot below. Thanks Martin Martin_Testing_–_Home_Assistant

rgc99 commented 6 months ago

This would be best left to an option within the card show_paused_sequences.

Please feel free to update the documentation. I could use the help.

Regards Robert

evercape commented 6 months ago

Will do feature request on card and also update the documentation least I can do to support your great work. Give me a day or two. Thanks Martin

evercape commented 6 months ago

Please feel free to update the documentation. I could use the help.

Hi Robert, documentation done via PR163.

Just a reminder that the help text on the service calls needs amendments as per above:

Amend the text that is shown when using HA UI on the page service call ui.pause and ui.resume: Under entity it's not the sequence entity it could be both sequence and master controller entity. under the optional sequence ID change "to run" to "to pause" and "to resume" accordingly. Add help text to 0=all

For reference copying a screenshot here: Notification_Center

Also the new service calls are not yet published into a release yet.

Thanks a lot. Martin

evercape commented 6 months ago

This would be best left to an option within the card show_paused_sequences.

Feature Request FR12 added to the companian card. Thanks.

rgc99 commented 6 months ago

The text on the service calls has been updated. Please let me know if anything else is needed or better yet this is all in the services.yaml file. Feel free to amend and submit a PR.

evercape commented 6 months ago

Thanks for the update. Tiny typo fix proposed in #164

On another note, if only sequences or controller entities can be paused/resumed - the drop down list of entities should then only show those?

See screenshot below which also lists entity ids of zones.

Thanks Martin

Fullscreen_2024_05_10__07_29

rgc99 commented 6 months ago

What you see on the Developers->Services screen is all done via the services.yaml file. It is read by HA to display the various fields for each service call. Each field can have a selector: attached (text, number, time etc). You can find the documentation here for the selectors and options that are available.

The entity_id uses the entity selector which has a few options available to limit the list. Not sure how it can be honed down further to eliminate the zones.

evercape commented 6 months ago

limit the list

Thanks Robert for the links and explanation, now I understand it better. It is possible to "manually" include and exclude entities, but Jinja does not seem to work within the entity selector.

This seems to work by excluding zones manually:

selector:
        entity:
          exclude_entities: 
            - binary_sensor. irrigation_unlimited_c1_z1
            - binary_sensor. irrigation_unlimited_c1_z2
            - binary_sensor. irrigation_unlimited_c1_z3
            - binary_sensor. irrigation_unlimited_c1_z4
            - ...
            - binary_sensor. irrigation_unlimited_c2_z1
            - binary_sensor. irrigation_unlimited_c2_z2
            - ...

However, this would be cool to only include controllers and sequences using regex within Jinja:

selector:
        entity:
          include_entities: >-
            {{ states.binary_sensor
            | selectattr('entity_id', 'match', '^binary_sensor\.irrigation_unlimited_c\d+_(s\d+|m)$')
            | map(attribute='entity_id') | list }}          

I googled a bit around and found a blue print with a selector that does in fact use Jinja:

selector:
        select:
          options:
          - label: 'Off'
            value: 'false'
          - label: 'On'
            value: 'true'
          - label: On During the Day
            value: '{{''true'' if is_state(''sun.sun'', ''above_horizon'') else ''false''
              }}'
          - label: On During the Night
            value: '{{''true'' if is_state(''sun.sun'', ''below_horizon'') else ''false''
              }}'

Not sure if that helps. I couldn't get the Jinja working.

On another note, multiple: true does seem to work. Obviously not conducive if a combination of controllers and sequences were to be selected.

Feel free to close this issue. From my side it's working perfectly and I am very grateful for the pause/resume services that really help me in our irrigation setup. Thanks again!

evercape commented 6 months ago

Thanks, the version 2024.5.0 now includes this feature request, much appreciated.

billmoseley commented 2 months ago

I've read through here and I'm not quite clear what the behavior is, for example, when a sequence is scheduled to start when paused, or if the pause is so long that a paused sequence's start time comes around again. Hard to know what the desired behavior is, to be honest. Pausing makes sense if for a short time (filling a tank) but less so if the time off is unknown.

I have two related cases where I might want to pause or disable. One is I can detect when the pump power is out. This could be many hours long (maybe days). The other is temporary low water pressure likely due to neighbors using the water.

In these cases is it better to just disable when power (or pressure) is out and enable after restored for some amount of time?

rgc99 commented 2 months ago

Pause only works on a running sequence. It will not prevent future schedules from starting. Its main purpose is temporarily stop for short periods such as filling a tank or access like walking through the sprinkler.

Enable/disable will stop everything from running. Suspend is much the same but has a restart time.