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_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

View File

@ -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,
),
}

View File

@ -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):

View File

@ -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]

View File

@ -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},
}
)