Add entity translations to Airzone (#99054)

This commit is contained in:
Joost Lekkerkerker 2023-10-28 13:56:45 +02:00 committed by GitHub
parent 8e112c04fb
commit 2601c6789d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 48 additions and 36 deletions

View File

@ -9,7 +9,6 @@ from aioairzone.const import (
AZD_BATTERY_LOW, AZD_BATTERY_LOW,
AZD_ERRORS, AZD_ERRORS,
AZD_FLOOR_DEMAND, AZD_FLOOR_DEMAND,
AZD_NAME,
AZD_PROBLEMS, AZD_PROBLEMS,
AZD_SYSTEMS, AZD_SYSTEMS,
AZD_ZONES, AZD_ZONES,
@ -45,7 +44,6 @@ SYSTEM_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ..
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
key=AZD_PROBLEMS, key=AZD_PROBLEMS,
name="Problem",
), ),
) )
@ -53,17 +51,16 @@ ZONE_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]
AirzoneBinarySensorEntityDescription( AirzoneBinarySensorEntityDescription(
device_class=BinarySensorDeviceClass.RUNNING, device_class=BinarySensorDeviceClass.RUNNING,
key=AZD_AIR_DEMAND, key=AZD_AIR_DEMAND,
name="Air Demand", translation_key="air_demand",
), ),
AirzoneBinarySensorEntityDescription( AirzoneBinarySensorEntityDescription(
device_class=BinarySensorDeviceClass.BATTERY, device_class=BinarySensorDeviceClass.BATTERY,
key=AZD_BATTERY_LOW, key=AZD_BATTERY_LOW,
name="Battery Low",
), ),
AirzoneBinarySensorEntityDescription( AirzoneBinarySensorEntityDescription(
device_class=BinarySensorDeviceClass.RUNNING, device_class=BinarySensorDeviceClass.RUNNING,
key=AZD_FLOOR_DEMAND, key=AZD_FLOOR_DEMAND,
name="Floor Demand", translation_key="floor_demand",
), ),
AirzoneBinarySensorEntityDescription( AirzoneBinarySensorEntityDescription(
attributes={ attributes={
@ -72,7 +69,6 @@ ZONE_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]
device_class=BinarySensorDeviceClass.PROBLEM, device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
key=AZD_PROBLEMS, key=AZD_PROBLEMS,
name="Problem",
), ),
) )
@ -149,7 +145,6 @@ class AirzoneSystemBinarySensor(AirzoneSystemEntity, AirzoneBinarySensor):
) -> None: ) -> None:
"""Initialize.""" """Initialize."""
super().__init__(coordinator, entry, system_data) super().__init__(coordinator, entry, system_data)
self._attr_name = f"System {system_id} {description.name}"
self._attr_unique_id = f"{self._attr_unique_id}_{system_id}_{description.key}" self._attr_unique_id = f"{self._attr_unique_id}_{system_id}_{description.key}"
self.entity_description = description self.entity_description = description
self._async_update_attrs() self._async_update_attrs()
@ -169,7 +164,6 @@ class AirzoneZoneBinarySensor(AirzoneZoneEntity, AirzoneBinarySensor):
"""Initialize.""" """Initialize."""
super().__init__(coordinator, entry, system_zone_id, zone_data) super().__init__(coordinator, entry, system_zone_id, zone_data)
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
self._attr_unique_id = ( self._attr_unique_id = (
f"{self._attr_unique_id}_{system_zone_id}_{description.key}" f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
) )

View File

@ -19,7 +19,6 @@ from aioairzone.const import (
AZD_MASTER, AZD_MASTER,
AZD_MODE, AZD_MODE,
AZD_MODES, AZD_MODES,
AZD_NAME,
AZD_ON, AZD_ON,
AZD_SPEED, AZD_SPEED,
AZD_SPEEDS, AZD_SPEEDS,
@ -114,6 +113,7 @@ async def async_setup_entry(
class AirzoneClimate(AirzoneZoneEntity, ClimateEntity): class AirzoneClimate(AirzoneZoneEntity, ClimateEntity):
"""Define an Airzone sensor.""" """Define an Airzone sensor."""
_attr_name = None
_speeds: dict[int, str] = {} _speeds: dict[int, str] = {}
_speeds_reverse: dict[str, int] = {} _speeds_reverse: dict[str, int] = {}
@ -127,7 +127,6 @@ class AirzoneClimate(AirzoneZoneEntity, ClimateEntity):
"""Initialize Airzone climate entity.""" """Initialize Airzone climate entity."""
super().__init__(coordinator, entry, system_zone_id, zone_data) super().__init__(coordinator, entry, system_zone_id, zone_data)
self._attr_name = f"{zone_data[AZD_NAME]}"
self._attr_unique_id = f"{self._attr_unique_id}_{system_zone_id}" self._attr_unique_id = f"{self._attr_unique_id}_{system_zone_id}"
self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE self._attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
self._attr_target_temperature_step = API_TEMPERATURE_STEP self._attr_target_temperature_step = API_TEMPERATURE_STEP

View File

@ -39,6 +39,8 @@ _LOGGER = logging.getLogger(__name__)
class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]): class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]):
"""Define an Airzone entity.""" """Define an Airzone entity."""
_attr_has_entity_name = True
def get_airzone_value(self, key: str) -> Any: def get_airzone_value(self, key: str) -> Any:
"""Return Airzone entity value by key.""" """Return Airzone entity value by key."""
raise NotImplementedError() raise NotImplementedError()
@ -62,7 +64,7 @@ class AirzoneSystemEntity(AirzoneEntity):
identifiers={(DOMAIN, f"{entry.entry_id}_{self.system_id}")}, identifiers={(DOMAIN, f"{entry.entry_id}_{self.system_id}")},
manufacturer=MANUFACTURER, manufacturer=MANUFACTURER,
model=self.get_airzone_value(AZD_MODEL), model=self.get_airzone_value(AZD_MODEL),
name=self.get_airzone_value(AZD_FULL_NAME), name=f"System {self.system_id}",
sw_version=self.get_airzone_value(AZD_FIRMWARE), sw_version=self.get_airzone_value(AZD_FIRMWARE),
via_device=(DOMAIN, f"{entry.entry_id}_ws"), via_device=(DOMAIN, f"{entry.entry_id}_ws"),
) )
@ -172,7 +174,7 @@ class AirzoneZoneEntity(AirzoneEntity):
identifiers={(DOMAIN, f"{entry.entry_id}_{system_zone_id}")}, identifiers={(DOMAIN, f"{entry.entry_id}_{system_zone_id}")},
manufacturer=MANUFACTURER, manufacturer=MANUFACTURER,
model=self.get_airzone_value(AZD_THERMOSTAT_MODEL), model=self.get_airzone_value(AZD_THERMOSTAT_MODEL),
name=f"Airzone [{system_zone_id}] {zone_data[AZD_NAME]}", name=zone_data[AZD_NAME],
sw_version=self.get_airzone_value(AZD_THERMOSTAT_FW), sw_version=self.get_airzone_value(AZD_THERMOSTAT_FW),
via_device=(DOMAIN, f"{entry.entry_id}_{self.system_id}"), via_device=(DOMAIN, f"{entry.entry_id}_{self.system_id}"),
) )

View File

@ -11,7 +11,6 @@ from aioairzone.const import (
API_SLEEP, API_SLEEP,
AZD_COLD_ANGLE, AZD_COLD_ANGLE,
AZD_HEAT_ANGLE, AZD_HEAT_ANGLE,
AZD_NAME,
AZD_SLEEP, AZD_SLEEP,
AZD_ZONES, AZD_ZONES,
) )
@ -60,7 +59,6 @@ ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = (
api_param=API_COLD_ANGLE, api_param=API_COLD_ANGLE,
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
key=AZD_COLD_ANGLE, key=AZD_COLD_ANGLE,
name="Cold Angle",
options=list(GRILLE_ANGLE_DICT), options=list(GRILLE_ANGLE_DICT),
options_dict=GRILLE_ANGLE_DICT, options_dict=GRILLE_ANGLE_DICT,
translation_key="grille_angles", translation_key="grille_angles",
@ -69,16 +67,14 @@ ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = (
api_param=API_HEAT_ANGLE, api_param=API_HEAT_ANGLE,
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
key=AZD_HEAT_ANGLE, key=AZD_HEAT_ANGLE,
name="Heat Angle",
options=list(GRILLE_ANGLE_DICT), options=list(GRILLE_ANGLE_DICT),
options_dict=GRILLE_ANGLE_DICT, options_dict=GRILLE_ANGLE_DICT,
translation_key="grille_angles", translation_key="heat_angles",
), ),
AirzoneSelectDescription( AirzoneSelectDescription(
api_param=API_SLEEP, api_param=API_SLEEP,
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
key=AZD_SLEEP, key=AZD_SLEEP,
name="Sleep",
options=list(SLEEP_DICT), options=list(SLEEP_DICT),
options_dict=SLEEP_DICT, options_dict=SLEEP_DICT,
translation_key="sleep_times", translation_key="sleep_times",
@ -146,7 +142,6 @@ class AirzoneZoneSelect(AirzoneZoneEntity, AirzoneBaseSelect):
"""Initialize.""" """Initialize."""
super().__init__(coordinator, entry, system_zone_id, zone_data) super().__init__(coordinator, entry, system_zone_id, zone_data)
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
self._attr_unique_id = ( self._attr_unique_id = (
f"{self._attr_unique_id}_{system_zone_id}_{description.key}" f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
) )

View File

@ -6,7 +6,6 @@ from typing import Any, Final
from aioairzone.const import ( from aioairzone.const import (
AZD_HOT_WATER, AZD_HOT_WATER,
AZD_HUMIDITY, AZD_HUMIDITY,
AZD_NAME,
AZD_TEMP, AZD_TEMP,
AZD_TEMP_UNIT, AZD_TEMP_UNIT,
AZD_WEBSERVER, AZD_WEBSERVER,
@ -54,7 +53,7 @@ WEBSERVER_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
entity_category=EntityCategory.DIAGNOSTIC, entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
key=AZD_WIFI_RSSI, key=AZD_WIFI_RSSI,
name="RSSI", translation_key="rssi",
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
@ -64,14 +63,12 @@ ZONE_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
SensorEntityDescription( SensorEntityDescription(
device_class=SensorDeviceClass.TEMPERATURE, device_class=SensorDeviceClass.TEMPERATURE,
key=AZD_TEMP, key=AZD_TEMP,
name="Temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS, native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
SensorEntityDescription( SensorEntityDescription(
device_class=SensorDeviceClass.HUMIDITY, device_class=SensorDeviceClass.HUMIDITY,
key=AZD_HUMIDITY, key=AZD_HUMIDITY,
name="Humidity",
native_unit_of_measurement=PERCENTAGE, native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
@ -144,8 +141,6 @@ class AirzoneSensor(AirzoneEntity, SensorEntity):
class AirzoneHotWaterSensor(AirzoneHotWaterEntity, AirzoneSensor): class AirzoneHotWaterSensor(AirzoneHotWaterEntity, AirzoneSensor):
"""Define an Airzone Hot Water sensor.""" """Define an Airzone Hot Water sensor."""
_attr_has_entity_name = True
def __init__( def __init__(
self, self,
coordinator: AirzoneUpdateCoordinator, coordinator: AirzoneUpdateCoordinator,
@ -176,7 +171,6 @@ class AirzoneWebServerSensor(AirzoneWebServerEntity, AirzoneSensor):
) -> None: ) -> None:
"""Initialize.""" """Initialize."""
super().__init__(coordinator, entry) super().__init__(coordinator, entry)
self._attr_name = f"WebServer {description.name}"
self._attr_unique_id = f"{self._attr_unique_id}_ws_{description.key}" self._attr_unique_id = f"{self._attr_unique_id}_ws_{description.key}"
self.entity_description = description self.entity_description = description
self._async_update_attrs() self._async_update_attrs()
@ -196,7 +190,6 @@ class AirzoneZoneSensor(AirzoneZoneEntity, AirzoneSensor):
"""Initialize.""" """Initialize."""
super().__init__(coordinator, entry, system_zone_id, zone_data) super().__init__(coordinator, entry, system_zone_id, zone_data)
self._attr_name = f"{zone_data[AZD_NAME]} {description.name}"
self._attr_unique_id = ( self._attr_unique_id = (
f"{self._attr_unique_id}_{system_zone_id}_{description.key}" f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
) )

View File

@ -25,8 +25,17 @@
} }
}, },
"entity": { "entity": {
"binary_sensor": {
"air_demand": {
"name": "Air demand"
},
"floor_demand": {
"name": "Floor demand"
}
},
"select": { "select": {
"grille_angles": { "grille_angles": {
"name": "Cold angle",
"state": { "state": {
"90deg": "90°", "90deg": "90°",
"50deg": "50°", "50deg": "50°",
@ -34,7 +43,17 @@
"40deg": "40°" "40deg": "40°"
} }
}, },
"heat_angles": {
"name": "Heat angle",
"state": {
"90deg": "[%key:component::airzone::entity::select::grille_angles::state::90deg%]",
"50deg": "[%key:component::airzone::entity::select::grille_angles::state::50deg%]",
"45deg": "[%key:component::airzone::entity::select::grille_angles::state::45deg%]",
"40deg": "[%key:component::airzone::entity::select::grille_angles::state::40deg%]"
}
},
"sleep_times": { "sleep_times": {
"name": "Sleep",
"state": { "state": {
"off": "[%key:common::state::off%]", "off": "[%key:common::state::off%]",
"30m": "30 minutes", "30m": "30 minutes",
@ -42,6 +61,11 @@
"90m": "90 minutes" "90m": "90 minutes"
} }
} }
},
"sensor": {
"rssi": {
"name": "RSSI"
}
} }
} }
} }

View File

@ -9,7 +9,6 @@ from aioairzone.const import (
API_ACS_POWER_MODE, API_ACS_POWER_MODE,
API_ACS_SET_POINT, API_ACS_SET_POINT,
AZD_HOT_WATER, AZD_HOT_WATER,
AZD_NAME,
AZD_OPERATION, AZD_OPERATION,
AZD_OPERATIONS, AZD_OPERATIONS,
AZD_TEMP, AZD_TEMP,
@ -67,6 +66,7 @@ async def async_setup_entry(
class AirzoneWaterHeater(AirzoneHotWaterEntity, WaterHeaterEntity): class AirzoneWaterHeater(AirzoneHotWaterEntity, WaterHeaterEntity):
"""Define an Airzone Water Heater.""" """Define an Airzone Water Heater."""
_attr_name = None
_attr_supported_features = ( _attr_supported_features = (
WaterHeaterEntityFeature.TARGET_TEMPERATURE WaterHeaterEntityFeature.TARGET_TEMPERATURE
| WaterHeaterEntityFeature.ON_OFF | WaterHeaterEntityFeature.ON_OFF
@ -81,7 +81,6 @@ class AirzoneWaterHeater(AirzoneHotWaterEntity, WaterHeaterEntity):
"""Initialize Airzone water heater entity.""" """Initialize Airzone water heater entity."""
super().__init__(coordinator, entry) super().__init__(coordinator, entry)
self._attr_name = self.get_airzone_value(AZD_NAME)
self._attr_unique_id = f"{self._attr_unique_id}_dhw" self._attr_unique_id = f"{self._attr_unique_id}_dhw"
self._attr_operation_list = [ self._attr_operation_list = [
OPERATION_LIB_TO_HASS[operation] OPERATION_LIB_TO_HASS[operation]

View File

@ -229,6 +229,7 @@
'mac': '**REDACTED**', 'mac': '**REDACTED**',
'wifi_channel': 6, 'wifi_channel': 6,
'wifi_rssi': -42, 'wifi_rssi': -42,
'ws_type': 'ws_az',
}), }),
}), }),
'config_entry': dict({ 'config_entry': dict({
@ -323,7 +324,9 @@
}), }),
'version': '1.62', 'version': '1.62',
'webserver': dict({ 'webserver': dict({
'full-name': 'Airzone WebServer',
'mac': '**REDACTED**', 'mac': '**REDACTED**',
'model': 'Airzone WebServer',
'wifi-channel': 6, 'wifi-channel': 6,
'wifi-rssi': -42, 'wifi-rssi': -42,
}), }),

View File

@ -21,7 +21,7 @@ async def test_airzone_create_binary_sensors(hass: HomeAssistant) -> None:
state = hass.states.get("binary_sensor.despacho_air_demand") state = hass.states.get("binary_sensor.despacho_air_demand")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.despacho_battery_low") state = hass.states.get("binary_sensor.despacho_battery")
assert state.state == STATE_ON assert state.state == STATE_ON
state = hass.states.get("binary_sensor.despacho_floor_demand") state = hass.states.get("binary_sensor.despacho_floor_demand")
@ -34,7 +34,7 @@ async def test_airzone_create_binary_sensors(hass: HomeAssistant) -> None:
state = hass.states.get("binary_sensor.dorm_1_air_demand") state = hass.states.get("binary_sensor.dorm_1_air_demand")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.dorm_1_battery_low") state = hass.states.get("binary_sensor.dorm_1_battery")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.dorm_1_floor_demand") state = hass.states.get("binary_sensor.dorm_1_floor_demand")
@ -46,7 +46,7 @@ async def test_airzone_create_binary_sensors(hass: HomeAssistant) -> None:
state = hass.states.get("binary_sensor.dorm_2_air_demand") state = hass.states.get("binary_sensor.dorm_2_air_demand")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.dorm_2_battery_low") state = hass.states.get("binary_sensor.dorm_2_battery")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.dorm_2_floor_demand") state = hass.states.get("binary_sensor.dorm_2_floor_demand")
@ -58,7 +58,7 @@ async def test_airzone_create_binary_sensors(hass: HomeAssistant) -> None:
state = hass.states.get("binary_sensor.dorm_ppal_air_demand") state = hass.states.get("binary_sensor.dorm_ppal_air_demand")
assert state.state == STATE_ON assert state.state == STATE_ON
state = hass.states.get("binary_sensor.dorm_ppal_battery_low") state = hass.states.get("binary_sensor.dorm_ppal_battery")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.dorm_ppal_floor_demand") state = hass.states.get("binary_sensor.dorm_ppal_floor_demand")
@ -70,7 +70,7 @@ async def test_airzone_create_binary_sensors(hass: HomeAssistant) -> None:
state = hass.states.get("binary_sensor.salon_air_demand") state = hass.states.get("binary_sensor.salon_air_demand")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.salon_battery_low") state = hass.states.get("binary_sensor.salon_battery")
assert state is None assert state is None
state = hass.states.get("binary_sensor.salon_floor_demand") state = hass.states.get("binary_sensor.salon_floor_demand")
@ -79,13 +79,13 @@ async def test_airzone_create_binary_sensors(hass: HomeAssistant) -> None:
state = hass.states.get("binary_sensor.salon_problem") state = hass.states.get("binary_sensor.salon_problem")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.airzone_2_1_battery_low") state = hass.states.get("binary_sensor.airzone_2_1_battery")
assert state is None assert state is None
state = hass.states.get("binary_sensor.airzone_2_1_problem") state = hass.states.get("binary_sensor.airzone_2_1_problem")
assert state.state == STATE_OFF assert state.state == STATE_OFF
state = hass.states.get("binary_sensor.dkn_plus_battery_low") state = hass.states.get("binary_sensor.dkn_plus_battery")
assert state is None assert state is None
state = hass.states.get("binary_sensor.dkn_plus_problem") state = hass.states.get("binary_sensor.dkn_plus_problem")

View File

@ -34,7 +34,7 @@ async def test_airzone_create_sensors(
assert state.state == "43" assert state.state == "43"
# WebServer # WebServer
state = hass.states.get("sensor.webserver_rssi") state = hass.states.get("sensor.airzone_webserver_rssi")
assert state.state == "-42" assert state.state == "-42"
# Zones # Zones

View File

@ -50,6 +50,8 @@ from aioairzone.const import (
API_VERSION, API_VERSION,
API_WIFI_CHANNEL, API_WIFI_CHANNEL,
API_WIFI_RSSI, API_WIFI_RSSI,
API_WS_AZ,
API_WS_TYPE,
API_ZONE_ID, API_ZONE_ID,
) )
@ -301,6 +303,7 @@ HVAC_VERSION_MOCK = {
HVAC_WEBSERVER_MOCK = { HVAC_WEBSERVER_MOCK = {
API_MAC: "11:22:33:44:55:66", API_MAC: "11:22:33:44:55:66",
API_WS_TYPE: API_WS_AZ,
API_WIFI_CHANNEL: 6, API_WIFI_CHANNEL: 6,
API_WIFI_RSSI: -42, API_WIFI_RSSI: -42,
} }