Add Rachio rain delay switch (#34741)
* Add Rachio Rain Delay Switch * Typo * Catch KeyError * Use HA dt module in place of time
This commit is contained in:
parent
ed925f9ef5
commit
360ac7e71f
3 changed files with 81 additions and 1 deletions
|
@ -23,6 +23,7 @@ KEY_NAME = "name"
|
||||||
KEY_MODEL = "model"
|
KEY_MODEL = "model"
|
||||||
KEY_ON = "on"
|
KEY_ON = "on"
|
||||||
KEY_DURATION = "totalDuration"
|
KEY_DURATION = "totalDuration"
|
||||||
|
KEY_RAIN_DELAY = "rainDelayExpirationDate"
|
||||||
KEY_STATUS = "status"
|
KEY_STATUS = "status"
|
||||||
KEY_SUBTYPE = "subType"
|
KEY_SUBTYPE = "subType"
|
||||||
KEY_SUMMARY = "summary"
|
KEY_SUMMARY = "summary"
|
||||||
|
@ -56,6 +57,7 @@ STATUS_OFFLINE = "OFFLINE"
|
||||||
|
|
||||||
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"
|
||||||
|
SIGNAL_RACHIO_RAIN_DELAY_UPDATE = f"{SIGNAL_RACHIO_UPDATE}_rain_delay"
|
||||||
SIGNAL_RACHIO_ZONE_UPDATE = f"{SIGNAL_RACHIO_UPDATE}_zone"
|
SIGNAL_RACHIO_ZONE_UPDATE = f"{SIGNAL_RACHIO_UPDATE}_zone"
|
||||||
SIGNAL_RACHIO_SCHEDULE_UPDATE = f"{SIGNAL_RACHIO_UPDATE}_schedule"
|
SIGNAL_RACHIO_SCHEDULE_UPDATE = f"{SIGNAL_RACHIO_UPDATE}_schedule"
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import logging
|
||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.util.dt import as_timestamp, now
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_ZONE_SHADE,
|
ATTR_ZONE_SHADE,
|
||||||
|
@ -22,17 +23,21 @@ from .const import (
|
||||||
KEY_IMAGE_URL,
|
KEY_IMAGE_URL,
|
||||||
KEY_NAME,
|
KEY_NAME,
|
||||||
KEY_ON,
|
KEY_ON,
|
||||||
|
KEY_RAIN_DELAY,
|
||||||
KEY_SCHEDULE_ID,
|
KEY_SCHEDULE_ID,
|
||||||
KEY_SUBTYPE,
|
KEY_SUBTYPE,
|
||||||
KEY_SUMMARY,
|
KEY_SUMMARY,
|
||||||
KEY_ZONE_ID,
|
KEY_ZONE_ID,
|
||||||
KEY_ZONE_NUMBER,
|
KEY_ZONE_NUMBER,
|
||||||
SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
||||||
|
SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
|
||||||
SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
||||||
SIGNAL_RACHIO_ZONE_UPDATE,
|
SIGNAL_RACHIO_ZONE_UPDATE,
|
||||||
)
|
)
|
||||||
from .entity import RachioDevice
|
from .entity import RachioDevice
|
||||||
from .webhooks import (
|
from .webhooks import (
|
||||||
|
SUBTYPE_RAIN_DELAY_OFF,
|
||||||
|
SUBTYPE_RAIN_DELAY_ON,
|
||||||
SUBTYPE_SCHEDULE_COMPLETED,
|
SUBTYPE_SCHEDULE_COMPLETED,
|
||||||
SUBTYPE_SCHEDULE_STARTED,
|
SUBTYPE_SCHEDULE_STARTED,
|
||||||
SUBTYPE_SCHEDULE_STOPPED,
|
SUBTYPE_SCHEDULE_STOPPED,
|
||||||
|
@ -67,6 +72,7 @@ def _create_entities(hass, config_entry):
|
||||||
# in order to avoid every zone doing it
|
# in order to avoid every zone doing it
|
||||||
for controller in person.controllers:
|
for controller in person.controllers:
|
||||||
entities.append(RachioStandbySwitch(controller))
|
entities.append(RachioStandbySwitch(controller))
|
||||||
|
entities.append(RachioRainDelay(controller))
|
||||||
zones = controller.list_zones()
|
zones = controller.list_zones()
|
||||||
schedules = controller.list_schedules()
|
schedules = controller.list_schedules()
|
||||||
flex_schedules = controller.list_flex_schedules()
|
flex_schedules = controller.list_flex_schedules()
|
||||||
|
@ -179,6 +185,72 @@ class RachioStandbySwitch(RachioSwitch):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RachioRainDelay(RachioSwitch):
|
||||||
|
"""Representation of a rain delay status/switch."""
|
||||||
|
|
||||||
|
def __init__(self, controller):
|
||||||
|
"""Instantiate a new Rachio rain delay switch."""
|
||||||
|
super().__init__(controller, poll=True)
|
||||||
|
self._poll_update(controller.init_data)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
"""Return the name of the switch."""
|
||||||
|
return f"{self._controller.name} rain delay"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self) -> str:
|
||||||
|
"""Return a unique id by combining controller id and purpose."""
|
||||||
|
return f"{self._controller.controller_id}-delay"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def icon(self) -> str:
|
||||||
|
"""Return an icon for rain delay."""
|
||||||
|
return "mdi:camera-timer"
|
||||||
|
|
||||||
|
def _poll_update(self, data=None) -> bool:
|
||||||
|
"""Request the state from the API."""
|
||||||
|
# API returns either 0 or current UNIX time when rain delay was canceled
|
||||||
|
# depending if it was done from the app or via the API
|
||||||
|
if data is None:
|
||||||
|
data = self._controller.rachio.device.get(self._controller.controller_id)[1]
|
||||||
|
|
||||||
|
try:
|
||||||
|
return data[KEY_RAIN_DELAY] / 1000 > as_timestamp(now())
|
||||||
|
except KeyError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_handle_update(self, *args, **kwargs) -> None:
|
||||||
|
"""Update the state using webhook data."""
|
||||||
|
if args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_DELAY_ON:
|
||||||
|
self._state = True
|
||||||
|
elif args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_DELAY_OFF:
|
||||||
|
self._state = False
|
||||||
|
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
def turn_on(self, **kwargs) -> None:
|
||||||
|
"""Activate a 24 hour rain delay on the controller."""
|
||||||
|
self._controller.rachio.device.rainDelay(self._controller.controller_id, 86400)
|
||||||
|
_LOGGER.debug("Starting rain delay for 24 hours")
|
||||||
|
|
||||||
|
def turn_off(self, **kwargs) -> None:
|
||||||
|
"""Resume controller functionality."""
|
||||||
|
self._controller.rachio.device.rainDelay(self._controller.controller_id, 0)
|
||||||
|
_LOGGER.debug("Canceling rain delay")
|
||||||
|
|
||||||
|
async def async_added_to_hass(self):
|
||||||
|
"""Subscribe to updates."""
|
||||||
|
self.async_on_remove(
|
||||||
|
async_dispatcher_connect(
|
||||||
|
self.hass,
|
||||||
|
SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
|
||||||
|
self._async_handle_any_update,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class RachioZone(RachioSwitch):
|
class RachioZone(RachioSwitch):
|
||||||
"""Representation of one zone of sprinklers connected to the Rachio Iro."""
|
"""Representation of one zone of sprinklers connected to the Rachio Iro."""
|
||||||
|
|
||||||
|
@ -320,7 +392,7 @@ class RachioSchedule(RachioSwitch):
|
||||||
@property
|
@property
|
||||||
def icon(self) -> str:
|
def icon(self) -> str:
|
||||||
"""Return the icon to display."""
|
"""Return the icon to display."""
|
||||||
return "mdi:water"
|
return "mdi:water" if self.schedule_is_enabled else "mdi:water-off"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self) -> dict:
|
def device_state_attributes(self) -> dict:
|
||||||
|
|
|
@ -15,6 +15,7 @@ from .const import (
|
||||||
KEY_EXTERNAL_ID,
|
KEY_EXTERNAL_ID,
|
||||||
KEY_TYPE,
|
KEY_TYPE,
|
||||||
SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
||||||
|
SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
|
||||||
SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
||||||
SIGNAL_RACHIO_ZONE_UPDATE,
|
SIGNAL_RACHIO_ZONE_UPDATE,
|
||||||
)
|
)
|
||||||
|
@ -30,6 +31,9 @@ SUBTYPE_SLEEP_MODE_OFF = "SLEEP_MODE_OFF"
|
||||||
SUBTYPE_BROWNOUT_VALVE = "BROWNOUT_VALVE"
|
SUBTYPE_BROWNOUT_VALVE = "BROWNOUT_VALVE"
|
||||||
SUBTYPE_RAIN_SENSOR_DETECTION_ON = "RAIN_SENSOR_DETECTION_ON"
|
SUBTYPE_RAIN_SENSOR_DETECTION_ON = "RAIN_SENSOR_DETECTION_ON"
|
||||||
SUBTYPE_RAIN_SENSOR_DETECTION_OFF = "RAIN_SENSOR_DETECTION_OFF"
|
SUBTYPE_RAIN_SENSOR_DETECTION_OFF = "RAIN_SENSOR_DETECTION_OFF"
|
||||||
|
|
||||||
|
# Rain delay values
|
||||||
|
TYPE_RAIN_DELAY_STATUS = "RAIN_DELAY"
|
||||||
SUBTYPE_RAIN_DELAY_ON = "RAIN_DELAY_ON"
|
SUBTYPE_RAIN_DELAY_ON = "RAIN_DELAY_ON"
|
||||||
SUBTYPE_RAIN_DELAY_OFF = "RAIN_DELAY_OFF"
|
SUBTYPE_RAIN_DELAY_OFF = "RAIN_DELAY_OFF"
|
||||||
|
|
||||||
|
@ -55,6 +59,7 @@ SUBTYPE_ZONE_CYCLING_COMPLETED = "ZONE_CYCLING_COMPLETED"
|
||||||
LISTEN_EVENT_TYPES = [
|
LISTEN_EVENT_TYPES = [
|
||||||
"DEVICE_STATUS_EVENT",
|
"DEVICE_STATUS_EVENT",
|
||||||
"ZONE_STATUS_EVENT",
|
"ZONE_STATUS_EVENT",
|
||||||
|
"RAIN_DELAY_EVENT",
|
||||||
"SCHEDULE_STATUS_EVENT",
|
"SCHEDULE_STATUS_EVENT",
|
||||||
]
|
]
|
||||||
WEBHOOK_CONST_ID = "homeassistant.rachio:"
|
WEBHOOK_CONST_ID = "homeassistant.rachio:"
|
||||||
|
@ -62,6 +67,7 @@ WEBHOOK_PATH = URL_API + DOMAIN
|
||||||
|
|
||||||
SIGNAL_MAP = {
|
SIGNAL_MAP = {
|
||||||
TYPE_CONTROLLER_STATUS: SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
TYPE_CONTROLLER_STATUS: SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
||||||
|
TYPE_RAIN_DELAY_STATUS: SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
|
||||||
TYPE_SCHEDULE_STATUS: SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
TYPE_SCHEDULE_STATUS: SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
||||||
TYPE_ZONE_STATUS: SIGNAL_RACHIO_ZONE_UPDATE,
|
TYPE_ZONE_STATUS: SIGNAL_RACHIO_ZONE_UPDATE,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue