From 7383eedcb1ebe655c542ca1fb4b45cf15cf1383a Mon Sep 17 00:00:00 2001 From: rgc99 Date: Sun, 11 Apr 2021 21:03:28 +0000 Subject: [PATCH] Add cancel service --- README.md | 9 ++++ .../irrigation_unlimited/const.py | 1 + .../irrigation_unlimited.py | 45 ++++++++++++++++++- .../irrigation_unlimited/service.py | 6 +++ .../irrigation_unlimited/services.yaml | 6 +++ 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 042a408..822e15a 100644 --- a/README.md +++ b/README.md @@ -272,6 +272,7 @@ The binary sensor associated with each controller and zone provide several servi - `enable` - `disable` - `toggle` +- `cancel` - `manual_run` - `adjust_time` @@ -285,6 +286,14 @@ Enables/disables/toggles the controller or zone respectively. | ---------------------- | -------- | ----------- | | `entity_id` | no | Controller or zone to enable/disable/toggle. +### Service `cancel` + +Cancels the current running schedule. + +| Service data attribute | Optional | Description | +| ---------------------- | -------- | ----------- | +| `entity_id` | no | Controller or zone to cancel. + ### Service `manual_run` Turn on the controller or zone for a period of time. diff --git a/custom_components/irrigation_unlimited/const.py b/custom_components/irrigation_unlimited/const.py index 3bd73df..d917f00 100644 --- a/custom_components/irrigation_unlimited/const.py +++ b/custom_components/irrigation_unlimited/const.py @@ -68,6 +68,7 @@ SERVICE_ENABLE = "enable" SERVICE_DISABLE = "disable" SERVICE_TOGGLE = "toggle" +SERVICE_CANCEL = "cancel" SERVICE_TIME_ADJUST = "adjust_time" SERVICE_MANUAL_RUN = "manual_run" diff --git a/custom_components/irrigation_unlimited/irrigation_unlimited.py b/custom_components/irrigation_unlimited/irrigation_unlimited.py index 6e7525e..f65d2ad 100644 --- a/custom_components/irrigation_unlimited/irrigation_unlimited.py +++ b/custom_components/irrigation_unlimited/irrigation_unlimited.py @@ -66,6 +66,7 @@ CONF_CONFIG, CONF_TIMELINE, CONF_ZONE_ID, + SERVICE_CANCEL, SERVICE_DISABLE, SERVICE_ENABLE, SERVICE_TOGGLE, @@ -511,12 +512,14 @@ class IURunQueue(list): RQ_STATUS_REDUCED: int = 0x04 RQ_STATUS_SORTED: int = 0x08 RQ_STATUS_UPDATED: int = 0x10 + RQ_STATUS_CANCELED: int = 0x20 def __init__(self) -> None: # Private variables self._current_run: IURun = None self._next_run: IURun = None self._sorted: bool = False + self._cancel_request: bool = False return @property @@ -541,6 +544,11 @@ def add( self._sorted = False return self + def cancel(self) -> None: + """Flag the current run to be cancelled""" + self._cancel_request = True + return + def clear_all(self) -> bool: modified: bool = False if len(self) > 0: @@ -619,6 +627,16 @@ def remove_expired(self, time: datetime) -> bool: i -= 1 return modified + def remove_current(self) -> bool: + """Remove the current run""" + modified: bool = False + if self._current_run is not None: + if len(self) > 0: + self.pop(0) + self._current_run = None + modified = True + return modified + def update_queue(self, time: datetime) -> int: """Update the run queue. Sort the queue, remove expired runs and set current and next runs. @@ -630,6 +648,11 @@ def update_queue(self, time: datetime) -> int: if self.sort(): status |= self.RQ_STATUS_SORTED + if self._cancel_request: + if self.remove_current(): + status |= self.RQ_STATUS_CANCELED + self._cancel_request = False + if self.remove_expired(time): status |= self.RQ_STATUS_REDUCED @@ -916,6 +939,11 @@ def service_manual_run(self, data: MappingProxyType, time: datetime) -> None: self._run_queue.add_manual(ns, wash_td(data[CONF_TIME])) return + def service_cancel(self, data: MappingProxyType, time: datetime) -> None: + """Cancel the current running schedule""" + self._run_queue.cancel() + return + def add(self, schedule: IUSchedule) -> IUSchedule: """Add a new schedule to the zone""" self._schedules.append(schedule) @@ -1465,10 +1493,11 @@ def muster(self, time: datetime, force: bool) -> int: IURunQueue.RQ_STATUS_CLEARED | IURunQueue.RQ_STATUS_EXTENDED | IURunQueue.RQ_STATUS_SORTED + | IURunQueue.RQ_STATUS_CANCELED ) != 0 ): - all = zone_status & IURunQueue.RQ_STATUS_CLEARED + all = bool(zone_status & (IURunQueue.RQ_STATUS_CLEARED | IURunQueue.RQ_STATUS_CANCELED)) status |= self._run_queue.rebuild_schedule( time, self._zones, self._preamble, self._postamble, all ) @@ -1820,6 +1849,15 @@ def manual_run_all( zone.service_manual_run(data, time) return + def cancel_all( + controller: IUController, data: MappingProxyType, time: datetime + ) -> None: + zl = data.get(CONF_ZONES, None) + for zone in controller.zones: + if zl is None or zone.zone_index + 1 in zl: + zone.service_cancel(data, time) + return + def notify_children(controller: IUController) -> None: for zone in controller.zones: zone.request_update() @@ -1843,6 +1881,11 @@ def notify_children(controller: IUController) -> None: else: controller.enabled = not controller.enabled notify_children(controller) + elif service == SERVICE_CANCEL: + if zone is not None: + zone.service_cancel(data, time) + else: + cancel_all(controller, data, time) elif service == SERVICE_TIME_ADJUST: if zone is not None: zone.service_adjust_time(data, time) diff --git a/custom_components/irrigation_unlimited/service.py b/custom_components/irrigation_unlimited/service.py index 50e1ed7..dbf308f 100644 --- a/custom_components/irrigation_unlimited/service.py +++ b/custom_components/irrigation_unlimited/service.py @@ -13,6 +13,7 @@ from .entity import IUEntity from .const import ( DOMAIN, + SERVICE_CANCEL, SERVICE_ENABLE, SERVICE_DISABLE, SERVICE_TOGGLE, @@ -85,12 +86,17 @@ async def async_manual_run(entity: IUEntity, call: ServiceCall) -> None: return +async def async_cancel(entity: IUEntity, call: ServiceCall) -> None: + entity.dispatch(SERVICE_CANCEL, call) + + def register_platform_services(platform: entity_platform.EntityPlatform) -> None: platform.async_register_entity_service(SERVICE_ENABLE, ENTITY_SCHEMA, async_enable) platform.async_register_entity_service( SERVICE_DISABLE, ENTITY_SCHEMA, async_disable ) platform.async_register_entity_service(SERVICE_TOGGLE, ENTITY_SCHEMA, async_toggle) + platform.async_register_entity_service(SERVICE_CANCEL, ENTITY_SCHEMA, async_cancel) platform.async_register_entity_service( SERVICE_TIME_ADJUST, TIME_ADJUST_SCHEMA, async_time_adjust ) diff --git a/custom_components/irrigation_unlimited/services.yaml b/custom_components/irrigation_unlimited/services.yaml index 8949c59..22e88cd 100644 --- a/custom_components/irrigation_unlimited/services.yaml +++ b/custom_components/irrigation_unlimited/services.yaml @@ -18,6 +18,12 @@ toggle: entity_id: description: Name of the Irrigation Unlimited entity. example: 'binary_sensor.irrigation_unlimited_c1_z1' +cancel: + description: Cancel the current run. + fields: + entity_id: + description: Name of the Irrigation Unlimited entity. + example: 'binary_sensor.irrigation_unlimited_c1_z1' reload: description: Reload the configuration fields: