From 39313057c4f8384cc44bc95a8262a49c986777c1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 May 2022 23:14:52 +1200 Subject: [PATCH] Add amperage limit number to JuiceNet (#71716) * Add amperage limit number to JuiceNet * coverage exception * Use mixin dataclass --- .coveragerc | 1 + homeassistant/components/juicenet/__init__.py | 2 +- homeassistant/components/juicenet/entity.py | 15 ++- homeassistant/components/juicenet/number.py | 98 +++++++++++++++++++ 4 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 homeassistant/components/juicenet/number.py diff --git a/.coveragerc b/.coveragerc index 78f63d30cbe..922c13e550c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -579,6 +579,7 @@ omit = homeassistant/components/juicenet/const.py homeassistant/components/juicenet/device.py homeassistant/components/juicenet/entity.py + homeassistant/components/juicenet/number.py homeassistant/components/juicenet/sensor.py homeassistant/components/juicenet/switch.py homeassistant/components/kaiterra/* diff --git a/homeassistant/components/juicenet/__init__.py b/homeassistant/components/juicenet/__init__.py index 92d8de8bc0a..60377d7e85b 100644 --- a/homeassistant/components/juicenet/__init__.py +++ b/homeassistant/components/juicenet/__init__.py @@ -20,7 +20,7 @@ from .device import JuiceNetApi _LOGGER = logging.getLogger(__name__) -PLATFORMS = [Platform.SENSOR, Platform.SWITCH] +PLATFORMS = [Platform.SENSOR, Platform.SWITCH, Platform.NUMBER] CONFIG_SCHEMA = vol.Schema( vol.All( diff --git a/homeassistant/components/juicenet/entity.py b/homeassistant/components/juicenet/entity.py index 4b4e5764a5e..c0151a0cd00 100644 --- a/homeassistant/components/juicenet/entity.py +++ b/homeassistant/components/juicenet/entity.py @@ -1,7 +1,12 @@ """Adapter to wrap the pyjuicenet api for home assistant.""" +from pyjuicenet import Charger + from homeassistant.helpers.entity import DeviceInfo -from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) from .const import DOMAIN @@ -9,16 +14,18 @@ from .const import DOMAIN class JuiceNetDevice(CoordinatorEntity): """Represent a base JuiceNet device.""" - def __init__(self, device, sensor_type, coordinator): + def __init__( + self, device: Charger, key: str, coordinator: DataUpdateCoordinator + ) -> None: """Initialise the sensor.""" super().__init__(coordinator) self.device = device - self.type = sensor_type + self.key = key @property def unique_id(self): """Return a unique ID.""" - return f"{self.device.id}-{self.type}" + return f"{self.device.id}-{self.key}" @property def device_info(self) -> DeviceInfo: diff --git a/homeassistant/components/juicenet/number.py b/homeassistant/components/juicenet/number.py new file mode 100644 index 00000000000..24b0ba4f42b --- /dev/null +++ b/homeassistant/components/juicenet/number.py @@ -0,0 +1,98 @@ +"""Support for controlling juicenet/juicepoint/juicebox based EVSE numbers.""" +from __future__ import annotations + +from dataclasses import dataclass + +from pyjuicenet import Api, Charger + +from homeassistant.components.number import NumberEntity, NumberEntityDescription +from homeassistant.components.number.const import DEFAULT_MAX_VALUE +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator + +from .const import DOMAIN, JUICENET_API, JUICENET_COORDINATOR +from .entity import JuiceNetDevice + + +@dataclass +class JuiceNetNumberEntityDescriptionMixin: + """Mixin for required keys.""" + + setter_key: str + + +@dataclass +class JuiceNetNumberEntityDescription( + NumberEntityDescription, JuiceNetNumberEntityDescriptionMixin +): + """An entity description for a JuiceNetNumber.""" + + max_value_key: str | None = None + + +NUMBER_TYPES: tuple[JuiceNetNumberEntityDescription, ...] = ( + JuiceNetNumberEntityDescription( + name="Amperage Limit", + key="current_charging_amperage_limit", + min_value=6, + max_value_key="max_charging_amperage", + step=1, + setter_key="set_charging_amperage_limit", + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the JuiceNet Numbers.""" + juicenet_data = hass.data[DOMAIN][config_entry.entry_id] + api: Api = juicenet_data[JUICENET_API] + coordinator = juicenet_data[JUICENET_COORDINATOR] + + entities = [ + JuiceNetNumber(device, description, coordinator) + for device in api.devices + for description in NUMBER_TYPES + ] + async_add_entities(entities) + + +class JuiceNetNumber(JuiceNetDevice, NumberEntity): + """Implementation of a JuiceNet number.""" + + entity_description: JuiceNetNumberEntityDescription + + def __init__( + self, + device: Charger, + description: JuiceNetNumberEntityDescription, + coordinator: DataUpdateCoordinator, + ) -> None: + """Initialise the number.""" + super().__init__(device, description.key, coordinator) + self.entity_description = description + + self._attr_name = f"{self.device.name} {description.name}" + + @property + def value(self) -> float | None: + """Return the value of the entity.""" + return getattr(self.device, self.entity_description.key, None) + + @property + def max_value(self) -> float: + """Return the maximum value.""" + if self.entity_description.max_value_key is not None: + return getattr(self.device, self.entity_description.max_value_key) + if self.entity_description.max_value is not None: + return self.entity_description.max_value + return DEFAULT_MAX_VALUE + + async def async_set_value(self, value: float) -> None: + """Update the current value.""" + await getattr(self.device, self.entity_description.setter_key)(value)