Add entity translations to devolo Home Control (#132927)

This commit is contained in:
Guido Schmitz 2024-12-18 14:38:29 +01:00 committed by GitHub
parent a46a0ad2b4
commit 9716183997
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 157 additions and 50 deletions

View File

@ -81,14 +81,8 @@ class DevoloBinaryDeviceEntity(DevoloDeviceEntity, BinarySensorEntity):
or self._binary_sensor_property.sensor_type
)
if device_instance.binary_sensor_property[element_uid].sub_type != "":
self._attr_name = device_instance.binary_sensor_property[
element_uid
].sub_type.capitalize()
else:
self._attr_name = device_instance.binary_sensor_property[
element_uid
].sensor_type.capitalize()
if device_instance.binary_sensor_property[element_uid].sub_type == "overload":
self._attr_translation_key = "overload"
self._value = self._binary_sensor_property.state
@ -129,7 +123,8 @@ class DevoloRemoteControl(DevoloDeviceEntity, BinarySensorEntity):
self._key = key
self._attr_is_on = False
self._attr_name = f"Button {key}"
self._attr_translation_key = "button"
self._attr_translation_placeholders = {"key": str(key)}
def _sync(self, message: tuple) -> None:
"""Update the binary sensor state."""

View File

@ -116,9 +116,11 @@ class DevoloGenericMultiLevelDeviceEntity(DevoloMultiLevelDeviceEntity):
self._multi_level_sensor_property.sensor_type
)
self._attr_native_unit_of_measurement = self._multi_level_sensor_property.unit
self._attr_name = self._multi_level_sensor_property.sensor_type.capitalize()
self._value = self._multi_level_sensor_property.value
if self._multi_level_sensor_property.sensor_type == "light":
self._attr_translation_key = "brightness"
if element_uid.startswith("devolo.VoltageMultiLevelSensor:"):
self._attr_entity_registry_enabled_default = False
@ -128,7 +130,6 @@ class DevoloBatteryEntity(DevoloMultiLevelDeviceEntity):
_attr_entity_category = EntityCategory.DIAGNOSTIC
_attr_native_unit_of_measurement = PERCENTAGE
_attr_name = "Battery level"
_attr_device_class = SensorDeviceClass.BATTERY
_attr_state_class = SensorStateClass.MEASUREMENT
@ -175,8 +176,6 @@ class DevoloConsumptionEntity(DevoloMultiLevelDeviceEntity):
device_instance.consumption_property[element_uid], consumption
)
self._attr_name = f"{consumption.capitalize()} consumption"
@property
def unique_id(self) -> str:
"""Return the unique ID of the entity.

View File

@ -30,5 +30,20 @@
}
}
}
},
"entity": {
"binary_sensor": {
"button": {
"name": "Button {key}"
},
"overload": {
"name": "Overload"
}
},
"sensor": {
"brightness": {
"name": "Brightness"
}
}
}
}

View File

@ -70,6 +70,18 @@ class MultiLevelSensorPropertyMock(MultiLevelSensorProperty):
self._logger = MagicMock()
class BrightnessSensorPropertyMock(MultiLevelSensorProperty):
"""devolo Home Control brightness sensor mock."""
def __init__(self, **kwargs: Any) -> None: # pylint: disable=super-init-not-called
"""Initialize the mock."""
self.element_uid = "Test"
self.sensor_type = "light"
self._unit = "%"
self._value = 20
self._logger = MagicMock()
class MultiLevelSwitchPropertyMock(MultiLevelSwitchProperty):
"""devolo Home Control multi level switch mock."""
@ -138,7 +150,18 @@ class BinarySensorMockOverload(DeviceMock):
"""Initialize the mock."""
super().__init__()
self.binary_sensor_property = {"Overload": BinarySensorPropertyMock()}
self.binary_sensor_property["Overload"].sensor_type = "overload"
self.binary_sensor_property["Overload"].sub_type = "overload"
class BrightnessSensorMock(DeviceMock):
"""devolo Home Control brightness sensor device mock."""
def __init__(self) -> None:
"""Initialize the mock."""
super().__init__()
self.multi_level_sensor_property = {
"devolo.MultiLevelSensor:Test": BrightnessSensorPropertyMock()
}
class ClimateMock(DeviceMock):
@ -275,6 +298,19 @@ class HomeControlMockBinarySensor(HomeControlMock):
self.publisher.unregister = MagicMock()
class HomeControlMockBrightness(HomeControlMock):
"""devolo Home Control gateway mock with brightness devices."""
def __init__(self, **kwargs: Any) -> None:
"""Initialize the mock."""
super().__init__()
self.devices = {
"Test": BrightnessSensorMock(),
}
self.publisher = Publisher(self.devices.keys())
self.publisher.unregister = MagicMock()
class HomeControlMockClimate(HomeControlMock):
"""devolo Home Control gateway mock with climate devices."""

View File

@ -88,7 +88,7 @@
'platform': 'devolo_home_control',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'translation_key': 'overload',
'unique_id': 'Overload',
'unit_of_measurement': None,
})
@ -134,7 +134,7 @@
'platform': 'devolo_home_control',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'translation_key': 'button',
'unique_id': 'Test_1',
'unit_of_measurement': None,
})

View File

@ -3,12 +3,12 @@
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery',
'friendly_name': 'Test Battery level',
'friendly_name': 'Test Battery',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.test_battery_level',
'entity_id': 'sensor.test_battery',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@ -29,7 +29,7 @@
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.test_battery_level',
'entity_id': 'sensor.test_battery',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
@ -41,7 +41,7 @@
}),
'original_device_class': <SensorDeviceClass.BATTERY: 'battery'>,
'original_icon': None,
'original_name': 'Battery level',
'original_name': 'Battery',
'platform': 'devolo_home_control',
'previous_unique_id': None,
'supported_features': 0,
@ -50,16 +50,66 @@
'unit_of_measurement': '%',
})
# ---
# name: test_brightness_sensor
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Brightness',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.test_brightness',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '20',
})
# ---
# name: test_brightness_sensor.1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_brightness',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Brightness',
'platform': 'devolo_home_control',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'brightness',
'unique_id': 'devolo.MultiLevelSensor:Test',
'unit_of_measurement': '%',
})
# ---
# name: test_consumption_sensor
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'power',
'friendly_name': 'Test Current consumption',
'friendly_name': 'Test Power',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'W',
}),
'context': <ANY>,
'entity_id': 'sensor.test_current_consumption',
'entity_id': 'sensor.test_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@ -80,7 +130,7 @@
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_current_consumption',
'entity_id': 'sensor.test_power',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
@ -92,7 +142,7 @@
}),
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
'original_icon': None,
'original_name': 'Current consumption',
'original_name': 'Power',
'platform': 'devolo_home_control',
'previous_unique_id': None,
'supported_features': 0,
@ -105,12 +155,12 @@
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'energy',
'friendly_name': 'Test Total consumption',
'friendly_name': 'Test Energy',
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
'unit_of_measurement': 'kWh',
}),
'context': <ANY>,
'entity_id': 'sensor.test_total_consumption',
'entity_id': 'sensor.test_energy',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@ -131,7 +181,7 @@
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.test_total_consumption',
'entity_id': 'sensor.test_energy',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
@ -143,7 +193,7 @@
}),
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
'original_icon': None,
'original_name': 'Total consumption',
'original_name': 'Energy',
'platform': 'devolo_home_control',
'previous_unique_id': None,
'supported_features': 0,

View File

@ -10,7 +10,30 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import configure_integration
from .mocks import HomeControlMock, HomeControlMockConsumption, HomeControlMockSensor
from .mocks import (
HomeControlMock,
HomeControlMockBrightness,
HomeControlMockConsumption,
HomeControlMockSensor,
)
async def test_brightness_sensor(
hass: HomeAssistant, entity_registry: er.EntityRegistry, snapshot: SnapshotAssertion
) -> None:
"""Test setup of a brightness sensor device."""
entry = configure_integration(hass)
test_gateway = HomeControlMockBrightness()
with patch(
"homeassistant.components.devolo_home_control.HomeControl",
side_effect=[test_gateway, HomeControlMock()],
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(f"{SENSOR_DOMAIN}.test_brightness")
assert state == snapshot
assert entity_registry.async_get(f"{SENSOR_DOMAIN}.test_brightness") == snapshot
async def test_temperature_sensor(
@ -45,14 +68,14 @@ async def test_battery_sensor(
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(f"{SENSOR_DOMAIN}.test_battery_level")
state = hass.states.get(f"{SENSOR_DOMAIN}.test_battery")
assert state == snapshot
assert entity_registry.async_get(f"{SENSOR_DOMAIN}.test_battery_level") == snapshot
assert entity_registry.async_get(f"{SENSOR_DOMAIN}.test_battery") == snapshot
# Emulate websocket message: value changed
test_gateway.publisher.dispatch("Test", ("Test", 10, "battery_level"))
await hass.async_block_till_done()
assert hass.states.get(f"{SENSOR_DOMAIN}.test_battery_level").state == "10"
assert hass.states.get(f"{SENSOR_DOMAIN}.test_battery").state == "10"
async def test_consumption_sensor(
@ -68,37 +91,26 @@ async def test_consumption_sensor(
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(f"{SENSOR_DOMAIN}.test_current_consumption")
state = hass.states.get(f"{SENSOR_DOMAIN}.test_power")
assert state == snapshot
assert (
entity_registry.async_get(f"{SENSOR_DOMAIN}.test_current_consumption")
== snapshot
)
assert entity_registry.async_get(f"{SENSOR_DOMAIN}.test_power") == snapshot
state = hass.states.get(f"{SENSOR_DOMAIN}.test_total_consumption")
state = hass.states.get(f"{SENSOR_DOMAIN}.test_energy")
assert state == snapshot
assert (
entity_registry.async_get(f"{SENSOR_DOMAIN}.test_total_consumption") == snapshot
)
assert entity_registry.async_get(f"{SENSOR_DOMAIN}.test_energy") == snapshot
# Emulate websocket message: value changed
test_gateway.devices["Test"].consumption_property["devolo.Meter:Test"].total = 50.0
test_gateway.publisher.dispatch("Test", ("devolo.Meter:Test", 50.0))
await hass.async_block_till_done()
assert hass.states.get(f"{SENSOR_DOMAIN}.test_total_consumption").state == "50.0"
assert hass.states.get(f"{SENSOR_DOMAIN}.test_energy").state == "50.0"
# Emulate websocket message: device went offline
test_gateway.devices["Test"].status = 1
test_gateway.publisher.dispatch("Test", ("Status", False, "status"))
await hass.async_block_till_done()
assert (
hass.states.get(f"{SENSOR_DOMAIN}.test_current_consumption").state
== STATE_UNAVAILABLE
)
assert (
hass.states.get(f"{SENSOR_DOMAIN}.test_total_consumption").state
== STATE_UNAVAILABLE
)
assert hass.states.get(f"{SENSOR_DOMAIN}.test_power").state == STATE_UNAVAILABLE
assert hass.states.get(f"{SENSOR_DOMAIN}.test_energy").state == STATE_UNAVAILABLE
async def test_voltage_sensor(hass: HomeAssistant) -> None: