2019-04-03 15:40:03 +00:00
|
|
|
"""This component provides support for RainMachine programs and zones."""
|
2021-04-20 15:40:41 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from collections.abc import Coroutine
|
2019-03-13 14:19:26 +00:00
|
|
|
from datetime import datetime
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
from regenmaschine.controller import Controller
|
2019-12-05 05:12:44 +00:00
|
|
|
from regenmaschine.errors import RequestError
|
2021-01-04 19:01:14 +00:00
|
|
|
import voluptuous as vol
|
2019-12-05 05:12:44 +00:00
|
|
|
|
2020-04-26 16:50:37 +00:00
|
|
|
from homeassistant.components.switch import SwitchEntity
|
2020-11-06 09:58:50 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
2019-03-21 05:56:46 +00:00
|
|
|
from homeassistant.const import ATTR_ID
|
2020-11-06 09:58:50 +00:00
|
|
|
from homeassistant.core import HomeAssistant, callback
|
2021-01-04 19:01:14 +00:00
|
|
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
2021-04-30 18:38:59 +00:00
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
2020-11-06 09:58:50 +00:00
|
|
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
from . import RainMachineEntity, async_update_programs_and_zones
|
2020-01-26 03:27:35 +00:00
|
|
|
from .const import (
|
2020-10-28 21:52:42 +00:00
|
|
|
CONF_ZONE_RUN_TIME,
|
2020-11-06 09:58:50 +00:00
|
|
|
DATA_CONTROLLER,
|
|
|
|
DATA_COORDINATOR,
|
2020-01-26 03:27:35 +00:00
|
|
|
DATA_PROGRAMS,
|
|
|
|
DATA_ZONES,
|
2021-01-04 19:01:14 +00:00
|
|
|
DEFAULT_ZONE_RUN,
|
2020-11-06 09:58:50 +00:00
|
|
|
DOMAIN,
|
|
|
|
LOGGER,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2019-03-21 05:56:46 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_AREA = "area"
|
|
|
|
ATTR_CS_ON = "cs_on"
|
|
|
|
ATTR_CURRENT_CYCLE = "current_cycle"
|
|
|
|
ATTR_CYCLES = "cycles"
|
|
|
|
ATTR_DELAY = "delay"
|
|
|
|
ATTR_DELAY_ON = "delay_on"
|
|
|
|
ATTR_FIELD_CAPACITY = "field_capacity"
|
2020-06-02 03:49:02 +00:00
|
|
|
ATTR_NEXT_RUN = "next_run"
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_NO_CYCLES = "number_of_cycles"
|
|
|
|
ATTR_PRECIP_RATE = "sprinkler_head_precipitation_rate"
|
|
|
|
ATTR_RESTRICTIONS = "restrictions"
|
|
|
|
ATTR_SLOPE = "slope"
|
|
|
|
ATTR_SOAK = "soak"
|
|
|
|
ATTR_SOIL_TYPE = "soil_type"
|
|
|
|
ATTR_SPRINKLER_TYPE = "sprinkler_head_type"
|
|
|
|
ATTR_STATUS = "status"
|
|
|
|
ATTR_SUN_EXPOSURE = "sun_exposure"
|
2020-06-02 03:49:02 +00:00
|
|
|
ATTR_TIME_REMAINING = "time_remaining"
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_VEGETATION_TYPE = "vegetation_type"
|
|
|
|
ATTR_ZONES = "zones"
|
|
|
|
|
2021-01-04 19:01:14 +00:00
|
|
|
CONF_PROGRAM_ID = "program_id"
|
|
|
|
CONF_SECONDS = "seconds"
|
|
|
|
CONF_ZONE_ID = "zone_id"
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
|
|
|
|
|
2020-08-22 21:19:20 +00:00
|
|
|
RUN_STATUS_MAP = {0: "Not Running", 1: "Running", 2: "Queued"}
|
2018-05-08 22:10:03 +00:00
|
|
|
|
|
|
|
SOIL_TYPE_MAP = {
|
2019-07-31 19:25:30 +00:00
|
|
|
0: "Not Set",
|
|
|
|
1: "Clay Loam",
|
|
|
|
2: "Silty Clay",
|
|
|
|
3: "Clay",
|
|
|
|
4: "Loam",
|
|
|
|
5: "Sandy Loam",
|
|
|
|
6: "Loamy Sand",
|
|
|
|
7: "Sand",
|
|
|
|
8: "Sandy Clay",
|
|
|
|
9: "Silt Loam",
|
|
|
|
10: "Silt",
|
|
|
|
99: "Other",
|
2018-05-08 22:10:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SLOPE_TYPE_MAP = {
|
2019-07-31 19:25:30 +00:00
|
|
|
0: "Not Set",
|
|
|
|
1: "Flat",
|
|
|
|
2: "Moderate",
|
|
|
|
3: "High",
|
|
|
|
4: "Very High",
|
|
|
|
99: "Other",
|
2018-05-08 22:10:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SPRINKLER_TYPE_MAP = {
|
2019-07-31 19:25:30 +00:00
|
|
|
0: "Not Set",
|
|
|
|
1: "Popup Spray",
|
|
|
|
2: "Rotors",
|
|
|
|
3: "Surface Drip",
|
|
|
|
4: "Bubblers Drip",
|
2021-06-29 08:20:11 +00:00
|
|
|
5: "Rotors High Rate",
|
2019-07-31 19:25:30 +00:00
|
|
|
99: "Other",
|
2018-05-08 22:10:03 +00:00
|
|
|
}
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
SUN_EXPOSURE_MAP = {0: "Not Set", 1: "Full Sun", 2: "Partial Shade", 3: "Full Shade"}
|
2018-05-08 22:10:03 +00:00
|
|
|
|
|
|
|
VEGETATION_MAP = {
|
2019-07-31 19:25:30 +00:00
|
|
|
0: "Not Set",
|
2021-06-29 08:20:11 +00:00
|
|
|
1: "Not Set",
|
2019-07-31 19:25:30 +00:00
|
|
|
2: "Cool Season Grass",
|
|
|
|
3: "Fruit Trees",
|
|
|
|
4: "Flowers",
|
|
|
|
5: "Vegetables",
|
|
|
|
6: "Citrus",
|
|
|
|
7: "Trees and Bushes",
|
|
|
|
9: "Drought Tolerant Plants",
|
|
|
|
10: "Warm Season Grass",
|
|
|
|
99: "Other",
|
2018-05-08 22:10:03 +00:00
|
|
|
}
|
|
|
|
|
2020-01-26 03:27:35 +00:00
|
|
|
SWITCH_TYPE_PROGRAM = "program"
|
|
|
|
SWITCH_TYPE_ZONE = "zone"
|
|
|
|
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
async def async_setup_entry(
|
2021-04-30 18:38:59 +00:00
|
|
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
2020-11-06 09:58:50 +00:00
|
|
|
) -> None:
|
2018-11-14 20:23:49 +00:00
|
|
|
"""Set up RainMachine switches based on a config entry."""
|
2021-05-03 16:34:28 +00:00
|
|
|
platform = entity_platform.async_get_current_platform()
|
2021-01-04 19:01:14 +00:00
|
|
|
|
|
|
|
alter_program_schema = {vol.Required(CONF_PROGRAM_ID): cv.positive_int}
|
|
|
|
alter_zone_schema = {vol.Required(CONF_ZONE_ID): cv.positive_int}
|
|
|
|
|
|
|
|
for service_name, schema, method in [
|
|
|
|
("disable_program", alter_program_schema, "async_disable_program"),
|
|
|
|
("disable_zone", alter_zone_schema, "async_disable_zone"),
|
|
|
|
("enable_program", alter_program_schema, "async_enable_program"),
|
|
|
|
("enable_zone", alter_zone_schema, "async_enable_zone"),
|
|
|
|
(
|
|
|
|
"pause_watering",
|
|
|
|
{vol.Required(CONF_SECONDS): cv.positive_int},
|
|
|
|
"async_pause_watering",
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"start_program",
|
|
|
|
{vol.Required(CONF_PROGRAM_ID): cv.positive_int},
|
|
|
|
"async_start_program",
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"start_zone",
|
|
|
|
{
|
|
|
|
vol.Required(CONF_ZONE_ID): cv.positive_int,
|
|
|
|
vol.Optional(
|
|
|
|
CONF_ZONE_RUN_TIME, default=DEFAULT_ZONE_RUN
|
|
|
|
): cv.positive_int,
|
|
|
|
},
|
|
|
|
"async_start_zone",
|
|
|
|
),
|
|
|
|
("stop_all", {}, "async_stop_all"),
|
|
|
|
(
|
|
|
|
"stop_program",
|
|
|
|
{vol.Required(CONF_PROGRAM_ID): cv.positive_int},
|
|
|
|
"async_stop_program",
|
|
|
|
),
|
|
|
|
("stop_zone", {vol.Required(CONF_ZONE_ID): cv.positive_int}, "async_stop_zone"),
|
|
|
|
("unpause_watering", {}, "async_unpause_watering"),
|
|
|
|
]:
|
|
|
|
platform.async_register_entity_service(service_name, schema, method)
|
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
controller = hass.data[DOMAIN][DATA_CONTROLLER][entry.entry_id]
|
|
|
|
programs_coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][
|
|
|
|
DATA_PROGRAMS
|
|
|
|
]
|
|
|
|
zones_coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][DATA_ZONES]
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2018-04-28 13:46:58 +00:00
|
|
|
entities = []
|
2020-11-06 09:58:50 +00:00
|
|
|
for uid, program in programs_coordinator.data.items():
|
|
|
|
entities.append(
|
|
|
|
RainMachineProgram(
|
|
|
|
programs_coordinator, controller, uid, program["name"], entry
|
|
|
|
)
|
|
|
|
)
|
|
|
|
for uid, zone in zones_coordinator.data.items():
|
|
|
|
entities.append(
|
|
|
|
RainMachineZone(zones_coordinator, controller, uid, zone["name"], entry)
|
|
|
|
)
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
async_add_entities(entities)
|
2017-08-08 07:49:25 +00:00
|
|
|
|
|
|
|
|
2020-04-26 16:50:37 +00:00
|
|
|
class RainMachineSwitch(RainMachineEntity, SwitchEntity):
|
2018-05-29 19:02:16 +00:00
|
|
|
"""A class to represent a generic RainMachine switch."""
|
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
coordinator: DataUpdateCoordinator,
|
|
|
|
controller: Controller,
|
|
|
|
uid: int,
|
|
|
|
name: str,
|
|
|
|
entry: ConfigEntry,
|
|
|
|
) -> None:
|
2018-05-29 19:02:16 +00:00
|
|
|
"""Initialize a generic RainMachine switch."""
|
2020-11-06 09:58:50 +00:00
|
|
|
super().__init__(coordinator, controller)
|
|
|
|
self._data = coordinator.data[uid]
|
|
|
|
self._entry = entry
|
|
|
|
self._is_active = True
|
2020-01-26 03:27:35 +00:00
|
|
|
self._is_on = False
|
2020-11-06 09:58:50 +00:00
|
|
|
self._name = name
|
|
|
|
self._switch_type = type(self).__name__
|
|
|
|
self._uid = uid
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2019-03-13 14:19:26 +00:00
|
|
|
@property
|
|
|
|
def available(self) -> bool:
|
|
|
|
"""Return True if entity is available."""
|
2020-11-06 09:58:50 +00:00
|
|
|
return self._is_active and self.coordinator.last_update_success
|
2019-03-13 14:19:26 +00:00
|
|
|
|
2018-05-29 19:02:16 +00:00
|
|
|
@property
|
|
|
|
def icon(self) -> str:
|
|
|
|
"""Return the icon."""
|
2019-07-31 19:25:30 +00:00
|
|
|
return "mdi:water"
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-01-26 03:27:35 +00:00
|
|
|
@property
|
|
|
|
def is_on(self) -> bool:
|
|
|
|
"""Return whether the program is running."""
|
|
|
|
return self._is_on
|
|
|
|
|
2018-05-29 19:02:16 +00:00
|
|
|
@property
|
|
|
|
def unique_id(self) -> str:
|
2020-01-05 12:09:17 +00:00
|
|
|
"""Return a unique, Home Assistant friendly identifier for this entity."""
|
2020-11-06 09:58:50 +00:00
|
|
|
return f"{self._unique_id}_{self._switch_type}_{self._uid}"
|
2018-05-29 19:02:16 +00:00
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
async def _async_run_switch_coroutine(self, api_coro: Coroutine) -> None:
|
2020-01-26 03:27:35 +00:00
|
|
|
"""Run a coroutine to toggle the switch."""
|
|
|
|
try:
|
|
|
|
resp = await api_coro
|
|
|
|
except RequestError as err:
|
2020-11-06 09:58:50 +00:00
|
|
|
LOGGER.error(
|
2020-01-26 03:27:35 +00:00
|
|
|
'Error while toggling %s "%s": %s',
|
|
|
|
self._switch_type,
|
|
|
|
self.unique_id,
|
|
|
|
err,
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
|
|
|
if resp["statusCode"] != 0:
|
2020-11-06 09:58:50 +00:00
|
|
|
LOGGER.error(
|
2020-01-26 03:27:35 +00:00
|
|
|
'Error while toggling %s "%s": %s',
|
|
|
|
self._switch_type,
|
|
|
|
self.unique_id,
|
|
|
|
resp["message"],
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
# Because of how inextricably linked programs and zones are, anytime one is
|
|
|
|
# toggled, we make sure to update the data of both coordinators:
|
|
|
|
self.hass.async_create_task(
|
|
|
|
async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
)
|
|
|
|
|
2021-01-04 19:01:14 +00:00
|
|
|
async def async_disable_program(self, *, program_id):
|
|
|
|
"""Disable a program."""
|
|
|
|
await self._controller.programs.disable(program_id)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_disable_zone(self, *, zone_id):
|
|
|
|
"""Disable a zone."""
|
|
|
|
await self._controller.zones.disable(zone_id)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_enable_program(self, *, program_id):
|
|
|
|
"""Enable a program."""
|
|
|
|
await self._controller.programs.enable(program_id)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_enable_zone(self, *, zone_id):
|
|
|
|
"""Enable a zone."""
|
|
|
|
await self._controller.zones.enable(zone_id)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_pause_watering(self, *, seconds):
|
|
|
|
"""Pause watering for a set number of seconds."""
|
|
|
|
await self._controller.watering.pause_all(seconds)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_start_program(self, *, program_id):
|
|
|
|
"""Start a particular program."""
|
|
|
|
await self._controller.programs.start(program_id)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_start_zone(self, *, zone_id, zone_run_time):
|
|
|
|
"""Start a particular zone for a certain amount of time."""
|
|
|
|
await self._controller.zones.start(zone_id, zone_run_time)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_stop_all(self):
|
|
|
|
"""Stop all watering."""
|
|
|
|
await self._controller.watering.stop_all()
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_stop_program(self, *, program_id):
|
|
|
|
"""Stop a program."""
|
|
|
|
await self._controller.programs.stop(program_id)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_stop_zone(self, *, zone_id):
|
|
|
|
"""Stop a zone."""
|
|
|
|
await self._controller.zones.stop(zone_id)
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
|
|
|
async def async_unpause_watering(self):
|
|
|
|
"""Unpause watering."""
|
|
|
|
await self._controller.watering.unpause_all()
|
|
|
|
await async_update_programs_and_zones(self.hass, self._entry)
|
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
@callback
|
|
|
|
def update_from_latest_data(self) -> None:
|
|
|
|
"""Update the state."""
|
|
|
|
self._data = self.coordinator.data[self._uid]
|
|
|
|
self._is_active = self._data["active"]
|
2018-06-10 08:23:07 +00:00
|
|
|
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2018-05-08 22:10:03 +00:00
|
|
|
class RainMachineProgram(RainMachineSwitch):
|
2017-08-08 07:49:25 +00:00
|
|
|
"""A RainMachine program."""
|
|
|
|
|
2018-02-12 03:55:51 +00:00
|
|
|
@property
|
2018-05-08 22:10:03 +00:00
|
|
|
def zones(self) -> list:
|
|
|
|
"""Return a list of active zones associated with this program."""
|
2020-11-06 09:58:50 +00:00
|
|
|
return [z for z in self._data["wateringTimes"] if z["active"]]
|
2018-11-14 20:23:49 +00:00
|
|
|
|
2018-06-10 08:23:07 +00:00
|
|
|
async def async_turn_off(self, **kwargs) -> None:
|
2017-08-08 07:49:25 +00:00
|
|
|
"""Turn the program off."""
|
2020-01-26 03:27:35 +00:00
|
|
|
await self._async_run_switch_coroutine(
|
2020-11-06 09:58:50 +00:00
|
|
|
self._controller.programs.stop(self._uid)
|
2020-01-26 03:27:35 +00:00
|
|
|
)
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2018-06-10 08:23:07 +00:00
|
|
|
async def async_turn_on(self, **kwargs) -> None:
|
2017-08-08 07:49:25 +00:00
|
|
|
"""Turn the program on."""
|
2020-01-26 03:27:35 +00:00
|
|
|
await self._async_run_switch_coroutine(
|
2020-11-06 09:58:50 +00:00
|
|
|
self._controller.programs.start(self._uid)
|
2020-01-26 03:27:35 +00:00
|
|
|
)
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-03-17 11:00:54 +00:00
|
|
|
@callback
|
|
|
|
def update_from_latest_data(self) -> None:
|
2020-11-06 09:58:50 +00:00
|
|
|
"""Update the state."""
|
|
|
|
super().update_from_latest_data()
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
self._is_on = bool(self._data["status"])
|
2018-05-08 22:10:03 +00:00
|
|
|
|
2020-11-06 09:58:50 +00:00
|
|
|
if self._data.get("nextRun") is not None:
|
2020-01-26 03:27:35 +00:00
|
|
|
next_run = datetime.strptime(
|
2020-11-06 09:58:50 +00:00
|
|
|
f"{self._data['nextRun']} {self._data['startTime']}",
|
2020-01-26 03:27:35 +00:00
|
|
|
"%Y-%m-%d %H:%M",
|
|
|
|
).isoformat()
|
2020-11-06 09:58:50 +00:00
|
|
|
else:
|
2020-01-26 03:27:35 +00:00
|
|
|
next_run = None
|
|
|
|
|
|
|
|
self._attrs.update(
|
|
|
|
{
|
2020-11-06 09:58:50 +00:00
|
|
|
ATTR_ID: self._uid,
|
2020-01-26 03:27:35 +00:00
|
|
|
ATTR_NEXT_RUN: next_run,
|
2020-11-06 09:58:50 +00:00
|
|
|
ATTR_SOAK: self.coordinator.data[self._uid].get("soak"),
|
|
|
|
ATTR_STATUS: RUN_STATUS_MAP[self.coordinator.data[self._uid]["status"]],
|
2020-01-26 03:27:35 +00:00
|
|
|
ATTR_ZONES: ", ".join(z["name"] for z in self.zones),
|
|
|
|
}
|
|
|
|
)
|
2017-08-08 07:49:25 +00:00
|
|
|
|
|
|
|
|
2018-05-08 22:10:03 +00:00
|
|
|
class RainMachineZone(RainMachineSwitch):
|
2017-08-08 07:49:25 +00:00
|
|
|
"""A RainMachine zone."""
|
|
|
|
|
2018-06-10 08:23:07 +00:00
|
|
|
async def async_turn_off(self, **kwargs) -> None:
|
2017-08-08 07:49:25 +00:00
|
|
|
"""Turn the zone off."""
|
2020-11-06 09:58:50 +00:00
|
|
|
await self._async_run_switch_coroutine(self._controller.zones.stop(self._uid))
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2018-06-10 08:23:07 +00:00
|
|
|
async def async_turn_on(self, **kwargs) -> None:
|
2017-08-08 07:49:25 +00:00
|
|
|
"""Turn the zone on."""
|
2020-01-26 03:27:35 +00:00
|
|
|
await self._async_run_switch_coroutine(
|
2020-11-06 09:58:50 +00:00
|
|
|
self._controller.zones.start(
|
|
|
|
self._uid,
|
|
|
|
self._entry.options[CONF_ZONE_RUN_TIME],
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2020-01-26 03:27:35 +00:00
|
|
|
)
|
2017-08-08 07:49:25 +00:00
|
|
|
|
2020-03-17 11:00:54 +00:00
|
|
|
@callback
|
|
|
|
def update_from_latest_data(self) -> None:
|
2020-11-06 09:58:50 +00:00
|
|
|
"""Update the state."""
|
|
|
|
super().update_from_latest_data()
|
|
|
|
|
|
|
|
self._is_on = bool(self._data["state"])
|
2020-01-26 03:27:35 +00:00
|
|
|
|
|
|
|
self._attrs.update(
|
|
|
|
{
|
2020-11-06 09:58:50 +00:00
|
|
|
ATTR_STATUS: RUN_STATUS_MAP[self._data["state"]],
|
|
|
|
ATTR_AREA: self._data.get("waterSense").get("area"),
|
|
|
|
ATTR_CURRENT_CYCLE: self._data.get("cycle"),
|
|
|
|
ATTR_FIELD_CAPACITY: self._data.get("waterSense").get("fieldCapacity"),
|
|
|
|
ATTR_ID: self._data["uid"],
|
|
|
|
ATTR_NO_CYCLES: self._data.get("noOfCycles"),
|
|
|
|
ATTR_PRECIP_RATE: self._data.get("waterSense").get("precipitationRate"),
|
|
|
|
ATTR_RESTRICTIONS: self._data.get("restriction"),
|
|
|
|
ATTR_SLOPE: SLOPE_TYPE_MAP.get(self._data.get("slope")),
|
2021-06-29 08:09:38 +00:00
|
|
|
ATTR_SOIL_TYPE: SOIL_TYPE_MAP.get(self._data.get("soil")),
|
2020-11-06 09:58:50 +00:00
|
|
|
ATTR_SPRINKLER_TYPE: SPRINKLER_TYPE_MAP.get(self._data.get("group_id")),
|
|
|
|
ATTR_SUN_EXPOSURE: SUN_EXPOSURE_MAP.get(self._data.get("sun")),
|
|
|
|
ATTR_TIME_REMAINING: self._data.get("remaining"),
|
|
|
|
ATTR_VEGETATION_TYPE: VEGETATION_MAP.get(self._data.get("type")),
|
2020-01-26 03:27:35 +00:00
|
|
|
}
|
|
|
|
)
|