diff --git a/homeassistant/components/wallbox/__init__.py b/homeassistant/components/wallbox/__init__.py index a1361984606..aade0c430f6 100644 --- a/homeassistant/components/wallbox/__init__.py +++ b/homeassistant/components/wallbox/__init__.py @@ -18,7 +18,6 @@ from .const import ( CONF_MAX_CHARGING_CURRENT_KEY, CONF_STATION, DOMAIN, - SENSOR_TYPES, ) _LOGGER = logging.getLogger(__name__) @@ -71,16 +70,8 @@ class WallboxCoordinator(DataUpdateCoordinator): CONF_MAX_CHARGING_CURRENT_KEY ] - filtered_data = {k: data[k] for k in SENSOR_TYPES if k in data} + return data - for key, value in filtered_data.items(): - if (sensor_round := SENSOR_TYPES[key].precision) is not None: - try: - filtered_data[key] = round(value, sensor_round) - except TypeError: - _LOGGER.debug("Cannot format %s", key) - - return filtered_data except requests.exceptions.HTTPError as wallbox_connection_error: raise ConnectionError from wallbox_connection_error diff --git a/homeassistant/components/wallbox/const.py b/homeassistant/components/wallbox/const.py index 26af7f4c499..e753d548987 100644 --- a/homeassistant/components/wallbox/const.py +++ b/homeassistant/components/wallbox/const.py @@ -1,20 +1,4 @@ """Constants for the Wallbox integration.""" -from __future__ import annotations - -from dataclasses import dataclass - -from homeassistant.components.sensor import SensorEntityDescription -from homeassistant.const import ( - DEVICE_CLASS_BATTERY, - DEVICE_CLASS_CURRENT, - DEVICE_CLASS_ENERGY, - DEVICE_CLASS_POWER, - ELECTRIC_CURRENT_AMPERE, - ENERGY_KILO_WATT_HOUR, - LENGTH_KILOMETERS, - PERCENTAGE, - POWER_KILO_WATT, -) DOMAIN = "wallbox" @@ -32,88 +16,4 @@ CONF_MAX_AVAILABLE_POWER_KEY = "max_available_power" CONF_MAX_CHARGING_CURRENT_KEY = "max_charging_current" CONF_STATE_OF_CHARGE_KEY = "state_of_charge" CONF_STATUS_DESCRIPTION_KEY = "status_description" - CONF_CONNECTIONS = "connections" - - -@dataclass -class WallboxSensorEntityDescription(SensorEntityDescription): - """Describes Wallbox sensor entity.""" - - precision: int | None = None - - -SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = { - CONF_CHARGING_POWER_KEY: WallboxSensorEntityDescription( - key=CONF_CHARGING_POWER_KEY, - name="Charging Power", - precision=2, - native_unit_of_measurement=POWER_KILO_WATT, - device_class=DEVICE_CLASS_POWER, - ), - CONF_MAX_AVAILABLE_POWER_KEY: WallboxSensorEntityDescription( - key=CONF_MAX_AVAILABLE_POWER_KEY, - name="Max Available Power", - precision=0, - native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, - device_class=DEVICE_CLASS_CURRENT, - ), - CONF_CHARGING_SPEED_KEY: WallboxSensorEntityDescription( - key=CONF_CHARGING_SPEED_KEY, - icon="mdi:speedometer", - name="Charging Speed", - precision=0, - ), - CONF_ADDED_RANGE_KEY: WallboxSensorEntityDescription( - key=CONF_ADDED_RANGE_KEY, - icon="mdi:map-marker-distance", - name="Added Range", - precision=0, - native_unit_of_measurement=LENGTH_KILOMETERS, - ), - CONF_ADDED_ENERGY_KEY: WallboxSensorEntityDescription( - key=CONF_ADDED_ENERGY_KEY, - name="Added Energy", - precision=2, - native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, - device_class=DEVICE_CLASS_ENERGY, - ), - CONF_CHARGING_TIME_KEY: WallboxSensorEntityDescription( - key=CONF_CHARGING_TIME_KEY, - icon="mdi:timer", - name="Charging Time", - ), - CONF_COST_KEY: WallboxSensorEntityDescription( - key=CONF_COST_KEY, - icon="mdi:ev-station", - name="Cost", - ), - CONF_STATE_OF_CHARGE_KEY: WallboxSensorEntityDescription( - key=CONF_STATE_OF_CHARGE_KEY, - name="State of Charge", - native_unit_of_measurement=PERCENTAGE, - device_class=DEVICE_CLASS_BATTERY, - ), - CONF_CURRENT_MODE_KEY: WallboxSensorEntityDescription( - key=CONF_CURRENT_MODE_KEY, - icon="mdi:ev-station", - name="Current Mode", - ), - CONF_DEPOT_PRICE_KEY: WallboxSensorEntityDescription( - key=CONF_DEPOT_PRICE_KEY, - icon="mdi:ev-station", - name="Depot Price", - precision=2, - ), - CONF_STATUS_DESCRIPTION_KEY: WallboxSensorEntityDescription( - key=CONF_STATUS_DESCRIPTION_KEY, - icon="mdi:ev-station", - name="Status Description", - ), - CONF_MAX_CHARGING_CURRENT_KEY: WallboxSensorEntityDescription( - key=CONF_MAX_CHARGING_CURRENT_KEY, - name="Max. Charging Current", - native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, - device_class=DEVICE_CLASS_CURRENT, - ), -} diff --git a/homeassistant/components/wallbox/number.py b/homeassistant/components/wallbox/number.py index 01e453593f3..837e880afcb 100644 --- a/homeassistant/components/wallbox/number.py +++ b/homeassistant/components/wallbox/number.py @@ -1,5 +1,10 @@ """Home Assistant component for accessing the Wallbox Portal API. The sensor component creates multiple sensors regarding wallbox performance.""" -from homeassistant.components.number import NumberEntity +from __future__ import annotations + +from dataclasses import dataclass + +from homeassistant.components.number import NumberEntity, NumberEntityDescription +from homeassistant.const import DEVICE_CLASS_CURRENT from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import InvalidAuth @@ -8,35 +13,59 @@ from .const import ( CONF_MAX_AVAILABLE_POWER_KEY, CONF_MAX_CHARGING_CURRENT_KEY, DOMAIN, - SENSOR_TYPES, ) +@dataclass +class WallboxNumberEntityDescription(NumberEntityDescription): + """Describes Wallbox sensor entity.""" + + min_value: float = 0 + + +NUMBER_TYPES: dict[str, NumberEntityDescription] = { + CONF_MAX_CHARGING_CURRENT_KEY: WallboxNumberEntityDescription( + key=CONF_MAX_CHARGING_CURRENT_KEY, + name="Max. Charging Current", + device_class=DEVICE_CLASS_CURRENT, + min_value=6, + ), +} + + async def async_setup_entry(hass, config, async_add_entities): """Create wallbox sensor entities in HASS.""" coordinator = hass.data[DOMAIN][CONF_CONNECTIONS][config.entry_id] + # Check if the user is authorized to change current, if so, add number component: try: await coordinator.async_set_charging_current( coordinator.data[CONF_MAX_CHARGING_CURRENT_KEY] ) except InvalidAuth: - pass - else: - async_add_entities([WallboxNumber(coordinator, config)]) + return + + async_add_entities( + [ + WallboxNumber(coordinator, config, description) + for ent in coordinator.data + if (description := NUMBER_TYPES.get(ent)) + ] + ) class WallboxNumber(CoordinatorEntity, NumberEntity): """Representation of the Wallbox portal.""" - def __init__(self, coordinator, config): + def __init__( + self, coordinator, config, description: WallboxNumberEntityDescription + ): """Initialize a Wallbox sensor.""" super().__init__(coordinator) - sensor_description = SENSOR_TYPES[CONF_MAX_CHARGING_CURRENT_KEY] + self.entity_description = description self._coordinator = coordinator - self._attr_name = f"{config.title} {sensor_description.name}" - self._attr_min_value = 6 - self._attr_device_class = sensor_description.device_class + self._attr_name = f"{config.title} {description.name}" + self._attr_min_value = description.min_value @property def max_value(self): diff --git a/homeassistant/components/wallbox/sensor.py b/homeassistant/components/wallbox/sensor.py index 3b87d3b29c3..25c0796d0bd 100644 --- a/homeassistant/components/wallbox/sensor.py +++ b/homeassistant/components/wallbox/sensor.py @@ -1,17 +1,122 @@ """Home Assistant component for accessing the Wallbox Portal API. The sensor component creates multiple sensors regarding wallbox performance.""" -from homeassistant.components.sensor import SensorEntity +from __future__ import annotations + +from dataclasses import dataclass +import logging + +from homeassistant.components.sensor import SensorEntity, SensorEntityDescription +from homeassistant.const import ( + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, + ELECTRIC_CURRENT_AMPERE, + ENERGY_KILO_WATT_HOUR, + LENGTH_KILOMETERS, + PERCENTAGE, + POWER_KILO_WATT, +) from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import ( + CONF_ADDED_ENERGY_KEY, + CONF_ADDED_RANGE_KEY, + CONF_CHARGING_POWER_KEY, + CONF_CHARGING_SPEED_KEY, CONF_CONNECTIONS, + CONF_COST_KEY, + CONF_CURRENT_MODE_KEY, + CONF_DEPOT_PRICE_KEY, + CONF_MAX_AVAILABLE_POWER_KEY, + CONF_MAX_CHARGING_CURRENT_KEY, + CONF_STATE_OF_CHARGE_KEY, + CONF_STATUS_DESCRIPTION_KEY, DOMAIN, - SENSOR_TYPES, - WallboxSensorEntityDescription, ) CONF_STATION = "station" UPDATE_INTERVAL = 30 +_LOGGER = logging.getLogger(__name__) + + +@dataclass +class WallboxSensorEntityDescription(SensorEntityDescription): + """Describes Wallbox sensor entity.""" + + precision: int | None = None + + +SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = { + CONF_CHARGING_POWER_KEY: WallboxSensorEntityDescription( + key=CONF_CHARGING_POWER_KEY, + name="Charging Power", + precision=2, + native_unit_of_measurement=POWER_KILO_WATT, + device_class=DEVICE_CLASS_POWER, + ), + CONF_MAX_AVAILABLE_POWER_KEY: WallboxSensorEntityDescription( + key=CONF_MAX_AVAILABLE_POWER_KEY, + name="Max Available Power", + precision=0, + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + device_class=DEVICE_CLASS_CURRENT, + ), + CONF_CHARGING_SPEED_KEY: WallboxSensorEntityDescription( + key=CONF_CHARGING_SPEED_KEY, + icon="mdi:speedometer", + name="Charging Speed", + precision=0, + ), + CONF_ADDED_RANGE_KEY: WallboxSensorEntityDescription( + key=CONF_ADDED_RANGE_KEY, + icon="mdi:map-marker-distance", + name="Added Range", + precision=0, + native_unit_of_measurement=LENGTH_KILOMETERS, + ), + CONF_ADDED_ENERGY_KEY: WallboxSensorEntityDescription( + key=CONF_ADDED_ENERGY_KEY, + name="Added Energy", + precision=2, + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + device_class=DEVICE_CLASS_ENERGY, + ), + CONF_COST_KEY: WallboxSensorEntityDescription( + key=CONF_COST_KEY, + icon="mdi:ev-station", + name="Cost", + ), + CONF_STATE_OF_CHARGE_KEY: WallboxSensorEntityDescription( + key=CONF_STATE_OF_CHARGE_KEY, + name="State of Charge", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_BATTERY, + ), + CONF_CURRENT_MODE_KEY: WallboxSensorEntityDescription( + key=CONF_CURRENT_MODE_KEY, + icon="mdi:ev-station", + name="Current Mode", + ), + CONF_DEPOT_PRICE_KEY: WallboxSensorEntityDescription( + key=CONF_DEPOT_PRICE_KEY, + icon="mdi:ev-station", + name="Depot Price", + precision=2, + ), + CONF_STATUS_DESCRIPTION_KEY: WallboxSensorEntityDescription( + key=CONF_STATUS_DESCRIPTION_KEY, + icon="mdi:ev-station", + name="Status Description", + ), + CONF_MAX_CHARGING_CURRENT_KEY: WallboxSensorEntityDescription( + key=CONF_MAX_CHARGING_CURRENT_KEY, + name="Max. Charging Current", + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + device_class=DEVICE_CLASS_CURRENT, + ), +} + async def async_setup_entry(hass, config, async_add_entities): """Create wallbox sensor entities in HASS.""" @@ -21,7 +126,7 @@ async def async_setup_entry(hass, config, async_add_entities): [ WallboxSensor(coordinator, config, description) for ent in coordinator.data - if (description := SENSOR_TYPES[ent]) + if (description := SENSOR_TYPES.get(ent)) ] ) @@ -42,4 +147,12 @@ class WallboxSensor(CoordinatorEntity, SensorEntity): @property def native_value(self): """Return the state of the sensor.""" + if (sensor_round := self.entity_description.precision) is not None: + try: + return round( + self.coordinator.data[self.entity_description.key], sensor_round + ) + except TypeError: + _LOGGER.debug("Cannot format %s", self._attr_name) + return None return self.coordinator.data[self.entity_description.key] diff --git a/tests/components/wallbox/__init__.py b/tests/components/wallbox/__init__.py index f8031bd86a4..21d1f0acbc5 100644 --- a/tests/components/wallbox/__init__.py +++ b/tests/components/wallbox/__init__.py @@ -18,14 +18,9 @@ from homeassistant.components.wallbox.const import ( ) from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from .const import CONF_ERROR, CONF_JWT, CONF_STATUS, CONF_TTL, CONF_USER_ID + from tests.common import MockConfigEntry -from tests.components.wallbox.const import ( - CONF_ERROR, - CONF_JWT, - CONF_STATUS, - CONF_TTL, - CONF_USER_ID, -) test_response = json.loads( json.dumps( @@ -33,8 +28,8 @@ test_response = json.loads( CONF_CHARGING_POWER_KEY: 0, CONF_MAX_AVAILABLE_POWER_KEY: 25.2, CONF_CHARGING_SPEED_KEY: 0, - CONF_ADDED_RANGE_KEY: "xx", - CONF_ADDED_ENERGY_KEY: "44.697", + CONF_ADDED_RANGE_KEY: 150, + CONF_ADDED_ENERGY_KEY: 44.697, CONF_DATA_KEY: {CONF_MAX_CHARGING_CURRENT_KEY: 24}, } )