Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split run services by target type #314

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading