Split wallbox sensor type and number type (#58807)

This commit is contained in:
hesselonline 2021-11-02 11:11:46 +01:00 committed by GitHub
parent 9d7786f887
commit bfb0d8dd19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 161 additions and 133 deletions

View File

@ -18,7 +18,6 @@ from .const import (
CONF_MAX_CHARGING_CURRENT_KEY, CONF_MAX_CHARGING_CURRENT_KEY,
CONF_STATION, CONF_STATION,
DOMAIN, DOMAIN,
SENSOR_TYPES,
) )
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -71,16 +70,8 @@ class WallboxCoordinator(DataUpdateCoordinator):
CONF_MAX_CHARGING_CURRENT_KEY 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: except requests.exceptions.HTTPError as wallbox_connection_error:
raise ConnectionError from wallbox_connection_error raise ConnectionError from wallbox_connection_error

View File

@ -1,20 +1,4 @@
"""Constants for the Wallbox integration.""" """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" DOMAIN = "wallbox"
@ -32,88 +16,4 @@ CONF_MAX_AVAILABLE_POWER_KEY = "max_available_power"
CONF_MAX_CHARGING_CURRENT_KEY = "max_charging_current" CONF_MAX_CHARGING_CURRENT_KEY = "max_charging_current"
CONF_STATE_OF_CHARGE_KEY = "state_of_charge" CONF_STATE_OF_CHARGE_KEY = "state_of_charge"
CONF_STATUS_DESCRIPTION_KEY = "status_description" CONF_STATUS_DESCRIPTION_KEY = "status_description"
CONF_CONNECTIONS = "connections" 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,
),
}

View File

@ -1,5 +1,10 @@
"""Home Assistant component for accessing the Wallbox Portal API. The sensor component creates multiple sensors regarding wallbox performance.""" """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 homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import InvalidAuth from . import InvalidAuth
@ -8,35 +13,59 @@ from .const import (
CONF_MAX_AVAILABLE_POWER_KEY, CONF_MAX_AVAILABLE_POWER_KEY,
CONF_MAX_CHARGING_CURRENT_KEY, CONF_MAX_CHARGING_CURRENT_KEY,
DOMAIN, 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): async def async_setup_entry(hass, config, async_add_entities):
"""Create wallbox sensor entities in HASS.""" """Create wallbox sensor entities in HASS."""
coordinator = hass.data[DOMAIN][CONF_CONNECTIONS][config.entry_id] coordinator = hass.data[DOMAIN][CONF_CONNECTIONS][config.entry_id]
# Check if the user is authorized to change current, if so, add number component: # Check if the user is authorized to change current, if so, add number component:
try: try:
await coordinator.async_set_charging_current( await coordinator.async_set_charging_current(
coordinator.data[CONF_MAX_CHARGING_CURRENT_KEY] coordinator.data[CONF_MAX_CHARGING_CURRENT_KEY]
) )
except InvalidAuth: except InvalidAuth:
pass return
else:
async_add_entities([WallboxNumber(coordinator, config)]) async_add_entities(
[
WallboxNumber(coordinator, config, description)
for ent in coordinator.data
if (description := NUMBER_TYPES.get(ent))
]
)
class WallboxNumber(CoordinatorEntity, NumberEntity): class WallboxNumber(CoordinatorEntity, NumberEntity):
"""Representation of the Wallbox portal.""" """Representation of the Wallbox portal."""
def __init__(self, coordinator, config): def __init__(
self, coordinator, config, description: WallboxNumberEntityDescription
):
"""Initialize a Wallbox sensor.""" """Initialize a Wallbox sensor."""
super().__init__(coordinator) super().__init__(coordinator)
sensor_description = SENSOR_TYPES[CONF_MAX_CHARGING_CURRENT_KEY] self.entity_description = description
self._coordinator = coordinator self._coordinator = coordinator
self._attr_name = f"{config.title} {sensor_description.name}" self._attr_name = f"{config.title} {description.name}"
self._attr_min_value = 6 self._attr_min_value = description.min_value
self._attr_device_class = sensor_description.device_class
@property @property
def max_value(self): def max_value(self):

View File

@ -1,17 +1,122 @@
"""Home Assistant component for accessing the Wallbox Portal API. The sensor component creates multiple sensors regarding wallbox performance.""" """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 homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import (
CONF_ADDED_ENERGY_KEY,
CONF_ADDED_RANGE_KEY,
CONF_CHARGING_POWER_KEY,
CONF_CHARGING_SPEED_KEY,
CONF_CONNECTIONS, 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, DOMAIN,
SENSOR_TYPES,
WallboxSensorEntityDescription,
) )
CONF_STATION = "station" CONF_STATION = "station"
UPDATE_INTERVAL = 30 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): async def async_setup_entry(hass, config, async_add_entities):
"""Create wallbox sensor entities in HASS.""" """Create wallbox sensor entities in HASS."""
@ -21,7 +126,7 @@ async def async_setup_entry(hass, config, async_add_entities):
[ [
WallboxSensor(coordinator, config, description) WallboxSensor(coordinator, config, description)
for ent in coordinator.data 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 @property
def native_value(self): def native_value(self):
"""Return the state of the sensor.""" """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] return self.coordinator.data[self.entity_description.key]

View File

@ -18,14 +18,9 @@ from homeassistant.components.wallbox.const import (
) )
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME 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.common import MockConfigEntry
from tests.components.wallbox.const import (
CONF_ERROR,
CONF_JWT,
CONF_STATUS,
CONF_TTL,
CONF_USER_ID,
)
test_response = json.loads( test_response = json.loads(
json.dumps( json.dumps(
@ -33,8 +28,8 @@ test_response = json.loads(
CONF_CHARGING_POWER_KEY: 0, CONF_CHARGING_POWER_KEY: 0,
CONF_MAX_AVAILABLE_POWER_KEY: 25.2, CONF_MAX_AVAILABLE_POWER_KEY: 25.2,
CONF_CHARGING_SPEED_KEY: 0, CONF_CHARGING_SPEED_KEY: 0,
CONF_ADDED_RANGE_KEY: "xx", CONF_ADDED_RANGE_KEY: 150,
CONF_ADDED_ENERGY_KEY: "44.697", CONF_ADDED_ENERGY_KEY: 44.697,
CONF_DATA_KEY: {CONF_MAX_CHARGING_CURRENT_KEY: 24}, CONF_DATA_KEY: {CONF_MAX_CHARGING_CURRENT_KEY: 24},
} }
) )