Skip to content

Commit

Permalink
Split run services by target type
Browse files Browse the repository at this point in the history
  • Loading branch information
EdLeckert committed Oct 5, 2024
1 parent a1c5df3 commit ab7b7ef
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 64 deletions.
143 changes: 82 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ Last tested on OS API `2.2.0` and Home Assistant `2024.2.0`
- Sensors for water level, last runtime and rain delay stop time
- Switches for each program and station to enable/disable program or station
- Switch to enable/disable OpenSprinkler controller operation
- Services to run and stop stations
- Service to run programs
- Services to pause, set a rain delay, and set the water level.
- Actions to run and stop stations
- Action to run programs
- Actions to pause, set a rain delay, and set the water level.

To have a Lovelace card for the UI, [opensprinkler-card](https://github.com/rianadon/opensprinkler-card) can be used.

Expand Down Expand Up @@ -47,51 +47,62 @@ Note: _1.0.0 has major breaking changes, you will need to update any automations

- Program binary sensors now show running state instead of operation state. Please use the program switch states for program operation state.
- Controller binary sensor is removed. Please use controller switch state for controller operation state.
- Station switches now enable/disable instead of run/stop stations. Please use `opensprinkler.run` and `opensprinkler.stop` services to run and stop stations.
- All scenes are removed. Please use the `opensprinkler.run` service to run programs.
- Station switches now enable/disable instead of run/stop stations. Please use `opensprinkler.run_station` and `opensprinkler.stop` actions to run and stop stations.
- All scenes are removed. Please use the `opensprinkler.run_program` action to run programs.

## Using Services
## Using Actions

Available services are `opensprinkler.run` for programs, stations and controllers (for running once program), and `opensprinkler.stop` for stations or controller (to stop all stations).
Available actions are `opensprinkler.run_program`, `opensprinkler.run_station`, and `opensprinkler.run_once`
to start a program, station, or controller (multiple stations) respectively, and `opensprinkler.stop` to stop one or all stations.

Note: The action `opensprinkler.run` is deprecated and will be removed in a future release. Please migrate to one of the above actions,
which use the same parameters.

### Run Examples

Note: If using a version of Home Assistant prior to 2024.8, substitute the keyword `service` for `action` in the following examples.

#### Run Program Example

```yaml
service: opensprinkler.run
data:
entity_id: switch.program_name # Switches or sensors for programs
action: opensprinkler.run_program
target:
entity_id: switch.standard_schedule_program_enabled # Any program enabled switch
data: {}
```
#### Run Station Example
```yaml
service: opensprinkler.run
action: opensprinkler.run_station
data:
entity_id: switch.station_name # Switches or sensors for stations
run_seconds: 60 # Seconds to run (optional, defaults to 60 seconds)
```
run_seconds: 600 # Number of seconds to run the station. Optional, defaults to 60 seconds.
target:
entity_id: switch.front_yard_station_enabled # Any station enabled switch
```
#### Run Once Program Example
To run an once program, the run seconds can either be a list of seconds per station or a list of index and second pairs.
To run a number of stations at once, use `opensprinkler.run_once`. The run seconds can either be a list of seconds per station
or a list or dict of index and seconds pairs.
The following examples are all equivalent.

```yaml
service: opensprinkler.run
action: opensprinkler.run_once
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
data:
entity_id: switch.controller_name # Switches or sensors for controller
run_seconds: # Seconds to run for each station (required)
run_seconds: # List of seconds to run for each station (required)
- 60
- 0
- 30
```

```yaml
service: opensprinkler.run
action: opensprinkler.run_once
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
data:
entity_id: switch.controller_name # Switches or sensors for controller
run_seconds: # List of station index and run seconds pairs (required)
- index: 0
run_seconds: 60
Expand All @@ -100,99 +111,108 @@ data:
```

```yaml
service: opensprinkler.run
action: opensprinkler.run_once
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
data:
entity_id: switch.controller_name # Switches or sensors for controller
run_seconds: # Dictionary of station index and run seconds key/value pairs (required)
0: 60
2: 30
"0": 60
"2": 30
```

By default running once program will stop all other stations that are running, you can specify
`continue_running_stations` to true to allow the stations to continue running. This only works when
specifying the run seconds in index/second pairs.
Calling `opensprinkler.run_once` or `opensprinkler.run_program` will stop all other stations that are running.
When using `opensprinkler.run_once`, you can set `continue_running_stations` to true to allow the stations to
continue running. This only works when specifying the run seconds in index/seconds pairs.

```yaml
service: opensprinkler.run
action: opensprinkler.run_once
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
data:
entity_id: switch.controller_name # Switches or sensors for controller
run_seconds: # List of station index and run seconds pairs (required)
continue_running_stations: true # Keep running stations running (optional, defaults to false)
run_seconds:
- index: 0
run_seconds: 60
- index: 2
run_seconds: 30
continue_running_stations: True # Whether to keep running stations running (optional, defaults to False)
```

```yaml
service: opensprinkler.run
action: opensprinkler.run_once
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
data:
entity_id: switch.controller_name # Switches or sensors for controller
run_seconds: # Dictionary of station index and run seconds key/value pairs (required)
0: 60
2: 30
continue_running_stations: True # Whether to keep running stations running (optional, defaults to False)
continue_running_stations: true # Keep running stations running (optional, defaults to false)
run_seconds:
"0": 60
"2": 30
```

### Stop Examples

#### Stop Station Example

```yaml
service: opensprinkler.stop
data:
entity_id: switch.station_name # Switches or sensors for stations
action: opensprinkler.stop
data: {}
target:
entity_id: switch.drip_station_enabled # Any station enabled switch
```

#### Stop All Stations Example

```yaml
service: opensprinkler.stop
data:
entity_id: switch.controller_name # Switches or sensors for controller
```
action: opensprinkler.stop
data: {}
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
```

### Set Water Level Example

This sets the water level to 50%, i.e. all stations will run half of their normally configured time.

```yaml
service: opensprinkler.set_water_level
action: opensprinkler.set_water_level
data:
entity_id: sensor.opensprinkler_water_level
water_level: 50
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
```

### Set Rain Delay Example

This sets the rain delay of the controller to 6 hours, i.e. all stations will stop and programs will not run until the rain delay time is over.

```yaml
service: opensprinkler.set_rain_delay
action: opensprinkler.set_rain_delay
data:
entity_id: sensor.opensprinkler_rain_delay_stop_time
rain_delay: 6
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
```

### Pause Example

This pauses the station runs for 10 minutes (600 seconds), resuming afterwards.

```yaml
service: opensprinkler.pause_stations
action: opensprinkler.pause_stations
data:
entity_id: sensor.opensprinkler_pause_end_time
pause_duration: 600
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
```

### Reboot Controller Example

This reboots the controller.

```yaml
service: opensprinkler.reboot
data:
entity_id: switch.opensprinkler_enabled
action: opensprinkler.reboot
data: {}
target:
entity_id: switch.opensprinkler_enabled # Controller enabled switch
```

## Creating a Station Switch
Expand All @@ -205,20 +225,21 @@ switch:
- platform: template
switches:
fruits_station:
value_template: "{{ is_state('binary_sensor.s01_station_running', 'on') }}"
value_template: "{{ is_state('binary_sensor.front_yard_station_running', 'on') }}"
turn_on:
service: opensprinkler.run
data_template:
entity_id: binary_sensor.s01_station_running
action: opensprinkler.run_station
target:
entity_id: switch.front_yard_station_enabled
# Run seconds uses the input_number below.
run_seconds: "{{ ((states('input_number.s01_station_minutes') | float) * 60) | int }}"
data:
run_seconds: "{{ ((states('input_number.front_yard_station_minutes') | float) * 60) | int }}"
turn_off:
service: opensprinkler.stop
data:
entity_id: binary_sensor.s01_station_running
target:
entity_id: switch.front_yard_station_enabled
input_number:
s01_station_minutes:
front_yard_station_minutes:
initial: 1
min: 1
max: 10
Expand Down
63 changes: 60 additions & 3 deletions custom_components/opensprinkler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@
SCHEMA_SERVICE_PAUSE_STATIONS,
SCHEMA_SERVICE_REBOOT,
SCHEMA_SERVICE_RUN,
SCHEMA_SERVICE_RUN_ONCE,
SCHEMA_SERVICE_RUN_PROGRAM,
SCHEMA_SERVICE_RUN_STATION,
SCHEMA_SERVICE_SET_RAIN_DELAY,
SCHEMA_SERVICE_SET_WATER_LEVEL,
SCHEMA_SERVICE_STOP,
SERVICE_PAUSE_STATIONS,
SERVICE_REBOOT,
SERVICE_RUN,
SERVICE_RUN_ONCE,
SERVICE_RUN_PROGRAM,
SERVICE_RUN_STATION,
SERVICE_SET_RAIN_DELAY,
SERVICE_SET_WATER_LEVEL,
SERVICE_STOP,
Expand Down Expand Up @@ -129,6 +135,42 @@ async def _async_send_run_command(call: ServiceCall) -> None:
service_func=_async_send_run_command,
)

async def _async_send_run_once_command(call: ServiceCall) -> None:
await entity_service_call(
hass, async_get_entities(hass), SERVICE_RUN_ONCE, call, None
)

hass.services.async_register(
domain=DOMAIN,
service=SERVICE_RUN_ONCE,
schema=cv.make_entity_service_schema(SCHEMA_SERVICE_RUN_ONCE),
service_func=_async_send_run_once_command,
)

async def _async_send_run_program_command(call: ServiceCall) -> None:
await entity_service_call(
hass, async_get_entities(hass), SERVICE_RUN_PROGRAM, call, None
)

hass.services.async_register(
domain=DOMAIN,
service=SERVICE_RUN_PROGRAM,
schema=cv.make_entity_service_schema(SCHEMA_SERVICE_RUN_PROGRAM),
service_func=_async_send_run_program_command,
)

async def _async_send_run_station_command(call: ServiceCall) -> None:
await entity_service_call(
hass, async_get_entities(hass), SERVICE_RUN_STATION, call, None
)

hass.services.async_register(
domain=DOMAIN,
service=SERVICE_RUN_STATION,
schema=cv.make_entity_service_schema(SCHEMA_SERVICE_RUN_STATION),
service_func=_async_send_run_station_command,
)

async def _async_send_stop_command(call: ServiceCall) -> None:
await entity_service_call(hass, async_get_entities(hass), SERVICE_STOP, call)

Expand Down Expand Up @@ -294,8 +336,13 @@ class OpenSprinklerTime(OpenSprinklerEntity):


class OpenSprinklerControllerEntity:
async def run(self, run_seconds=None, continue_running_stations=None):
async def run_once(self, run_seconds=None, continue_running_stations=None):
"""Run once program."""
await self.run(run_seconds, continue_running_stations)
return

async def run(self, run_seconds=None, continue_running_stations=None):
"""Run controller program."""
if run_seconds is None or (
not isinstance(run_seconds, list) and not isinstance(run_seconds, dict)
):
Expand All @@ -317,7 +364,7 @@ async def run(self, run_seconds=None, continue_running_stations=None):
run_seconds_list.append(
seconds
if seconds is not None
else (0 if continue_running_stations else station.seconds_remaining)
else (station.seconds_remaining if continue_running_stations else 0)
)
await self._controller.run_once_program(run_seconds_list)
await self._coordinator.async_request_refresh()
Expand All @@ -335,7 +382,7 @@ async def run(self, run_seconds=None, continue_running_stations=None):
run_seconds_list.append(
run_seconds_by_index.get(station.index)
if run_seconds_by_index.get(station.index) is not None
else (0 if continue_running_stations else station.seconds_remaining)
else (station.seconds_remaining if continue_running_stations else 0)
)

await self._controller.run_once_program(run_seconds_list)
Expand Down Expand Up @@ -387,6 +434,11 @@ def extra_state_attributes(self):

return attributes

async def run_program(self):
"""Run program."""
await self.run()
return

async def run(self):
"""Runs the program."""
await self._program.run()
Expand Down Expand Up @@ -417,6 +469,11 @@ def extra_state_attributes(self):

return attributes

async def run_station(self, run_seconds=None):
"""Run station."""
await self.run(run_seconds)
return

async def run(self, run_seconds=None):
"""Run station."""
if run_seconds is not None and not isinstance(run_seconds, int):
Expand Down
Loading

0 comments on commit ab7b7ef

Please sign in to comment.