Add rachio service to start multiple zones (#42092)
This commit is contained in:
parent
5a907095e5
commit
199464f084
4 changed files with 71 additions and 5 deletions
|
@ -52,6 +52,7 @@ STATUS_ONLINE = "ONLINE"
|
||||||
SCHEDULE_TYPE_FIXED = "FIXED"
|
SCHEDULE_TYPE_FIXED = "FIXED"
|
||||||
SCHEDULE_TYPE_FLEX = "FLEX"
|
SCHEDULE_TYPE_FLEX = "FLEX"
|
||||||
SERVICE_SET_ZONE_MOISTURE = "set_zone_moisture_percent"
|
SERVICE_SET_ZONE_MOISTURE = "set_zone_moisture_percent"
|
||||||
|
SERVICE_START_MULTIPLE_ZONES = "start_multiple_zone_schedule"
|
||||||
|
|
||||||
SIGNAL_RACHIO_UPDATE = f"{DOMAIN}_update"
|
SIGNAL_RACHIO_UPDATE = f"{DOMAIN}_update"
|
||||||
SIGNAL_RACHIO_CONTROLLER_UPDATE = f"{SIGNAL_RACHIO_UPDATE}_controller"
|
SIGNAL_RACHIO_CONTROLLER_UPDATE = f"{SIGNAL_RACHIO_UPDATE}_controller"
|
||||||
|
|
|
@ -80,6 +80,10 @@ class RachioPerson:
|
||||||
"""Get a list of controllers managed by this account."""
|
"""Get a list of controllers managed by this account."""
|
||||||
return self._controllers
|
return self._controllers
|
||||||
|
|
||||||
|
def start_multiple_zones(self, zones) -> None:
|
||||||
|
"""Start multiple zones."""
|
||||||
|
self.rachio.zone.start_multiple(zones)
|
||||||
|
|
||||||
|
|
||||||
class RachioIro:
|
class RachioIro:
|
||||||
"""Represent a Rachio Iro."""
|
"""Represent a Rachio Iro."""
|
||||||
|
|
|
@ -7,3 +7,12 @@ set_zone_moisture_percent:
|
||||||
percent:
|
percent:
|
||||||
description: Set the desired zone moisture percentage from 0 to 100. [Required]
|
description: Set the desired zone moisture percentage from 0 to 100. [Required]
|
||||||
example: 50
|
example: 50
|
||||||
|
start_multiple_zone_schedule:
|
||||||
|
description: Create a custom schedule of zones and runtimes.
|
||||||
|
fields:
|
||||||
|
entity_id:
|
||||||
|
description: Name of the zone or zones to run. Zones should all be on the same controller, attempting to start zones on multiple controllers may have undesired results. [Required]
|
||||||
|
example: "switch.front_yard, switch.side_yard"
|
||||||
|
duration:
|
||||||
|
description: Number of minutes to run the zone(s). If only 1 duration is given, that time will be used for all zones. If given a list of durations, the durations will apply to the respective zone listed above. [Required]
|
||||||
|
example: 15, 20
|
||||||
|
|
|
@ -6,7 +6,9 @@ import logging
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.event import async_track_point_in_utc_time
|
from homeassistant.helpers.event import async_track_point_in_utc_time
|
||||||
|
@ -37,6 +39,7 @@ from .const import (
|
||||||
SCHEDULE_TYPE_FIXED,
|
SCHEDULE_TYPE_FIXED,
|
||||||
SCHEDULE_TYPE_FLEX,
|
SCHEDULE_TYPE_FLEX,
|
||||||
SERVICE_SET_ZONE_MOISTURE,
|
SERVICE_SET_ZONE_MOISTURE,
|
||||||
|
SERVICE_START_MULTIPLE_ZONES,
|
||||||
SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
||||||
SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
|
SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
|
||||||
SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
||||||
|
@ -63,32 +66,81 @@ from .webhooks import (
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ATTR_DURATION = "duration"
|
||||||
|
ATTR_ID = "id"
|
||||||
ATTR_PERCENT = "percent"
|
ATTR_PERCENT = "percent"
|
||||||
ATTR_SCHEDULE_SUMMARY = "Summary"
|
ATTR_SCHEDULE_SUMMARY = "Summary"
|
||||||
ATTR_SCHEDULE_ENABLED = "Enabled"
|
ATTR_SCHEDULE_ENABLED = "Enabled"
|
||||||
ATTR_SCHEDULE_DURATION = "Duration"
|
ATTR_SCHEDULE_DURATION = "Duration"
|
||||||
ATTR_SCHEDULE_TYPE = "Type"
|
ATTR_SCHEDULE_TYPE = "Type"
|
||||||
|
ATTR_SORT_ORDER = "sortOrder"
|
||||||
ATTR_ZONE_NUMBER = "Zone number"
|
ATTR_ZONE_NUMBER = "Zone number"
|
||||||
ATTR_ZONE_SHADE = "Shade"
|
ATTR_ZONE_SHADE = "Shade"
|
||||||
ATTR_ZONE_SLOPE = "Slope"
|
ATTR_ZONE_SLOPE = "Slope"
|
||||||
ATTR_ZONE_SUMMARY = "Summary"
|
ATTR_ZONE_SUMMARY = "Summary"
|
||||||
ATTR_ZONE_TYPE = "Type"
|
ATTR_ZONE_TYPE = "Type"
|
||||||
|
|
||||||
|
START_MULTIPLE_ZONES_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
|
vol.Required(ATTR_DURATION): cv.ensure_list_csv,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up the Rachio switches."""
|
"""Set up the Rachio switches."""
|
||||||
|
zone_entities = []
|
||||||
has_flex_sched = False
|
has_flex_sched = False
|
||||||
entities = await hass.async_add_executor_job(_create_entities, hass, config_entry)
|
entities = await hass.async_add_executor_job(_create_entities, hass, config_entry)
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
|
if isinstance(entity, RachioZone):
|
||||||
|
zone_entities.append(entity)
|
||||||
if isinstance(entity, RachioSchedule) and entity.type == SCHEDULE_TYPE_FLEX:
|
if isinstance(entity, RachioSchedule) and entity.type == SCHEDULE_TYPE_FLEX:
|
||||||
has_flex_sched = True
|
has_flex_sched = True
|
||||||
break
|
|
||||||
|
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
_LOGGER.info("%d Rachio switch(es) added", len(entities))
|
_LOGGER.info("%d Rachio switch(es) added", len(entities))
|
||||||
|
|
||||||
platform = entity_platform.current_platform.get()
|
def start_multiple(service):
|
||||||
|
"""Service to start multiple zones in sequence."""
|
||||||
|
zones_list = []
|
||||||
|
person = hass.data[DOMAIN_RACHIO][config_entry.entry_id]
|
||||||
|
entity_id = service.data[ATTR_ENTITY_ID]
|
||||||
|
duration = iter(service.data[ATTR_DURATION])
|
||||||
|
default_time = service.data[ATTR_DURATION][0]
|
||||||
|
entity_to_zone_id = {
|
||||||
|
entity.entity_id: entity.zone_id for entity in zone_entities
|
||||||
|
}
|
||||||
|
|
||||||
|
for (count, data) in enumerate(entity_id):
|
||||||
|
if data in entity_to_zone_id:
|
||||||
|
# Time can be passed as a list per zone,
|
||||||
|
# or one time for all zones
|
||||||
|
time = int(next(duration, default_time)) * 60
|
||||||
|
zones_list.append(
|
||||||
|
{
|
||||||
|
ATTR_ID: entity_to_zone_id.get(data),
|
||||||
|
ATTR_DURATION: time,
|
||||||
|
ATTR_SORT_ORDER: count,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(zones_list) != 0:
|
||||||
|
person.start_multiple_zones(zones_list)
|
||||||
|
_LOGGER.debug("Starting zone(s) %s", entity_id)
|
||||||
|
else:
|
||||||
|
raise HomeAssistantError("No matching zones found in given entity_ids")
|
||||||
|
|
||||||
|
hass.services.async_register(
|
||||||
|
DOMAIN_RACHIO,
|
||||||
|
SERVICE_START_MULTIPLE_ZONES,
|
||||||
|
start_multiple,
|
||||||
|
schema=START_MULTIPLE_ZONES_SCHEMA,
|
||||||
|
)
|
||||||
|
|
||||||
if has_flex_sched:
|
if has_flex_sched:
|
||||||
|
platform = entity_platform.current_platform.get()
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_SET_ZONE_MOISTURE,
|
SERVICE_SET_ZONE_MOISTURE,
|
||||||
{vol.Required(ATTR_PERCENT): cv.positive_int},
|
{vol.Required(ATTR_PERCENT): cv.positive_int},
|
||||||
|
@ -289,7 +341,7 @@ class RachioZone(RachioSwitch):
|
||||||
|
|
||||||
def __init__(self, person, controller, data, current_schedule):
|
def __init__(self, person, controller, data, current_schedule):
|
||||||
"""Initialize a new Rachio Zone."""
|
"""Initialize a new Rachio Zone."""
|
||||||
self._id = data[KEY_ID]
|
self.id = data[KEY_ID]
|
||||||
self._zone_name = data[KEY_NAME]
|
self._zone_name = data[KEY_NAME]
|
||||||
self._zone_number = data[KEY_ZONE_NUMBER]
|
self._zone_number = data[KEY_ZONE_NUMBER]
|
||||||
self._zone_enabled = data[KEY_ENABLED]
|
self._zone_enabled = data[KEY_ENABLED]
|
||||||
|
@ -309,7 +361,7 @@ class RachioZone(RachioSwitch):
|
||||||
@property
|
@property
|
||||||
def zone_id(self) -> str:
|
def zone_id(self) -> str:
|
||||||
"""How the Rachio API refers to the zone."""
|
"""How the Rachio API refers to the zone."""
|
||||||
return self._id
|
return self.id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
|
@ -381,7 +433,7 @@ class RachioZone(RachioSwitch):
|
||||||
def set_moisture_percent(self, percent) -> None:
|
def set_moisture_percent(self, percent) -> None:
|
||||||
"""Set the zone moisture percent."""
|
"""Set the zone moisture percent."""
|
||||||
_LOGGER.debug("Setting %s moisture to %s percent", self._zone_name, percent)
|
_LOGGER.debug("Setting %s moisture to %s percent", self._zone_name, percent)
|
||||||
self._controller.rachio.zone.set_moisture_percent(self._id, percent / 100)
|
self._controller.rachio.zone.set_moisture_percent(self.id, percent / 100)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_handle_update(self, *args, **kwargs) -> None:
|
def _async_handle_update(self, *args, **kwargs) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue