Migrate Gree to has entity name (#104739)

* Migrate Gree to has entity name

* Migrate Gree to has entity name
This commit is contained in:
Joost Lekkerkerker 2023-12-07 22:47:52 +01:00 committed by GitHub
parent c4d77877d2
commit 00e87b9dff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 49 deletions

View file

@ -38,10 +38,8 @@ from homeassistant.components.climate import (
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .bridge import DeviceDataUpdateCoordinator from .bridge import DeviceDataUpdateCoordinator
from .const import ( from .const import (
@ -52,6 +50,7 @@ from .const import (
FAN_MEDIUM_LOW, FAN_MEDIUM_LOW,
TARGET_TEMPERATURE_STEP, TARGET_TEMPERATURE_STEP,
) )
from .entity import GreeEntity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -105,7 +104,7 @@ async def async_setup_entry(
) )
class GreeClimateEntity(CoordinatorEntity[DeviceDataUpdateCoordinator], ClimateEntity): class GreeClimateEntity(GreeEntity, ClimateEntity):
"""Representation of a Gree HVAC device.""" """Representation of a Gree HVAC device."""
_attr_precision = PRECISION_WHOLE _attr_precision = PRECISION_WHOLE
@ -120,19 +119,12 @@ class GreeClimateEntity(CoordinatorEntity[DeviceDataUpdateCoordinator], ClimateE
_attr_preset_modes = PRESET_MODES _attr_preset_modes = PRESET_MODES
_attr_fan_modes = [*FAN_MODES_REVERSE] _attr_fan_modes = [*FAN_MODES_REVERSE]
_attr_swing_modes = SWING_MODES _attr_swing_modes = SWING_MODES
_attr_name = None
def __init__(self, coordinator: DeviceDataUpdateCoordinator) -> None: def __init__(self, coordinator: DeviceDataUpdateCoordinator) -> None:
"""Initialize the Gree device.""" """Initialize the Gree device."""
super().__init__(coordinator) super().__init__(coordinator)
self._attr_name = coordinator.device.device_info.name self._attr_unique_id = coordinator.device.device_info.mac
mac = coordinator.device.device_info.mac
self._attr_unique_id = mac
self._attr_device_info = DeviceInfo(
connections={(CONNECTION_NETWORK_MAC, mac)},
identifiers={(DOMAIN, mac)},
manufacturer="Gree",
name=self._attr_name,
)
units = self.coordinator.device.temperature_units units = self.coordinator.device.temperature_units
if units == TemperatureUnits.C: if units == TemperatureUnits.C:
self._attr_temperature_unit = UnitOfTemperature.CELSIUS self._attr_temperature_unit = UnitOfTemperature.CELSIUS

View file

@ -9,13 +9,15 @@ from .const import DOMAIN
class GreeEntity(CoordinatorEntity[DeviceDataUpdateCoordinator]): class GreeEntity(CoordinatorEntity[DeviceDataUpdateCoordinator]):
"""Generic Gree entity (base class).""" """Generic Gree entity (base class)."""
def __init__(self, coordinator: DeviceDataUpdateCoordinator, desc: str) -> None: _attr_has_entity_name = True
def __init__(
self, coordinator: DeviceDataUpdateCoordinator, desc: str | None = None
) -> None:
"""Initialize the entity.""" """Initialize the entity."""
super().__init__(coordinator) super().__init__(coordinator)
self._desc = desc
name = coordinator.device.device_info.name name = coordinator.device.device_info.name
mac = coordinator.device.device_info.mac mac = coordinator.device.device_info.mac
self._attr_name = f"{name} {desc}"
self._attr_unique_id = f"{mac}_{desc}" self._attr_unique_id = f"{mac}_{desc}"
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
connections={(CONNECTION_NETWORK_MAC, mac)}, connections={(CONNECTION_NETWORK_MAC, mac)},

View file

@ -9,5 +9,24 @@
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]", "single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]" "no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]"
} }
},
"entity": {
"switch": {
"light": {
"name": "Panel light"
},
"quiet": {
"name": "Quiet"
},
"fresh_air": {
"name": "Fresh air"
},
"xfan": {
"name": "XFan"
},
"health_mode": {
"name": "Health mode"
}
}
} }
} }

View file

@ -33,10 +33,6 @@ class GreeRequiredKeysMixin:
class GreeSwitchEntityDescription(SwitchEntityDescription, GreeRequiredKeysMixin): class GreeSwitchEntityDescription(SwitchEntityDescription, GreeRequiredKeysMixin):
"""Describes Gree switch entity.""" """Describes Gree switch entity."""
# GreeSwitch does not support UNDEFINED or None,
# restrict the type to str.
name: str = ""
def _set_light(device: Device, value: bool) -> None: def _set_light(device: Device, value: bool) -> None:
"""Typed helper to set device light property.""" """Typed helper to set device light property."""
@ -66,33 +62,33 @@ def _set_anion(device: Device, value: bool) -> None:
GREE_SWITCHES: tuple[GreeSwitchEntityDescription, ...] = ( GREE_SWITCHES: tuple[GreeSwitchEntityDescription, ...] = (
GreeSwitchEntityDescription( GreeSwitchEntityDescription(
icon="mdi:lightbulb", icon="mdi:lightbulb",
name="Panel Light", key="Panel Light",
key="light", translation_key="light",
get_value_fn=lambda d: d.light, get_value_fn=lambda d: d.light,
set_value_fn=_set_light, set_value_fn=_set_light,
), ),
GreeSwitchEntityDescription( GreeSwitchEntityDescription(
name="Quiet", key="Quiet",
key="quiet", translation_key="quiet",
get_value_fn=lambda d: d.quiet, get_value_fn=lambda d: d.quiet,
set_value_fn=_set_quiet, set_value_fn=_set_quiet,
), ),
GreeSwitchEntityDescription( GreeSwitchEntityDescription(
name="Fresh Air", key="Fresh Air",
key="fresh_air", translation_key="fresh_air",
get_value_fn=lambda d: d.fresh_air, get_value_fn=lambda d: d.fresh_air,
set_value_fn=_set_fresh_air, set_value_fn=_set_fresh_air,
), ),
GreeSwitchEntityDescription( GreeSwitchEntityDescription(
name="XFan", key="XFan",
key="xfan", translation_key="xfan",
get_value_fn=lambda d: d.xfan, get_value_fn=lambda d: d.xfan,
set_value_fn=_set_xfan, set_value_fn=_set_xfan,
), ),
GreeSwitchEntityDescription( GreeSwitchEntityDescription(
icon="mdi:pine-tree", icon="mdi:pine-tree",
name="Health mode", key="Health mode",
key="anion", translation_key="health_mode",
get_value_fn=lambda d: d.anion, get_value_fn=lambda d: d.anion,
set_value_fn=_set_anion, set_value_fn=_set_anion,
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
@ -134,7 +130,7 @@ class GreeSwitch(GreeEntity, SwitchEntity):
"""Initialize the Gree device.""" """Initialize the Gree device."""
self.entity_description = description self.entity_description = description
super().__init__(coordinator, description.name) super().__init__(coordinator, description.key)
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:

View file

@ -98,7 +98,7 @@
'domain': 'climate', 'domain': 'climate',
'entity_category': None, 'entity_category': None,
'entity_id': 'climate.fake_device_1', 'entity_id': 'climate.fake_device_1',
'has_entity_name': False, 'has_entity_name': True,
'hidden_by': None, 'hidden_by': None,
'icon': None, 'icon': None,
'id': <ANY>, 'id': <ANY>,
@ -107,7 +107,7 @@
}), }),
'original_device_class': None, 'original_device_class': None,
'original_icon': None, 'original_icon': None,
'original_name': 'fake-device-1', 'original_name': None,
'platform': 'gree', 'platform': 'gree',
'previous_unique_id': None, 'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 57>, 'supported_features': <ClimateEntityFeature: 57>,

View file

@ -4,7 +4,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'device_class': 'switch', 'device_class': 'switch',
'friendly_name': 'fake-device-1 Panel Light', 'friendly_name': 'fake-device-1 Panel light',
'icon': 'mdi:lightbulb', 'icon': 'mdi:lightbulb',
}), }),
'context': <ANY>, 'context': <ANY>,
@ -27,7 +27,7 @@
StateSnapshot({ StateSnapshot({
'attributes': ReadOnlyDict({ 'attributes': ReadOnlyDict({
'device_class': 'switch', 'device_class': 'switch',
'friendly_name': 'fake-device-1 Fresh Air', 'friendly_name': 'fake-device-1 Fresh air',
}), }),
'context': <ANY>, 'context': <ANY>,
'entity_id': 'switch.fake_device_1_fresh_air', 'entity_id': 'switch.fake_device_1_fresh_air',
@ -74,7 +74,7 @@
'domain': 'switch', 'domain': 'switch',
'entity_category': None, 'entity_category': None,
'entity_id': 'switch.fake_device_1_panel_light', 'entity_id': 'switch.fake_device_1_panel_light',
'has_entity_name': False, 'has_entity_name': True,
'hidden_by': None, 'hidden_by': None,
'icon': None, 'icon': None,
'id': <ANY>, 'id': <ANY>,
@ -83,11 +83,11 @@
}), }),
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>, 'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
'original_icon': 'mdi:lightbulb', 'original_icon': 'mdi:lightbulb',
'original_name': 'fake-device-1 Panel Light', 'original_name': 'Panel light',
'platform': 'gree', 'platform': 'gree',
'previous_unique_id': None, 'previous_unique_id': None,
'supported_features': 0, 'supported_features': 0,
'translation_key': None, 'translation_key': 'light',
'unique_id': 'aabbcc112233_Panel Light', 'unique_id': 'aabbcc112233_Panel Light',
'unit_of_measurement': None, 'unit_of_measurement': None,
}), }),
@ -103,7 +103,7 @@
'domain': 'switch', 'domain': 'switch',
'entity_category': None, 'entity_category': None,
'entity_id': 'switch.fake_device_1_quiet', 'entity_id': 'switch.fake_device_1_quiet',
'has_entity_name': False, 'has_entity_name': True,
'hidden_by': None, 'hidden_by': None,
'icon': None, 'icon': None,
'id': <ANY>, 'id': <ANY>,
@ -112,11 +112,11 @@
}), }),
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>, 'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
'original_icon': None, 'original_icon': None,
'original_name': 'fake-device-1 Quiet', 'original_name': 'Quiet',
'platform': 'gree', 'platform': 'gree',
'previous_unique_id': None, 'previous_unique_id': None,
'supported_features': 0, 'supported_features': 0,
'translation_key': None, 'translation_key': 'quiet',
'unique_id': 'aabbcc112233_Quiet', 'unique_id': 'aabbcc112233_Quiet',
'unit_of_measurement': None, 'unit_of_measurement': None,
}), }),
@ -132,7 +132,7 @@
'domain': 'switch', 'domain': 'switch',
'entity_category': None, 'entity_category': None,
'entity_id': 'switch.fake_device_1_fresh_air', 'entity_id': 'switch.fake_device_1_fresh_air',
'has_entity_name': False, 'has_entity_name': True,
'hidden_by': None, 'hidden_by': None,
'icon': None, 'icon': None,
'id': <ANY>, 'id': <ANY>,
@ -141,11 +141,11 @@
}), }),
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>, 'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
'original_icon': None, 'original_icon': None,
'original_name': 'fake-device-1 Fresh Air', 'original_name': 'Fresh air',
'platform': 'gree', 'platform': 'gree',
'previous_unique_id': None, 'previous_unique_id': None,
'supported_features': 0, 'supported_features': 0,
'translation_key': None, 'translation_key': 'fresh_air',
'unique_id': 'aabbcc112233_Fresh Air', 'unique_id': 'aabbcc112233_Fresh Air',
'unit_of_measurement': None, 'unit_of_measurement': None,
}), }),
@ -161,7 +161,7 @@
'domain': 'switch', 'domain': 'switch',
'entity_category': None, 'entity_category': None,
'entity_id': 'switch.fake_device_1_xfan', 'entity_id': 'switch.fake_device_1_xfan',
'has_entity_name': False, 'has_entity_name': True,
'hidden_by': None, 'hidden_by': None,
'icon': None, 'icon': None,
'id': <ANY>, 'id': <ANY>,
@ -170,11 +170,11 @@
}), }),
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>, 'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
'original_icon': None, 'original_icon': None,
'original_name': 'fake-device-1 XFan', 'original_name': 'XFan',
'platform': 'gree', 'platform': 'gree',
'previous_unique_id': None, 'previous_unique_id': None,
'supported_features': 0, 'supported_features': 0,
'translation_key': None, 'translation_key': 'xfan',
'unique_id': 'aabbcc112233_XFan', 'unique_id': 'aabbcc112233_XFan',
'unit_of_measurement': None, 'unit_of_measurement': None,
}), }),
@ -190,7 +190,7 @@
'domain': 'switch', 'domain': 'switch',
'entity_category': None, 'entity_category': None,
'entity_id': 'switch.fake_device_1_health_mode', 'entity_id': 'switch.fake_device_1_health_mode',
'has_entity_name': False, 'has_entity_name': True,
'hidden_by': None, 'hidden_by': None,
'icon': None, 'icon': None,
'id': <ANY>, 'id': <ANY>,
@ -199,11 +199,11 @@
}), }),
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>, 'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
'original_icon': 'mdi:pine-tree', 'original_icon': 'mdi:pine-tree',
'original_name': 'fake-device-1 Health mode', 'original_name': 'Health mode',
'platform': 'gree', 'platform': 'gree',
'previous_unique_id': None, 'previous_unique_id': None,
'supported_features': 0, 'supported_features': 0,
'translation_key': None, 'translation_key': 'health_mode',
'unique_id': 'aabbcc112233_Health mode', 'unique_id': 'aabbcc112233_Health mode',
'unit_of_measurement': None, 'unit_of_measurement': None,
}), }),