Add entity translations to Wallbox (#99021)

Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
Joost Lekkerkerker 2023-09-26 11:41:40 +02:00 committed by GitHub
parent 1e76d37cee
commit f21d924dd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 88 additions and 35 deletions

View File

@ -246,6 +246,8 @@ class InvalidAuth(HomeAssistantError):
class WallboxEntity(CoordinatorEntity[WallboxCoordinator]): class WallboxEntity(CoordinatorEntity[WallboxCoordinator]):
"""Defines a base Wallbox entity.""" """Defines a base Wallbox entity."""
_attr_has_entity_name = True
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
"""Return device information about this Wallbox device.""" """Return device information about this Wallbox device."""
@ -256,7 +258,7 @@ class WallboxEntity(CoordinatorEntity[WallboxCoordinator]):
self.coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY], self.coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY],
) )
}, },
name=f"Wallbox - {self.coordinator.data[CHARGER_NAME_KEY]}", name=f"Wallbox {self.coordinator.data[CHARGER_NAME_KEY]}",
manufacturer="Wallbox", manufacturer="Wallbox",
model=self.coordinator.data[CHARGER_DATA_KEY][CHARGER_PART_NUMBER_KEY], model=self.coordinator.data[CHARGER_DATA_KEY][CHARGER_PART_NUMBER_KEY],
sw_version=self.coordinator.data[CHARGER_DATA_KEY][CHARGER_SOFTWARE_KEY][ sw_version=self.coordinator.data[CHARGER_DATA_KEY][CHARGER_SOFTWARE_KEY][

View File

@ -20,7 +20,7 @@ from .const import (
LOCK_TYPES: dict[str, LockEntityDescription] = { LOCK_TYPES: dict[str, LockEntityDescription] = {
CHARGER_LOCKED_UNLOCKED_KEY: LockEntityDescription( CHARGER_LOCKED_UNLOCKED_KEY: LockEntityDescription(
key=CHARGER_LOCKED_UNLOCKED_KEY, key=CHARGER_LOCKED_UNLOCKED_KEY,
name="Locked/Unlocked", translation_key="lock",
), ),
} }
@ -42,7 +42,7 @@ async def async_setup_entry(
async_add_entities( async_add_entities(
[ [
WallboxLock(coordinator, entry, description) WallboxLock(coordinator, description)
for ent in coordinator.data for ent in coordinator.data
if (description := LOCK_TYPES.get(ent)) if (description := LOCK_TYPES.get(ent))
] ]
@ -55,14 +55,12 @@ class WallboxLock(WallboxEntity, LockEntity):
def __init__( def __init__(
self, self,
coordinator: WallboxCoordinator, coordinator: WallboxCoordinator,
entry: ConfigEntry,
description: LockEntityDescription, description: LockEntityDescription,
) -> None: ) -> None:
"""Initialize a Wallbox lock.""" """Initialize a Wallbox lock."""
super().__init__(coordinator) super().__init__(coordinator)
self.entity_description = description self.entity_description = description
self._attr_name = f"{entry.title} {description.name}"
self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}" self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}"
@property @property

View File

@ -33,7 +33,7 @@ class WallboxNumberEntityDescription(NumberEntityDescription):
NUMBER_TYPES: dict[str, WallboxNumberEntityDescription] = { NUMBER_TYPES: dict[str, WallboxNumberEntityDescription] = {
CHARGER_MAX_CHARGING_CURRENT_KEY: WallboxNumberEntityDescription( CHARGER_MAX_CHARGING_CURRENT_KEY: WallboxNumberEntityDescription(
key=CHARGER_MAX_CHARGING_CURRENT_KEY, key=CHARGER_MAX_CHARGING_CURRENT_KEY,
name="Max. Charging Current", translation_key="maximum_charging_current",
), ),
} }
@ -77,7 +77,6 @@ class WallboxNumber(WallboxEntity, NumberEntity):
super().__init__(coordinator) super().__init__(coordinator)
self.entity_description = description self.entity_description = description
self._coordinator = coordinator self._coordinator = coordinator
self._attr_name = f"{entry.title} {description.name}"
self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}" self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}"
self._is_bidirectional = ( self._is_bidirectional = (
coordinator.data[CHARGER_DATA_KEY][CHARGER_PART_NUMBER_KEY][0:3] coordinator.data[CHARGER_DATA_KEY][CHARGER_PART_NUMBER_KEY][0:3]

View File

@ -60,7 +60,7 @@ class WallboxSensorEntityDescription(SensorEntityDescription):
SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = { SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = {
CHARGER_CHARGING_POWER_KEY: WallboxSensorEntityDescription( CHARGER_CHARGING_POWER_KEY: WallboxSensorEntityDescription(
key=CHARGER_CHARGING_POWER_KEY, key=CHARGER_CHARGING_POWER_KEY,
name="Charging Power", translation_key=CHARGER_CHARGING_POWER_KEY,
precision=2, precision=2,
native_unit_of_measurement=UnitOfPower.KILO_WATT, native_unit_of_measurement=UnitOfPower.KILO_WATT,
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
@ -68,7 +68,7 @@ SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = {
), ),
CHARGER_MAX_AVAILABLE_POWER_KEY: WallboxSensorEntityDescription( CHARGER_MAX_AVAILABLE_POWER_KEY: WallboxSensorEntityDescription(
key=CHARGER_MAX_AVAILABLE_POWER_KEY, key=CHARGER_MAX_AVAILABLE_POWER_KEY,
name="Max Available Power", translation_key=CHARGER_MAX_AVAILABLE_POWER_KEY,
precision=0, precision=0,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
@ -76,15 +76,15 @@ SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = {
), ),
CHARGER_CHARGING_SPEED_KEY: WallboxSensorEntityDescription( CHARGER_CHARGING_SPEED_KEY: WallboxSensorEntityDescription(
key=CHARGER_CHARGING_SPEED_KEY, key=CHARGER_CHARGING_SPEED_KEY,
translation_key=CHARGER_CHARGING_SPEED_KEY,
icon="mdi:speedometer", icon="mdi:speedometer",
name="Charging Speed",
precision=0, precision=0,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
CHARGER_ADDED_RANGE_KEY: WallboxSensorEntityDescription( CHARGER_ADDED_RANGE_KEY: WallboxSensorEntityDescription(
key=CHARGER_ADDED_RANGE_KEY, key=CHARGER_ADDED_RANGE_KEY,
translation_key=CHARGER_ADDED_RANGE_KEY,
icon="mdi:map-marker-distance", icon="mdi:map-marker-distance",
name="Added Range",
precision=0, precision=0,
native_unit_of_measurement=UnitOfLength.KILOMETERS, native_unit_of_measurement=UnitOfLength.KILOMETERS,
device_class=SensorDeviceClass.DISTANCE, device_class=SensorDeviceClass.DISTANCE,
@ -92,7 +92,7 @@ SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = {
), ),
CHARGER_ADDED_ENERGY_KEY: WallboxSensorEntityDescription( CHARGER_ADDED_ENERGY_KEY: WallboxSensorEntityDescription(
key=CHARGER_ADDED_ENERGY_KEY, key=CHARGER_ADDED_ENERGY_KEY,
name="Added Energy", translation_key=CHARGER_ADDED_ENERGY_KEY,
precision=2, precision=2,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY, device_class=SensorDeviceClass.ENERGY,
@ -100,7 +100,7 @@ SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = {
), ),
CHARGER_ADDED_DISCHARGED_ENERGY_KEY: WallboxSensorEntityDescription( CHARGER_ADDED_DISCHARGED_ENERGY_KEY: WallboxSensorEntityDescription(
key=CHARGER_ADDED_DISCHARGED_ENERGY_KEY, key=CHARGER_ADDED_DISCHARGED_ENERGY_KEY,
name="Discharged Energy", translation_key=CHARGER_ADDED_DISCHARGED_ENERGY_KEY,
precision=2, precision=2,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY, device_class=SensorDeviceClass.ENERGY,
@ -108,44 +108,44 @@ SENSOR_TYPES: dict[str, WallboxSensorEntityDescription] = {
), ),
CHARGER_COST_KEY: WallboxSensorEntityDescription( CHARGER_COST_KEY: WallboxSensorEntityDescription(
key=CHARGER_COST_KEY, key=CHARGER_COST_KEY,
translation_key=CHARGER_COST_KEY,
icon="mdi:ev-station", icon="mdi:ev-station",
name="Cost",
state_class=SensorStateClass.TOTAL_INCREASING, state_class=SensorStateClass.TOTAL_INCREASING,
), ),
CHARGER_STATE_OF_CHARGE_KEY: WallboxSensorEntityDescription( CHARGER_STATE_OF_CHARGE_KEY: WallboxSensorEntityDescription(
key=CHARGER_STATE_OF_CHARGE_KEY, key=CHARGER_STATE_OF_CHARGE_KEY,
name="State of Charge", translation_key=CHARGER_STATE_OF_CHARGE_KEY,
native_unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.BATTERY, device_class=SensorDeviceClass.BATTERY,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
CHARGER_CURRENT_MODE_KEY: WallboxSensorEntityDescription( CHARGER_CURRENT_MODE_KEY: WallboxSensorEntityDescription(
key=CHARGER_CURRENT_MODE_KEY, key=CHARGER_CURRENT_MODE_KEY,
translation_key=CHARGER_CURRENT_MODE_KEY,
icon="mdi:ev-station", icon="mdi:ev-station",
name="Current Mode",
), ),
CHARGER_DEPOT_PRICE_KEY: WallboxSensorEntityDescription( CHARGER_DEPOT_PRICE_KEY: WallboxSensorEntityDescription(
key=CHARGER_DEPOT_PRICE_KEY, key=CHARGER_DEPOT_PRICE_KEY,
translation_key=CHARGER_DEPOT_PRICE_KEY,
icon="mdi:ev-station", icon="mdi:ev-station",
name="Depot Price",
precision=2, precision=2,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
CHARGER_ENERGY_PRICE_KEY: WallboxSensorEntityDescription( CHARGER_ENERGY_PRICE_KEY: WallboxSensorEntityDescription(
key=CHARGER_ENERGY_PRICE_KEY, key=CHARGER_ENERGY_PRICE_KEY,
translation_key=CHARGER_ENERGY_PRICE_KEY,
icon="mdi:ev-station", icon="mdi:ev-station",
name="Energy Price",
precision=2, precision=2,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
CHARGER_STATUS_DESCRIPTION_KEY: WallboxSensorEntityDescription( CHARGER_STATUS_DESCRIPTION_KEY: WallboxSensorEntityDescription(
key=CHARGER_STATUS_DESCRIPTION_KEY, key=CHARGER_STATUS_DESCRIPTION_KEY,
translation_key=CHARGER_STATUS_DESCRIPTION_KEY,
icon="mdi:ev-station", icon="mdi:ev-station",
name="Status Description",
), ),
CHARGER_MAX_CHARGING_CURRENT_KEY: WallboxSensorEntityDescription( CHARGER_MAX_CHARGING_CURRENT_KEY: WallboxSensorEntityDescription(
key=CHARGER_MAX_CHARGING_CURRENT_KEY, key=CHARGER_MAX_CHARGING_CURRENT_KEY,
name="Max. Charging Current", translation_key=CHARGER_MAX_CHARGING_CURRENT_KEY,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
device_class=SensorDeviceClass.CURRENT, device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
@ -161,7 +161,7 @@ async def async_setup_entry(
async_add_entities( async_add_entities(
[ [
WallboxSensor(coordinator, entry, description) WallboxSensor(coordinator, description)
for ent in coordinator.data for ent in coordinator.data
if (description := SENSOR_TYPES.get(ent)) if (description := SENSOR_TYPES.get(ent))
] ]
@ -176,13 +176,11 @@ class WallboxSensor(WallboxEntity, SensorEntity):
def __init__( def __init__(
self, self,
coordinator: WallboxCoordinator, coordinator: WallboxCoordinator,
entry: ConfigEntry,
description: WallboxSensorEntityDescription, description: WallboxSensorEntityDescription,
) -> None: ) -> None:
"""Initialize a Wallbox sensor.""" """Initialize a Wallbox sensor."""
super().__init__(coordinator) super().__init__(coordinator)
self.entity_description = description self.entity_description = description
self._attr_name = f"{entry.title} {description.name}"
self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}" self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}"
@property @property

View File

@ -25,5 +25,63 @@
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
} }
},
"entity": {
"lock": {
"lock": {
"name": "[%key:component::lock::title%]"
}
},
"number": {
"maximum_charging_current": {
"name": "Maximum charging current"
}
},
"sensor": {
"charging_power": {
"name": "Charging power"
},
"max_available_power": {
"name": "Max available power"
},
"charging_speed": {
"name": "Charging speed"
},
"added_range": {
"name": "Added range"
},
"added_energy": {
"name": "Added energy"
},
"added_discharged_energy": {
"name": "Discharged energy"
},
"cost": {
"name": "Cost"
},
"state_of_charge": {
"name": "State of charge"
},
"current_mode": {
"name": "Current mode"
},
"depot_price": {
"name": "Depot price"
},
"energy_price": {
"name": "Energy price"
},
"status_description": {
"name": "Status description"
},
"max_charging_current": {
"name": "Max charging current"
}
},
"switch": {
"pause_resume": {
"name": "Pause/resume"
}
}
} }
} }

View File

@ -21,7 +21,7 @@ from .const import (
SWITCH_TYPES: dict[str, SwitchEntityDescription] = { SWITCH_TYPES: dict[str, SwitchEntityDescription] = {
CHARGER_PAUSE_RESUME_KEY: SwitchEntityDescription( CHARGER_PAUSE_RESUME_KEY: SwitchEntityDescription(
key=CHARGER_PAUSE_RESUME_KEY, key=CHARGER_PAUSE_RESUME_KEY,
name="Pause/Resume", translation_key="pause_resume",
), ),
} }
@ -32,7 +32,7 @@ async def async_setup_entry(
"""Create wallbox sensor entities in HASS.""" """Create wallbox sensor entities in HASS."""
coordinator: WallboxCoordinator = hass.data[DOMAIN][entry.entry_id] coordinator: WallboxCoordinator = hass.data[DOMAIN][entry.entry_id]
async_add_entities( async_add_entities(
[WallboxSwitch(coordinator, entry, SWITCH_TYPES[CHARGER_PAUSE_RESUME_KEY])] [WallboxSwitch(coordinator, SWITCH_TYPES[CHARGER_PAUSE_RESUME_KEY])]
) )
@ -42,13 +42,11 @@ class WallboxSwitch(WallboxEntity, SwitchEntity):
def __init__( def __init__(
self, self,
coordinator: WallboxCoordinator, coordinator: WallboxCoordinator,
entry: ConfigEntry,
description: SwitchEntityDescription, description: SwitchEntityDescription,
) -> None: ) -> None:
"""Initialize a Wallbox switch.""" """Initialize a Wallbox switch."""
super().__init__(coordinator) super().__init__(coordinator)
self.entity_description = description self.entity_description = description
self._attr_name = f"{entry.title} {description.name}"
self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}" self._attr_unique_id = f"{description.key}-{coordinator.data[CHARGER_DATA_KEY][CHARGER_SERIAL_NUMBER_KEY]}"
@property @property

View File

@ -5,9 +5,9 @@ TTL = "ttl"
ERROR = "error" ERROR = "error"
STATUS = "status" STATUS = "status"
MOCK_NUMBER_ENTITY_ID = "number.mock_title_max_charging_current" MOCK_NUMBER_ENTITY_ID = "number.wallbox_wallboxname_maximum_charging_current"
MOCK_LOCK_ENTITY_ID = "lock.mock_title_locked_unlocked" MOCK_LOCK_ENTITY_ID = "lock.wallbox_wallboxname_lock"
MOCK_SENSOR_CHARGING_SPEED_ID = "sensor.mock_title_charging_speed" MOCK_SENSOR_CHARGING_SPEED_ID = "sensor.wallbox_wallboxname_charging_speed"
MOCK_SENSOR_CHARGING_POWER_ID = "sensor.mock_title_charging_power" MOCK_SENSOR_CHARGING_POWER_ID = "sensor.wallbox_wallboxname_charging_power"
MOCK_SENSOR_MAX_AVAILABLE_POWER = "sensor.mock_title_max_available_power" MOCK_SENSOR_MAX_AVAILABLE_POWER = "sensor.wallbox_wallboxname_max_available_power"
MOCK_SWITCH_ENTITY_ID = "switch.mock_title_pause_resume" MOCK_SWITCH_ENTITY_ID = "switch.wallbox_wallboxname_pause_resume"

View File

@ -21,11 +21,11 @@ async def test_wallbox_sensor_class(
state = hass.states.get(MOCK_SENSOR_CHARGING_POWER_ID) state = hass.states.get(MOCK_SENSOR_CHARGING_POWER_ID)
assert state.attributes[CONF_UNIT_OF_MEASUREMENT] == UnitOfPower.KILO_WATT assert state.attributes[CONF_UNIT_OF_MEASUREMENT] == UnitOfPower.KILO_WATT
assert state.name == "Mock Title Charging Power" assert state.name == "Wallbox WallboxName Charging power"
state = hass.states.get(MOCK_SENSOR_CHARGING_SPEED_ID) state = hass.states.get(MOCK_SENSOR_CHARGING_SPEED_ID)
assert state.attributes[CONF_ICON] == "mdi:speedometer" assert state.attributes[CONF_ICON] == "mdi:speedometer"
assert state.name == "Mock Title Charging Speed" assert state.name == "Wallbox WallboxName Charging speed"
# Test round with precision '0' works # Test round with precision '0' works
state = hass.states.get(MOCK_SENSOR_MAX_AVAILABLE_POWER) state = hass.states.get(MOCK_SENSOR_MAX_AVAILABLE_POWER)