From 4597bbd5ef5769670feec040cdd0c80591ce1fa9 Mon Sep 17 00:00:00 2001 From: drc38 <20024196+drc38@users.noreply.github.com> Date: Thu, 23 Dec 2021 12:38:34 +1300 Subject: [PATCH] Refactor Numbers for 2021.12+ (#254) * update numbers for 2012.12+ * fix numbers definition * fix test reference * Add restore after restart * Add RestoreEntity import * Fix error * Update test_charge_point.py fix typo * Update test_charge_point.py fix imports * Update const.py Co-authored-by: lbbrhzn --- custom_components/ocpp/const.py | 18 ----- custom_components/ocpp/number.py | 118 +++++++++++++++++++------------ tests/test_charge_point.py | 7 +- 3 files changed, 74 insertions(+), 69 deletions(-) diff --git a/custom_components/ocpp/const.py b/custom_components/ocpp/const.py index 42709c4b..e4ab9166 100644 --- a/custom_components/ocpp/const.py +++ b/custom_components/ocpp/const.py @@ -11,9 +11,6 @@ CONF_CSID = "csid" CONF_HOST = ha.CONF_HOST CONF_ICON = ha.CONF_ICON -CONF_INITIAL = input_number.CONF_INITIAL -CONF_MAX = input_number.CONF_MAX -CONF_MIN = input_number.CONF_MIN CONF_METER_INTERVAL = "meter_interval" CONF_MODE = ha.CONF_MODE CONF_MONITORED_VARIABLES = ha.CONF_MONITORED_VARIABLES @@ -32,8 +29,6 @@ DEFAULT_METER_INTERVAL = 60 DOMAIN = "ocpp" ICON = "mdi:ev-station" -MODE_SLIDER = input_number.MODE_SLIDER -MODE_BOX = input_number.MODE_BOX SLEEP_TIME = 60 # Platforms @@ -97,19 +92,6 @@ SWITCHES = [SWITCH_CHARGE, SWITCH_AVAILABILITY] -# Input number definitions -NUMBER_MAX_CURRENT = { - CONF_NAME: "Maximum_Current", - CONF_ICON: ICON, - CONF_MIN: 0, - CONF_MAX: 32, - CONF_STEP: 1, - CONF_INITIAL: 32, - CONF_MODE: MODE_SLIDER, - CONF_UNIT_OF_MEASUREMENT: "A", -} -NUMBERS = [NUMBER_MAX_CURRENT] - # Where a HA unit does not exist use Ocpp unit UNITS_OCCP_TO_HA = { UnitOfMeasure.wh: ha.ENERGY_WATT_HOUR, diff --git a/custom_components/ocpp/number.py b/custom_components/ocpp/number.py index 53deefb4..6fcb5b10 100644 --- a/custom_components/ocpp/number.py +++ b/custom_components/ocpp/number.py @@ -1,22 +1,47 @@ """Number platform for ocpp.""" -from homeassistant.components.input_number import InputNumber -from homeassistant.components.number import NumberEntity +from __future__ import annotations + +from dataclasses import dataclass +from typing import Final + +from homeassistant.components.number import ( + DOMAIN as NUMBER_DOMAIN, + NumberEntity, + NumberEntityDescription, +) +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.restore_state import RestoreEntity import voluptuous as vol from .api import CentralSystem -from .const import ( - CONF_CPID, - CONF_INITIAL, - CONF_MAX, - CONF_MIN, - CONF_STEP, - DEFAULT_CPID, - DOMAIN, - NUMBERS, -) +from .const import CONF_CPID, DEFAULT_CPID, DOMAIN, ICON from .enums import Profiles +@dataclass +class OcppNumberDescription(NumberEntityDescription): + """Class to describe a Number entity.""" + + initial_value: float | None = None + # can be removed when dev branch released + max_value: float | None = None + min_value: float | None = None + step: float | None = None + + +NUMBERS: Final = [ + OcppNumberDescription( + key="maximum_current", + name="Maximum_Current", + icon=ICON, + initial_value=32, + min_value=0, + max_value=32, + step=1, + ), +] + + async def async_setup_entry(hass, entry, async_add_devices): """Configure the number platform.""" central_system = hass.data[DOMAIN][entry.entry_id] @@ -24,37 +49,49 @@ async def async_setup_entry(hass, entry, async_add_devices): entities = [] - for cfg in NUMBERS: - entities.append(Number(central_system, cp_id, cfg)) + for ent in NUMBERS: + entities.append(OcppNumber(central_system, cp_id, ent)) async_add_devices(entities, False) -class Number(InputNumber, NumberEntity): +class OcppNumber(NumberEntity, RestoreEntity): """Individual slider for setting charge rate.""" - def __init__(self, central_system: CentralSystem, cp_id: str, config: dict): + entity_description: OcppNumberDescription + + def __init__( + self, + central_system: CentralSystem, + cp_id: str, + description: OcppNumberDescription, + ): """Initialize a Number instance.""" - super().__init__(config) self.cp_id = cp_id self.central_system = central_system - self.id = ".".join(["number", self.cp_id, config["name"]]) - self._name = ".".join([self.cp_id, config["name"]]) - self.entity_id = "number." + "_".join([self.cp_id, config["name"]]) - self._attr_max_value: float = config[CONF_MAX] - self._attr_min_value: float = config[CONF_MIN] - self._attr_step: float = config[CONF_STEP] - self._attr_value: float = config[CONF_INITIAL] - - @property - def unique_id(self): - """Return the unique id of this entity.""" - return self.id - - @property - def name(self): - """Return the name of this entity.""" - return self._name + self.entity_description = description + self._attr_unique_id = ".".join( + [NUMBER_DOMAIN, self.cp_id, self.entity_description.key] + ) + self._name = ".".join([self.cp_id, self.entity_description.name]) + self.entity_id = ( + NUMBER_DOMAIN + "." + "_".join([self.cp_id, self.entity_description.key]) + ) + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, self.cp_id)}, + via_device=(DOMAIN, self.central_system.id), + ) + self._attr_value = self.entity_description.initial_value + # can be removed when dev branch released + self._attr_max_value = self.entity_description.max_value + self._attr_min_value = self.entity_description.min_value + self._attr_step = self.entity_description.step + + async def async_added_to_hass(self) -> None: + """Handle entity which will be added.""" + await self.async_base_added_to_hass() + if state := await self.async_get_last_state(): + self._attr_value = state.state @property def available(self) -> bool: @@ -65,19 +102,6 @@ def available(self) -> bool: return False return self.central_system.get_available(self.cp_id) # type: ignore [no-any-return] - @property - def state(self): - """Return the state of the component.""" - return self._attr_value - - @property - def device_info(self): - """Return device information.""" - return { - "identifiers": {(DOMAIN, self.cp_id)}, - "via_device": (DOMAIN, self.central_system.id), - } - async def async_set_value(self, value): """Set new value.""" num_value = float(value) diff --git a/tests/test_charge_point.py b/tests/test_charge_point.py index d9c722a0..bf9b370d 100644 --- a/tests/test_charge_point.py +++ b/tests/test_charge_point.py @@ -16,8 +16,9 @@ from custom_components.ocpp import async_setup_entry, async_unload_entry from custom_components.ocpp.button import BUTTONS -from custom_components.ocpp.const import DOMAIN as OCPP_DOMAIN, NUMBERS +from custom_components.ocpp.const import DOMAIN as OCPP_DOMAIN from custom_components.ocpp.enums import ConfigurationKey, HAChargerServices as csvcs +from custom_components.ocpp.number import NUMBERS from custom_components.ocpp.switch import SWITCHES from ocpp.routing import on from ocpp.v16 import ChargePoint as cpclass, call, call_result @@ -117,9 +118,7 @@ async def test_services(hass, socket_enabled): "set_value", service_data={"value": "10"}, blocking=True, - target={ - ATTR_ENTITY_ID: f"{NUMBER_DOMAIN}.test_cpid_{number['name'].lower()}" - }, + target={ATTR_ENTITY_ID: f"{NUMBER_DOMAIN}.test_cpid_{number.key}"}, ) assert result