mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Add Rachio Schedules (#33421)
* Add Rachio Scheudles * Add Rachio Schedules * Revert "Add Rachio Schedules" This reverts commit ffe1e3d1c231703804077417acc4e7fbe837e98a. * Revert "Add Rachio Scheudles" This reverts commit a015ec4a1994e40981d3642097caf0b5a305533c. * Add Rachio Schedules * Update Logger * Remove person * Remove unneeded call * Black * Fix typo * fix lint * Replace old commits * Revert "Replace old commits" This reverts commit cc8a2a332a0dd9b9a49af30a22490e27bf31b45e. * Replace Schedules * Fix Tests * Missing unsubscribe * Update homeassistant/components/rachio/switch.py Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
fbd197146a
commit
775010f160
@ -22,6 +22,7 @@ KEY_ID = "id"
|
||||
KEY_NAME = "name"
|
||||
KEY_MODEL = "model"
|
||||
KEY_ON = "on"
|
||||
KEY_DURATION = "totalDuration"
|
||||
KEY_STATUS = "status"
|
||||
KEY_SUBTYPE = "subType"
|
||||
KEY_SUMMARY = "summary"
|
||||
@ -33,6 +34,8 @@ KEY_USERNAME = "username"
|
||||
KEY_ZONE_ID = "zoneId"
|
||||
KEY_ZONE_NUMBER = "zoneNumber"
|
||||
KEY_ZONES = "zones"
|
||||
KEY_SCHEDULES = "scheduleRules"
|
||||
KEY_SCHEDULE_ID = "scheduleId"
|
||||
KEY_CUSTOM_SHADE = "customShade"
|
||||
KEY_CUSTOM_CROP = "customCrop"
|
||||
|
||||
|
@ -13,6 +13,7 @@ from .const import (
|
||||
KEY_MAC_ADDRESS,
|
||||
KEY_MODEL,
|
||||
KEY_NAME,
|
||||
KEY_SCHEDULES,
|
||||
KEY_SERIAL_NUMBER,
|
||||
KEY_STATUS,
|
||||
KEY_USERNAME,
|
||||
@ -90,6 +91,7 @@ class RachioIro:
|
||||
self.mac_address = data[KEY_MAC_ADDRESS]
|
||||
self.model = data[KEY_MODEL]
|
||||
self._zones = data[KEY_ZONES]
|
||||
self._schedules = data[KEY_SCHEDULES]
|
||||
self._init_data = data
|
||||
self._webhooks = webhooks
|
||||
_LOGGER.debug('%s has ID "%s"', str(self), self.controller_id)
|
||||
@ -174,6 +176,10 @@ class RachioIro:
|
||||
|
||||
return None
|
||||
|
||||
def list_schedules(self) -> list:
|
||||
"""Return a list of schedules."""
|
||||
return self._schedules
|
||||
|
||||
def stop_watering(self) -> None:
|
||||
"""Stop watering all zones connected to this controller."""
|
||||
self.rachio.device.stopWater(self.controller_id)
|
||||
|
@ -15,20 +15,26 @@ from .const import (
|
||||
KEY_CUSTOM_CROP,
|
||||
KEY_CUSTOM_SHADE,
|
||||
KEY_DEVICE_ID,
|
||||
KEY_DURATION,
|
||||
KEY_ENABLED,
|
||||
KEY_ID,
|
||||
KEY_IMAGE_URL,
|
||||
KEY_NAME,
|
||||
KEY_ON,
|
||||
KEY_SCHEDULE_ID,
|
||||
KEY_SUBTYPE,
|
||||
KEY_SUMMARY,
|
||||
KEY_ZONE_ID,
|
||||
KEY_ZONE_NUMBER,
|
||||
SIGNAL_RACHIO_CONTROLLER_UPDATE,
|
||||
SIGNAL_RACHIO_SCHEDULE_UPDATE,
|
||||
SIGNAL_RACHIO_ZONE_UPDATE,
|
||||
)
|
||||
from .entity import RachioDevice
|
||||
from .webhooks import (
|
||||
SUBTYPE_SCHEDULE_COMPLETED,
|
||||
SUBTYPE_SCHEDULE_STARTED,
|
||||
SUBTYPE_SCHEDULE_STOPPED,
|
||||
SUBTYPE_SLEEP_MODE_OFF,
|
||||
SUBTYPE_SLEEP_MODE_ON,
|
||||
SUBTYPE_ZONE_COMPLETED,
|
||||
@ -40,6 +46,9 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_ZONE_SUMMARY = "Summary"
|
||||
ATTR_ZONE_NUMBER = "Zone number"
|
||||
ATTR_SCHEDULE_SUMMARY = "Summary"
|
||||
ATTR_SCHEDULE_ENABLED = "Enabled"
|
||||
ATTR_SCHEDULE_DURATION = "Duration"
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
@ -58,11 +67,14 @@ def _create_entities(hass, config_entry):
|
||||
for controller in person.controllers:
|
||||
entities.append(RachioStandbySwitch(controller))
|
||||
zones = controller.list_zones()
|
||||
schedules = controller.list_schedules()
|
||||
current_schedule = controller.current_schedule
|
||||
_LOGGER.debug("Rachio setting up zones: %s", zones)
|
||||
for zone in zones:
|
||||
_LOGGER.debug("Rachio setting up zone: %s", zone)
|
||||
entities.append(RachioZone(person, controller, zone, current_schedule))
|
||||
for sched in schedules:
|
||||
_LOGGER.debug("Added schedule: %s", sched)
|
||||
entities.append(RachioSchedule(person, controller, sched, current_schedule))
|
||||
return entities
|
||||
|
||||
|
||||
@ -276,3 +288,98 @@ class RachioZone(RachioSwitch):
|
||||
"""Unsubscribe from updates."""
|
||||
if self._undo_dispatcher:
|
||||
self._undo_dispatcher()
|
||||
|
||||
|
||||
class RachioSchedule(RachioSwitch):
|
||||
"""Representation of one fixed schedule on the Rachio Iro."""
|
||||
|
||||
def __init__(self, person, controller, data, current_schedule):
|
||||
"""Initialize a new Rachio Schedule."""
|
||||
self._id = data[KEY_ID]
|
||||
self._schedule_name = data[KEY_NAME]
|
||||
self._duration = data[KEY_DURATION]
|
||||
self._schedule_enabled = data[KEY_ENABLED]
|
||||
self._summary = data[KEY_SUMMARY]
|
||||
self._current_schedule = current_schedule
|
||||
super().__init__(controller, poll=False)
|
||||
self._state = self.schedule_id == self._current_schedule.get(KEY_SCHEDULE_ID)
|
||||
self._undo_dispatcher = None
|
||||
|
||||
@property
|
||||
def schedule_id(self) -> str:
|
||||
"""How the Rachio API refers to the schedule."""
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the friendly name of the schedule."""
|
||||
return f"{self._schedule_name} Schedule"
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique id by combining controller id and schedule."""
|
||||
return f"{self._controller.controller_id}-schedule-{self.schedule_id}"
|
||||
|
||||
@property
|
||||
def icon(self) -> str:
|
||||
"""Return the icon to display."""
|
||||
return "mdi:water"
|
||||
|
||||
@property
|
||||
def device_state_attributes(self) -> dict:
|
||||
"""Return the optional state attributes."""
|
||||
return {
|
||||
ATTR_SCHEDULE_SUMMARY: self._summary,
|
||||
ATTR_SCHEDULE_ENABLED: self.schedule_is_enabled,
|
||||
ATTR_SCHEDULE_DURATION: self._duration / 60,
|
||||
}
|
||||
|
||||
@property
|
||||
def schedule_is_enabled(self) -> bool:
|
||||
"""Return whether the schedule is allowed to run."""
|
||||
return self._schedule_enabled
|
||||
|
||||
def turn_on(self, **kwargs) -> None:
|
||||
"""Start this schedule."""
|
||||
|
||||
self._controller.rachio.schedulerule.start(self.schedule_id)
|
||||
_LOGGER.debug(
|
||||
"Schedule %s started on %s", self.name, self._controller.name,
|
||||
)
|
||||
|
||||
def turn_off(self, **kwargs) -> None:
|
||||
"""Stop watering all zones."""
|
||||
self._controller.stop_watering()
|
||||
|
||||
def _poll_update(self, data=None) -> bool:
|
||||
"""Poll the API to check whether the schedule is running."""
|
||||
self._current_schedule = self._controller.current_schedule
|
||||
return self.schedule_id == self._current_schedule.get(KEY_SCHEDULE_ID)
|
||||
|
||||
def _handle_update(self, *args, **kwargs) -> None:
|
||||
"""Handle incoming webhook schedule data."""
|
||||
# Schedule ID not passed when running individual zones, so we catch that error
|
||||
try:
|
||||
if args[0][KEY_SCHEDULE_ID] == self.schedule_id:
|
||||
if args[0][KEY_SUBTYPE] in [SUBTYPE_SCHEDULE_STARTED]:
|
||||
self._state = True
|
||||
elif args[0][KEY_SUBTYPE] in [
|
||||
SUBTYPE_SCHEDULE_STOPPED,
|
||||
SUBTYPE_SCHEDULE_COMPLETED,
|
||||
]:
|
||||
self._state = False
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Subscribe to updates."""
|
||||
self._undo_dispatcher = async_dispatcher_connect(
|
||||
self.hass, SIGNAL_RACHIO_SCHEDULE_UPDATE, self._handle_update
|
||||
)
|
||||
|
||||
async def async_will_remove_from_hass(self):
|
||||
"""Unsubscribe from updates."""
|
||||
if self._undo_dispatcher:
|
||||
self._undo_dispatcher()
|
||||
|
@ -50,7 +50,11 @@ SUBTYPE_ZONE_CYCLING = "ZONE_CYCLING"
|
||||
SUBTYPE_ZONE_CYCLING_COMPLETED = "ZONE_CYCLING_COMPLETED"
|
||||
|
||||
# Webhook callbacks
|
||||
LISTEN_EVENT_TYPES = ["DEVICE_STATUS_EVENT", "ZONE_STATUS_EVENT"]
|
||||
LISTEN_EVENT_TYPES = [
|
||||
"DEVICE_STATUS_EVENT",
|
||||
"ZONE_STATUS_EVENT",
|
||||
"SCHEDULE_STATUS_EVENT",
|
||||
]
|
||||
WEBHOOK_CONST_ID = "homeassistant.rachio:"
|
||||
WEBHOOK_PATH = URL_API + DOMAIN
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user