Add entity name translations to AVM Fritz!SmartHome (#90707)

* add entity name translation

* sort and capitalize

* adjust tests

* sort entities
This commit is contained in:
Michael 2023-04-03 19:04:09 +02:00 committed by Paulus Schoutsen
parent 0c12d45581
commit eaaf24d326
7 changed files with 67 additions and 42 deletions

View File

@ -113,8 +113,8 @@ class FritzBoxEntity(CoordinatorEntity[FritzboxDataUpdateCoordinator], ABC):
self.ain = ain self.ain = ain
if entity_description is not None: if entity_description is not None:
self._attr_has_entity_name = True
self.entity_description = entity_description self.entity_description = entity_description
self._attr_name = f"{self.data.name} {entity_description.name}"
self._attr_unique_id = f"{ain}_{entity_description.key}" self._attr_unique_id = f"{ain}_{entity_description.key}"
else: else:
self._attr_name = self.data.name self._attr_name = self.data.name

View File

@ -40,14 +40,14 @@ class FritzBinarySensorEntityDescription(
BINARY_SENSOR_TYPES: Final[tuple[FritzBinarySensorEntityDescription, ...]] = ( BINARY_SENSOR_TYPES: Final[tuple[FritzBinarySensorEntityDescription, ...]] = (
FritzBinarySensorEntityDescription( FritzBinarySensorEntityDescription(
key="alarm", key="alarm",
name="Alarm", translation_key="alarm",
device_class=BinarySensorDeviceClass.WINDOW, device_class=BinarySensorDeviceClass.WINDOW,
suitable=lambda device: device.has_alarm, # type: ignore[no-any-return] suitable=lambda device: device.has_alarm, # type: ignore[no-any-return]
is_on=lambda device: device.alert_state, # type: ignore[no-any-return] is_on=lambda device: device.alert_state, # type: ignore[no-any-return]
), ),
FritzBinarySensorEntityDescription( FritzBinarySensorEntityDescription(
key="lock", key="lock",
name="Button Lock on Device", translation_key="lock",
device_class=BinarySensorDeviceClass.LOCK, device_class=BinarySensorDeviceClass.LOCK,
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
suitable=lambda device: device.lock is not None, suitable=lambda device: device.lock is not None,
@ -55,7 +55,7 @@ BINARY_SENSOR_TYPES: Final[tuple[FritzBinarySensorEntityDescription, ...]] = (
), ),
FritzBinarySensorEntityDescription( FritzBinarySensorEntityDescription(
key="device_lock", key="device_lock",
name="Button Lock via UI", translation_key="device_lock",
device_class=BinarySensorDeviceClass.LOCK, device_class=BinarySensorDeviceClass.LOCK,
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
suitable=lambda device: device.device_lock is not None, suitable=lambda device: device.device_lock is not None,
@ -87,17 +87,6 @@ class FritzboxBinarySensor(FritzBoxDeviceEntity, BinarySensorEntity):
entity_description: FritzBinarySensorEntityDescription entity_description: FritzBinarySensorEntityDescription
def __init__(
self,
coordinator: FritzboxDataUpdateCoordinator,
ain: str,
entity_description: FritzBinarySensorEntityDescription,
) -> None:
"""Initialize the FritzBox entity."""
super().__init__(coordinator, ain, entity_description)
self._attr_name = f"{self.data.name} {entity_description.name}"
self._attr_unique_id = f"{ain}_{entity_description.key}"
@property @property
def is_on(self) -> bool | None: def is_on(self) -> bool | None:
"""Return true if sensor is on.""" """Return true if sensor is on."""

View File

@ -91,7 +91,7 @@ def value_scheduled_preset(device: FritzhomeDevice) -> str:
SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = ( SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="temperature", key="temperature",
name="Temperature", translation_key="temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS, native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE, device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
@ -101,7 +101,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="humidity", key="humidity",
name="Humidity", translation_key="humidity",
native_unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY, device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
@ -110,7 +110,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="battery", key="battery",
name="Battery", translation_key="battery",
native_unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.BATTERY, device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
@ -119,7 +119,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="power_consumption", key="power_consumption",
name="Power Consumption", translation_key="power_consumption",
native_unit_of_measurement=UnitOfPower.WATT, native_unit_of_measurement=UnitOfPower.WATT,
device_class=SensorDeviceClass.POWER, device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
@ -128,7 +128,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="voltage", key="voltage",
name="Voltage", translation_key="voltage",
native_unit_of_measurement=UnitOfElectricPotential.VOLT, native_unit_of_measurement=UnitOfElectricPotential.VOLT,
device_class=SensorDeviceClass.VOLTAGE, device_class=SensorDeviceClass.VOLTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
@ -137,7 +137,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="electric_current", key="electric_current",
name="Electric Current", translation_key="electric_current",
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,
@ -146,7 +146,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="total_energy", key="total_energy",
name="Total Energy", translation_key="total_energy",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
device_class=SensorDeviceClass.ENERGY, device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING, state_class=SensorStateClass.TOTAL_INCREASING,
@ -156,7 +156,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
# Thermostat Sensors # Thermostat Sensors
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="comfort_temperature", key="comfort_temperature",
name="Comfort Temperature", translation_key="comfort_temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS, native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE, device_class=SensorDeviceClass.TEMPERATURE,
suitable=suitable_comfort_temperature, suitable=suitable_comfort_temperature,
@ -164,7 +164,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="eco_temperature", key="eco_temperature",
name="Eco Temperature", translation_key="eco_temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS, native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE, device_class=SensorDeviceClass.TEMPERATURE,
suitable=suitable_eco_temperature, suitable=suitable_eco_temperature,
@ -172,7 +172,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="nextchange_temperature", key="nextchange_temperature",
name="Next Scheduled Temperature", translation_key="nextchange_temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS, native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE, device_class=SensorDeviceClass.TEMPERATURE,
suitable=suitable_nextchange_temperature, suitable=suitable_nextchange_temperature,
@ -180,20 +180,20 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="nextchange_time", key="nextchange_time",
name="Next Scheduled Change Time", translation_key="nextchange_time",
device_class=SensorDeviceClass.TIMESTAMP, device_class=SensorDeviceClass.TIMESTAMP,
suitable=suitable_nextchange_time, suitable=suitable_nextchange_time,
native_value=lambda device: utc_from_timestamp(device.nextchange_endperiod), native_value=lambda device: utc_from_timestamp(device.nextchange_endperiod),
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="nextchange_preset", key="nextchange_preset",
name="Next Scheduled Preset", translation_key="nextchange_preset",
suitable=suitable_nextchange_temperature, suitable=suitable_nextchange_temperature,
native_value=value_nextchange_preset, native_value=value_nextchange_preset,
), ),
FritzSensorEntityDescription( FritzSensorEntityDescription(
key="scheduled_preset", key="scheduled_preset",
name="Current Scheduled Preset", translation_key="scheduled_preset",
suitable=suitable_nextchange_temperature, suitable=suitable_nextchange_temperature,
native_value=value_scheduled_preset, native_value=value_scheduled_preset,
), ),

View File

@ -36,5 +36,41 @@
"error": { "error": {
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]" "invalid_auth": "[%key:common::config_flow::error::invalid_auth%]"
} }
},
"entity": {
"binary_sensor": {
"alarm": { "name": "Alarm" },
"device_lock": { "name": "Button lock via UI" },
"lock": { "name": "Button lock on device" }
},
"sensor": {
"battery": {
"name": "[%key:component::sensor::entity_component::battery::name%]"
},
"comfort_temperature": { "name": "Comfort temperature" },
"eco_temperature": { "name": "Eco temperature" },
"electric_current": {
"name": "[%key:component::sensor::entity_component::current::name%]"
},
"humidity": {
"name": "[%key:component::sensor::entity_component::humidity::name%]"
},
"nextchange_preset": { "name": "Next scheduled preset" },
"nextchange_temperature": { "name": "Next scheduled temperature" },
"nextchange_time": { "name": "Next scheduled change time" },
"power_consumption": {
"name": "[%key:component::sensor::entity_component::power::name%]"
},
"scheduled_preset": { "name": "Current scheduled preset" },
"temperature": {
"name": "[%key:component::sensor::entity_component::temperature::name%]"
},
"total_energy": {
"name": "[%key:component::sensor::entity_component::energy::name%]"
},
"voltage": {
"name": "[%key:component::sensor::entity_component::voltage::name%]"
}
}
} }
} }

View File

@ -48,7 +48,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
assert state.state == STATE_OFF assert state.state == STATE_OFF
assert ( assert (
state.attributes[ATTR_FRIENDLY_NAME] state.attributes[ATTR_FRIENDLY_NAME]
== f"{CONF_FAKE_NAME} Button Lock on Device" == f"{CONF_FAKE_NAME} Button lock on device"
) )
assert state.attributes[ATTR_DEVICE_CLASS] == BinarySensorDeviceClass.LOCK assert state.attributes[ATTR_DEVICE_CLASS] == BinarySensorDeviceClass.LOCK
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes
@ -57,7 +57,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
assert state assert state
assert state.state == STATE_OFF assert state.state == STATE_OFF
assert ( assert (
state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Button Lock via UI" state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Button lock via UI"
) )
assert state.attributes[ATTR_DEVICE_CLASS] == BinarySensorDeviceClass.LOCK assert state.attributes[ATTR_DEVICE_CLASS] == BinarySensorDeviceClass.LOCK
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes

View File

@ -85,7 +85,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
assert state assert state
assert state.state == "22.0" assert state.state == "22.0"
assert ( assert (
state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Comfort Temperature" state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Comfort temperature"
) )
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == UnitOfTemperature.CELSIUS assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == UnitOfTemperature.CELSIUS
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes
@ -93,7 +93,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_eco_temperature") state = hass.states.get(f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_eco_temperature")
assert state assert state
assert state.state == "16.0" assert state.state == "16.0"
assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Eco Temperature" assert state.attributes[ATTR_FRIENDLY_NAME] == f"{CONF_FAKE_NAME} Eco temperature"
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == UnitOfTemperature.CELSIUS assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == UnitOfTemperature.CELSIUS
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes
@ -104,7 +104,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
assert state.state == "22.0" assert state.state == "22.0"
assert ( assert (
state.attributes[ATTR_FRIENDLY_NAME] state.attributes[ATTR_FRIENDLY_NAME]
== f"{CONF_FAKE_NAME} Next Scheduled Temperature" == f"{CONF_FAKE_NAME} Next scheduled temperature"
) )
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == UnitOfTemperature.CELSIUS assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == UnitOfTemperature.CELSIUS
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes
@ -116,7 +116,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
assert state.state == "1970-01-01T00:00:00+00:00" assert state.state == "1970-01-01T00:00:00+00:00"
assert ( assert (
state.attributes[ATTR_FRIENDLY_NAME] state.attributes[ATTR_FRIENDLY_NAME]
== f"{CONF_FAKE_NAME} Next Scheduled Change Time" == f"{CONF_FAKE_NAME} Next scheduled change time"
) )
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes
@ -125,7 +125,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
assert state.state == PRESET_COMFORT assert state.state == PRESET_COMFORT
assert ( assert (
state.attributes[ATTR_FRIENDLY_NAME] state.attributes[ATTR_FRIENDLY_NAME]
== f"{CONF_FAKE_NAME} Next Scheduled Preset" == f"{CONF_FAKE_NAME} Next scheduled preset"
) )
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes
@ -136,7 +136,7 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
assert state.state == PRESET_ECO assert state.state == PRESET_ECO
assert ( assert (
state.attributes[ATTR_FRIENDLY_NAME] state.attributes[ATTR_FRIENDLY_NAME]
== f"{CONF_FAKE_NAME} Current Scheduled Preset" == f"{CONF_FAKE_NAME} Current scheduled preset"
) )
assert ATTR_STATE_CLASS not in state.attributes assert ATTR_STATE_CLASS not in state.attributes

View File

@ -62,16 +62,16 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
SensorStateClass.MEASUREMENT, SensorStateClass.MEASUREMENT,
], ],
[ [
f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_power_consumption", f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_power",
"5.678", "5.678",
f"{CONF_FAKE_NAME} Power Consumption", f"{CONF_FAKE_NAME} Power",
UnitOfPower.WATT, UnitOfPower.WATT,
SensorStateClass.MEASUREMENT, SensorStateClass.MEASUREMENT,
], ],
[ [
f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_total_energy", f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_energy",
"1.234", "1.234",
f"{CONF_FAKE_NAME} Total Energy", f"{CONF_FAKE_NAME} Energy",
UnitOfEnergy.KILO_WATT_HOUR, UnitOfEnergy.KILO_WATT_HOUR,
SensorStateClass.TOTAL_INCREASING, SensorStateClass.TOTAL_INCREASING,
], ],
@ -83,9 +83,9 @@ async def test_setup(hass: HomeAssistant, fritz: Mock) -> None:
SensorStateClass.MEASUREMENT, SensorStateClass.MEASUREMENT,
], ],
[ [
f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_electric_current", f"{SENSOR_DOMAIN}.{CONF_FAKE_NAME}_current",
"0.025", "0.025",
f"{CONF_FAKE_NAME} Electric Current", f"{CONF_FAKE_NAME} Current",
UnitOfElectricCurrent.AMPERE, UnitOfElectricCurrent.AMPERE,
SensorStateClass.MEASUREMENT, SensorStateClass.MEASUREMENT,
], ],