Finish EntityDescription implementation for RainMachine (#55180)
This commit is contained in:
parent
53851cb1b4
commit
6bc5c1c9af
6 changed files with 178 additions and 158 deletions
|
@ -845,6 +845,7 @@ omit =
|
|||
homeassistant/components/raincloud/*
|
||||
homeassistant/components/rainmachine/__init__.py
|
||||
homeassistant/components/rainmachine/binary_sensor.py
|
||||
homeassistant/components/rainmachine/model.py
|
||||
homeassistant/components/rainmachine/sensor.py
|
||||
homeassistant/components/rainmachine/switch.py
|
||||
homeassistant/components/raspihats/*
|
||||
|
|
|
@ -22,6 +22,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import aiohttp_client, config_validation as cv
|
||||
import homeassistant.helpers.device_registry as dr
|
||||
from homeassistant.helpers.entity import EntityDescription
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
|
@ -180,7 +181,7 @@ class RainMachineEntity(CoordinatorEntity):
|
|||
self,
|
||||
coordinator: DataUpdateCoordinator,
|
||||
controller: Controller,
|
||||
entity_type: str,
|
||||
description: EntityDescription,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator)
|
||||
|
@ -200,9 +201,9 @@ class RainMachineEntity(CoordinatorEntity):
|
|||
# The colons are removed from the device MAC simply because that value
|
||||
# (unnecessarily) makes up the existing unique ID formula and we want to avoid
|
||||
# a breaking change:
|
||||
self._attr_unique_id = f"{controller.mac.replace(':', '')}_{entity_type}"
|
||||
self._attr_unique_id = f"{controller.mac.replace(':', '')}_{description.key}"
|
||||
self._controller = controller
|
||||
self._entity_type = entity_type
|
||||
self.entity_description = description
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
"""This platform provides binary sensors for key RainMachine data."""
|
||||
from dataclasses import dataclass
|
||||
from functools import partial
|
||||
|
||||
from regenmaschine.controller import Controller
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorEntity,
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from . import RainMachineEntity
|
||||
from .const import (
|
||||
|
@ -18,6 +19,7 @@ from .const import (
|
|||
DATA_RESTRICTIONS_UNIVERSAL,
|
||||
DOMAIN,
|
||||
)
|
||||
from .model import RainMachineSensorDescriptionMixin
|
||||
|
||||
TYPE_FLOW_SENSOR = "flow_sensor"
|
||||
TYPE_FREEZE = "freeze"
|
||||
|
@ -29,47 +31,75 @@ TYPE_RAINDELAY = "raindelay"
|
|||
TYPE_RAINSENSOR = "rainsensor"
|
||||
TYPE_WEEKDAY = "weekday"
|
||||
|
||||
BINARY_SENSORS = {
|
||||
TYPE_FLOW_SENSOR: ("Flow Sensor", "mdi:water-pump", True, DATA_PROVISION_SETTINGS),
|
||||
TYPE_FREEZE: ("Freeze Restrictions", "mdi:cancel", True, DATA_RESTRICTIONS_CURRENT),
|
||||
TYPE_FREEZE_PROTECTION: (
|
||||
"Freeze Protection",
|
||||
"mdi:weather-snowy",
|
||||
True,
|
||||
DATA_RESTRICTIONS_UNIVERSAL,
|
||||
|
||||
@dataclass
|
||||
class RainMachineBinarySensorDescription(
|
||||
BinarySensorEntityDescription, RainMachineSensorDescriptionMixin
|
||||
):
|
||||
"""Describe a RainMachine binary sensor."""
|
||||
|
||||
|
||||
BINARY_SENSOR_DESCRIPTIONS = (
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_FLOW_SENSOR,
|
||||
name="Flow Sensor",
|
||||
icon="mdi:water-pump",
|
||||
api_category=DATA_PROVISION_SETTINGS,
|
||||
),
|
||||
TYPE_HOT_DAYS: (
|
||||
"Extra Water on Hot Days",
|
||||
"mdi:thermometer-lines",
|
||||
True,
|
||||
DATA_RESTRICTIONS_UNIVERSAL,
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_FREEZE,
|
||||
name="Freeze Restrictions",
|
||||
icon="mdi:cancel",
|
||||
api_category=DATA_RESTRICTIONS_CURRENT,
|
||||
),
|
||||
TYPE_HOURLY: (
|
||||
"Hourly Restrictions",
|
||||
"mdi:cancel",
|
||||
False,
|
||||
DATA_RESTRICTIONS_CURRENT,
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_FREEZE_PROTECTION,
|
||||
name="Freeze Protection",
|
||||
icon="mdi:weather-snowy",
|
||||
api_category=DATA_RESTRICTIONS_UNIVERSAL,
|
||||
),
|
||||
TYPE_MONTH: ("Month Restrictions", "mdi:cancel", False, DATA_RESTRICTIONS_CURRENT),
|
||||
TYPE_RAINDELAY: (
|
||||
"Rain Delay Restrictions",
|
||||
"mdi:cancel",
|
||||
False,
|
||||
DATA_RESTRICTIONS_CURRENT,
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_HOT_DAYS,
|
||||
name="Extra Water on Hot Days",
|
||||
icon="mdi:thermometer-lines",
|
||||
api_category=DATA_RESTRICTIONS_UNIVERSAL,
|
||||
),
|
||||
TYPE_RAINSENSOR: (
|
||||
"Rain Sensor Restrictions",
|
||||
"mdi:cancel",
|
||||
False,
|
||||
DATA_RESTRICTIONS_CURRENT,
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_HOURLY,
|
||||
name="Hourly Restrictions",
|
||||
icon="mdi:cancel",
|
||||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_RESTRICTIONS_CURRENT,
|
||||
),
|
||||
TYPE_WEEKDAY: (
|
||||
"Weekday Restrictions",
|
||||
"mdi:cancel",
|
||||
False,
|
||||
DATA_RESTRICTIONS_CURRENT,
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_MONTH,
|
||||
name="Month Restrictions",
|
||||
icon="mdi:cancel",
|
||||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_RESTRICTIONS_CURRENT,
|
||||
),
|
||||
}
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_RAINDELAY,
|
||||
name="Rain Delay Restrictions",
|
||||
icon="mdi:cancel",
|
||||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_RESTRICTIONS_CURRENT,
|
||||
),
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_RAINSENSOR,
|
||||
name="Rain Sensor Restrictions",
|
||||
icon="mdi:cancel",
|
||||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_RESTRICTIONS_CURRENT,
|
||||
),
|
||||
RainMachineBinarySensorDescription(
|
||||
key=TYPE_WEEKDAY,
|
||||
name="Weekday Restrictions",
|
||||
icon="mdi:cancel",
|
||||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_RESTRICTIONS_CURRENT,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
|
@ -101,74 +131,49 @@ async def async_setup_entry(
|
|||
|
||||
async_add_entities(
|
||||
[
|
||||
async_get_sensor(api_category)(
|
||||
controller, sensor_type, name, icon, enabled_by_default
|
||||
)
|
||||
for (
|
||||
sensor_type,
|
||||
(name, icon, enabled_by_default, api_category),
|
||||
) in BINARY_SENSORS.items()
|
||||
async_get_sensor(description.api_category)(controller, description)
|
||||
for description in BINARY_SENSOR_DESCRIPTIONS
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class RainMachineBinarySensor(RainMachineEntity, BinarySensorEntity):
|
||||
"""Define a general RainMachine binary sensor."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DataUpdateCoordinator,
|
||||
controller: Controller,
|
||||
sensor_type: str,
|
||||
name: str,
|
||||
icon: str,
|
||||
enabled_by_default: bool,
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(coordinator, controller, sensor_type)
|
||||
|
||||
self._attr_entity_registry_enabled_default = enabled_by_default
|
||||
self._attr_icon = icon
|
||||
self._attr_name = name
|
||||
|
||||
|
||||
class CurrentRestrictionsBinarySensor(RainMachineBinarySensor):
|
||||
class CurrentRestrictionsBinarySensor(RainMachineEntity, BinarySensorEntity):
|
||||
"""Define a binary sensor that handles current restrictions data."""
|
||||
|
||||
@callback
|
||||
def update_from_latest_data(self) -> None:
|
||||
"""Update the state."""
|
||||
if self._entity_type == TYPE_FREEZE:
|
||||
if self.entity_description.key == TYPE_FREEZE:
|
||||
self._attr_is_on = self.coordinator.data["freeze"]
|
||||
elif self._entity_type == TYPE_HOURLY:
|
||||
elif self.entity_description.key == TYPE_HOURLY:
|
||||
self._attr_is_on = self.coordinator.data["hourly"]
|
||||
elif self._entity_type == TYPE_MONTH:
|
||||
elif self.entity_description.key == TYPE_MONTH:
|
||||
self._attr_is_on = self.coordinator.data["month"]
|
||||
elif self._entity_type == TYPE_RAINDELAY:
|
||||
elif self.entity_description.key == TYPE_RAINDELAY:
|
||||
self._attr_is_on = self.coordinator.data["rainDelay"]
|
||||
elif self._entity_type == TYPE_RAINSENSOR:
|
||||
elif self.entity_description.key == TYPE_RAINSENSOR:
|
||||
self._attr_is_on = self.coordinator.data["rainSensor"]
|
||||
elif self._entity_type == TYPE_WEEKDAY:
|
||||
elif self.entity_description.key == TYPE_WEEKDAY:
|
||||
self._attr_is_on = self.coordinator.data["weekDay"]
|
||||
|
||||
|
||||
class ProvisionSettingsBinarySensor(RainMachineBinarySensor):
|
||||
class ProvisionSettingsBinarySensor(RainMachineEntity, BinarySensorEntity):
|
||||
"""Define a binary sensor that handles provisioning data."""
|
||||
|
||||
@callback
|
||||
def update_from_latest_data(self) -> None:
|
||||
"""Update the state."""
|
||||
if self._entity_type == TYPE_FLOW_SENSOR:
|
||||
if self.entity_description.key == TYPE_FLOW_SENSOR:
|
||||
self._attr_is_on = self.coordinator.data["system"].get("useFlowSensor")
|
||||
|
||||
|
||||
class UniversalRestrictionsBinarySensor(RainMachineBinarySensor):
|
||||
class UniversalRestrictionsBinarySensor(RainMachineEntity, BinarySensorEntity):
|
||||
"""Define a binary sensor that handles universal restrictions data."""
|
||||
|
||||
@callback
|
||||
def update_from_latest_data(self) -> None:
|
||||
"""Update the state."""
|
||||
if self._entity_type == TYPE_FREEZE_PROTECTION:
|
||||
if self.entity_description.key == TYPE_FREEZE_PROTECTION:
|
||||
self._attr_is_on = self.coordinator.data["freezeProtectEnabled"]
|
||||
elif self._entity_type == TYPE_HOT_DAYS:
|
||||
elif self.entity_description.key == TYPE_HOT_DAYS:
|
||||
self._attr_is_on = self.coordinator.data["hotDaysExtraWatering"]
|
||||
|
|
9
homeassistant/components/rainmachine/model.py
Normal file
9
homeassistant/components/rainmachine/model.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
"""Define RainMachine data models."""
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class RainMachineSensorDescriptionMixin:
|
||||
"""Define an entity description mixin for binary and regular sensors."""
|
||||
|
||||
api_category: str
|
|
@ -4,8 +4,6 @@ from __future__ import annotations
|
|||
from dataclasses import dataclass
|
||||
from functools import partial
|
||||
|
||||
from regenmaschine.controller import Controller
|
||||
|
||||
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
|
@ -15,7 +13,6 @@ from homeassistant.const import (
|
|||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from . import RainMachineEntity
|
||||
from .const import (
|
||||
|
@ -25,6 +22,7 @@ from .const import (
|
|||
DATA_RESTRICTIONS_UNIVERSAL,
|
||||
DOMAIN,
|
||||
)
|
||||
from .model import RainMachineSensorDescriptionMixin
|
||||
|
||||
TYPE_FLOW_SENSOR_CLICK_M3 = "flow_sensor_clicks_cubic_meter"
|
||||
TYPE_FLOW_SENSOR_CONSUMED_LITERS = "flow_sensor_consumed_liters"
|
||||
|
@ -34,21 +32,14 @@ TYPE_FREEZE_TEMP = "freeze_protect_temp"
|
|||
|
||||
|
||||
@dataclass
|
||||
class RainmachineRequiredKeysMixin:
|
||||
"""Mixin for required keys."""
|
||||
|
||||
api_category: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class RainmachineSensorEntityDescription(
|
||||
SensorEntityDescription, RainmachineRequiredKeysMixin
|
||||
class RainMachineSensorEntityDescription(
|
||||
SensorEntityDescription, RainMachineSensorDescriptionMixin
|
||||
):
|
||||
"""Describes Rainmachine sensor entity."""
|
||||
"""Describe a RainMachine sensor."""
|
||||
|
||||
|
||||
SENSOR_TYPES: tuple[RainmachineSensorEntityDescription, ...] = (
|
||||
RainmachineSensorEntityDescription(
|
||||
SENSOR_DESCRIPTIONS = (
|
||||
RainMachineSensorEntityDescription(
|
||||
key=TYPE_FLOW_SENSOR_CLICK_M3,
|
||||
name="Flow Sensor Clicks",
|
||||
icon="mdi:water-pump",
|
||||
|
@ -56,7 +47,7 @@ SENSOR_TYPES: tuple[RainmachineSensorEntityDescription, ...] = (
|
|||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_PROVISION_SETTINGS,
|
||||
),
|
||||
RainmachineSensorEntityDescription(
|
||||
RainMachineSensorEntityDescription(
|
||||
key=TYPE_FLOW_SENSOR_CONSUMED_LITERS,
|
||||
name="Flow Sensor Consumed Liters",
|
||||
icon="mdi:water-pump",
|
||||
|
@ -64,7 +55,7 @@ SENSOR_TYPES: tuple[RainmachineSensorEntityDescription, ...] = (
|
|||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_PROVISION_SETTINGS,
|
||||
),
|
||||
RainmachineSensorEntityDescription(
|
||||
RainMachineSensorEntityDescription(
|
||||
key=TYPE_FLOW_SENSOR_START_INDEX,
|
||||
name="Flow Sensor Start Index",
|
||||
icon="mdi:water-pump",
|
||||
|
@ -72,7 +63,7 @@ SENSOR_TYPES: tuple[RainmachineSensorEntityDescription, ...] = (
|
|||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_PROVISION_SETTINGS,
|
||||
),
|
||||
RainmachineSensorEntityDescription(
|
||||
RainMachineSensorEntityDescription(
|
||||
key=TYPE_FLOW_SENSOR_WATERING_CLICKS,
|
||||
name="Flow Sensor Clicks",
|
||||
icon="mdi:water-pump",
|
||||
|
@ -80,13 +71,12 @@ SENSOR_TYPES: tuple[RainmachineSensorEntityDescription, ...] = (
|
|||
entity_registry_enabled_default=False,
|
||||
api_category=DATA_PROVISION_SETTINGS,
|
||||
),
|
||||
RainmachineSensorEntityDescription(
|
||||
RainMachineSensorEntityDescription(
|
||||
key=TYPE_FREEZE_TEMP,
|
||||
name="Freeze Protect Temperature",
|
||||
icon="mdi:thermometer",
|
||||
native_unit_of_measurement=TEMP_CELSIUS,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
entity_registry_enabled_default=True,
|
||||
api_category=DATA_RESTRICTIONS_UNIVERSAL,
|
||||
),
|
||||
)
|
||||
|
@ -116,38 +106,22 @@ async def async_setup_entry(
|
|||
async_add_entities(
|
||||
[
|
||||
async_get_sensor(description.api_category)(controller, description)
|
||||
for description in SENSOR_TYPES
|
||||
for description in SENSOR_DESCRIPTIONS
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class RainMachineSensor(RainMachineEntity, SensorEntity):
|
||||
"""Define a general RainMachine sensor."""
|
||||
|
||||
entity_description: RainmachineSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DataUpdateCoordinator,
|
||||
controller: Controller,
|
||||
description: RainmachineSensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator, controller, description.key)
|
||||
self.entity_description = description
|
||||
|
||||
|
||||
class ProvisionSettingsSensor(RainMachineSensor):
|
||||
class ProvisionSettingsSensor(RainMachineEntity, SensorEntity):
|
||||
"""Define a sensor that handles provisioning data."""
|
||||
|
||||
@callback
|
||||
def update_from_latest_data(self) -> None:
|
||||
"""Update the state."""
|
||||
if self._entity_type == TYPE_FLOW_SENSOR_CLICK_M3:
|
||||
if self.entity_description.key == TYPE_FLOW_SENSOR_CLICK_M3:
|
||||
self._attr_native_value = self.coordinator.data["system"].get(
|
||||
"flowSensorClicksPerCubicMeter"
|
||||
)
|
||||
elif self._entity_type == TYPE_FLOW_SENSOR_CONSUMED_LITERS:
|
||||
elif self.entity_description.key == TYPE_FLOW_SENSOR_CONSUMED_LITERS:
|
||||
clicks = self.coordinator.data["system"].get("flowSensorWateringClicks")
|
||||
clicks_per_m3 = self.coordinator.data["system"].get(
|
||||
"flowSensorClicksPerCubicMeter"
|
||||
|
@ -157,21 +131,21 @@ class ProvisionSettingsSensor(RainMachineSensor):
|
|||
self._attr_native_value = (clicks * 1000) / clicks_per_m3
|
||||
else:
|
||||
self._attr_native_value = None
|
||||
elif self._entity_type == TYPE_FLOW_SENSOR_START_INDEX:
|
||||
elif self.entity_description.key == TYPE_FLOW_SENSOR_START_INDEX:
|
||||
self._attr_native_value = self.coordinator.data["system"].get(
|
||||
"flowSensorStartIndex"
|
||||
)
|
||||
elif self._entity_type == TYPE_FLOW_SENSOR_WATERING_CLICKS:
|
||||
elif self.entity_description.key == TYPE_FLOW_SENSOR_WATERING_CLICKS:
|
||||
self._attr_native_value = self.coordinator.data["system"].get(
|
||||
"flowSensorWateringClicks"
|
||||
)
|
||||
|
||||
|
||||
class UniversalRestrictionsSensor(RainMachineSensor):
|
||||
class UniversalRestrictionsSensor(RainMachineEntity, SensorEntity):
|
||||
"""Define a sensor that handles universal restrictions data."""
|
||||
|
||||
@callback
|
||||
def update_from_latest_data(self) -> None:
|
||||
"""Update the state."""
|
||||
if self._entity_type == TYPE_FREEZE_TEMP:
|
||||
if self.entity_description.key == TYPE_FREEZE_TEMP:
|
||||
self._attr_native_value = self.coordinator.data["freezeProtectTemp"]
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Coroutine
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
|
@ -9,7 +10,7 @@ from regenmaschine.controller import Controller
|
|||
from regenmaschine.errors import RequestError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_ID
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
@ -115,6 +116,20 @@ SWITCH_TYPE_PROGRAM = "program"
|
|||
SWITCH_TYPE_ZONE = "zone"
|
||||
|
||||
|
||||
@dataclass
|
||||
class RainMachineSwitchDescriptionMixin:
|
||||
"""Define an entity description mixin for switches."""
|
||||
|
||||
uid: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class RainMachineSwitchDescription(
|
||||
SwitchEntityDescription, RainMachineSwitchDescriptionMixin
|
||||
):
|
||||
"""Describe a RainMachine switch."""
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
|
@ -166,18 +181,34 @@ async def async_setup_entry(
|
|||
]
|
||||
zones_coordinator = hass.data[DOMAIN][DATA_COORDINATOR][entry.entry_id][DATA_ZONES]
|
||||
|
||||
entities: list[RainMachineProgram | RainMachineZone] = []
|
||||
|
||||
for uid, program in programs_coordinator.data.items():
|
||||
entities.append(
|
||||
RainMachineProgram(
|
||||
programs_coordinator, controller, uid, program["name"], entry
|
||||
entities: list[RainMachineProgram | RainMachineZone] = [
|
||||
RainMachineProgram(
|
||||
programs_coordinator,
|
||||
controller,
|
||||
entry,
|
||||
RainMachineSwitchDescription(
|
||||
key=f"RainMachineProgram_{uid}",
|
||||
name=program["name"],
|
||||
uid=uid,
|
||||
),
|
||||
)
|
||||
for uid, program in programs_coordinator.data.items()
|
||||
]
|
||||
entities.extend(
|
||||
[
|
||||
RainMachineZone(
|
||||
zones_coordinator,
|
||||
controller,
|
||||
entry,
|
||||
RainMachineSwitchDescription(
|
||||
key=f"RainMachineZone_{uid}",
|
||||
name=zone["name"],
|
||||
uid=uid,
|
||||
),
|
||||
)
|
||||
)
|
||||
for uid, zone in zones_coordinator.data.items():
|
||||
entities.append(
|
||||
RainMachineZone(zones_coordinator, controller, uid, zone["name"], entry)
|
||||
)
|
||||
for uid, zone in zones_coordinator.data.items()
|
||||
]
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
@ -186,35 +217,28 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity):
|
|||
"""A class to represent a generic RainMachine switch."""
|
||||
|
||||
_attr_icon = DEFAULT_ICON
|
||||
entity_description: RainMachineSwitchDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DataUpdateCoordinator,
|
||||
controller: Controller,
|
||||
uid: int,
|
||||
name: str,
|
||||
entry: ConfigEntry,
|
||||
description: RainMachineSwitchDescription,
|
||||
) -> None:
|
||||
"""Initialize a generic RainMachine switch."""
|
||||
super().__init__(coordinator, controller, type(self).__name__)
|
||||
super().__init__(coordinator, controller, description)
|
||||
|
||||
self._attr_is_on = False
|
||||
self._attr_name = name
|
||||
self._data = coordinator.data[uid]
|
||||
self._data = coordinator.data[self.entity_description.uid]
|
||||
self._entry = entry
|
||||
self._is_active = True
|
||||
self._uid = uid
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return super().available and self._is_active
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique, Home Assistant friendly identifier for this entity."""
|
||||
return f"{super().unique_id}_{self._uid}"
|
||||
|
||||
async def _async_run_switch_coroutine(self, api_coro: Coroutine) -> None:
|
||||
"""Run a coroutine to toggle the switch."""
|
||||
try:
|
||||
|
@ -222,7 +246,7 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity):
|
|||
except RequestError as err:
|
||||
LOGGER.error(
|
||||
'Error while toggling %s "%s": %s',
|
||||
self._entity_type,
|
||||
self.entity_description.key,
|
||||
self.unique_id,
|
||||
err,
|
||||
)
|
||||
|
@ -231,7 +255,7 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity):
|
|||
if resp["statusCode"] != 0:
|
||||
LOGGER.error(
|
||||
'Error while toggling %s "%s": %s',
|
||||
self._entity_type,
|
||||
self.entity_description.key,
|
||||
self.unique_id,
|
||||
resp["message"],
|
||||
)
|
||||
|
@ -301,7 +325,7 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity):
|
|||
@callback
|
||||
def update_from_latest_data(self) -> None:
|
||||
"""Update the state."""
|
||||
self._data = self.coordinator.data[self._uid]
|
||||
self._data = self.coordinator.data[self.entity_description.uid]
|
||||
self._is_active = self._data["active"]
|
||||
|
||||
|
||||
|
@ -316,13 +340,13 @@ class RainMachineProgram(RainMachineSwitch):
|
|||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the program off."""
|
||||
await self._async_run_switch_coroutine(
|
||||
self._controller.programs.stop(self._uid)
|
||||
self._controller.programs.stop(self.entity_description.uid)
|
||||
)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the program on."""
|
||||
await self._async_run_switch_coroutine(
|
||||
self._controller.programs.start(self._uid)
|
||||
self._controller.programs.start(self.entity_description.uid)
|
||||
)
|
||||
|
||||
@callback
|
||||
|
@ -341,10 +365,14 @@ class RainMachineProgram(RainMachineSwitch):
|
|||
|
||||
self._attr_extra_state_attributes.update(
|
||||
{
|
||||
ATTR_ID: self._uid,
|
||||
ATTR_ID: self.entity_description.uid,
|
||||
ATTR_NEXT_RUN: next_run,
|
||||
ATTR_SOAK: self.coordinator.data[self._uid].get("soak"),
|
||||
ATTR_STATUS: RUN_STATUS_MAP[self.coordinator.data[self._uid]["status"]],
|
||||
ATTR_SOAK: self.coordinator.data[self.entity_description.uid].get(
|
||||
"soak"
|
||||
),
|
||||
ATTR_STATUS: RUN_STATUS_MAP[
|
||||
self.coordinator.data[self.entity_description.uid]["status"]
|
||||
],
|
||||
ATTR_ZONES: ", ".join(z["name"] for z in self.zones),
|
||||
}
|
||||
)
|
||||
|
@ -355,13 +383,15 @@ class RainMachineZone(RainMachineSwitch):
|
|||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the zone off."""
|
||||
await self._async_run_switch_coroutine(self._controller.zones.stop(self._uid))
|
||||
await self._async_run_switch_coroutine(
|
||||
self._controller.zones.stop(self.entity_description.uid)
|
||||
)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the zone on."""
|
||||
await self._async_run_switch_coroutine(
|
||||
self._controller.zones.start(
|
||||
self._uid,
|
||||
self.entity_description.uid,
|
||||
self._entry.options[CONF_ZONE_RUN_TIME],
|
||||
)
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue