diff --git a/homeassistant/components/homekit_controller/__init__.py b/homeassistant/components/homekit_controller/__init__.py index 6909b226556..e5853c8ba66 100644 --- a/homeassistant/components/homekit_controller/__init__.py +++ b/homeassistant/components/homekit_controller/__init__.py @@ -27,7 +27,7 @@ from .config_flow import normalize_hkid from .connection import HKDevice, valid_serial_number from .const import ENTITY_MAP, KNOWN_DEVICES, TRIGGERS from .storage import EntityMapStorage -from .utils import async_get_controller +from .utils import async_get_controller, folded_name _LOGGER = logging.getLogger(__name__) @@ -42,6 +42,7 @@ class HomeKitEntity(Entity): self._accessory = accessory self._aid = devinfo["aid"] self._iid = devinfo["iid"] + self._char_name: str | None = None self._features = 0 self.setup() @@ -127,6 +128,9 @@ class HomeKitEntity(Entity): if CharacteristicPermissions.events in char.perms: self.watchable_characteristics.append((self._aid, char.iid)) + if self._char_name is None: + self._char_name = char.service.value(CharacteristicsTypes.NAME) + @property def unique_id(self) -> str: """Return the ID of this device.""" @@ -137,10 +141,27 @@ class HomeKitEntity(Entity): # Some accessories do not have a serial number return f"homekit-{self._accessory.unique_id}-{self._aid}-{self._iid}" + @property + def default_name(self) -> str | None: + """Return the default name of the device.""" + return None + @property def name(self) -> str | None: """Return the name of the device if any.""" - return self.accessory.name + accessory_name = self.accessory.name + # If the service has a name char, use that, if not + # fallback to the default name provided by the subclass + device_name = self._char_name or self.default_name + folded_device_name = folded_name(device_name or "") + folded_accessory_name = folded_name(accessory_name) + if ( + device_name + and folded_accessory_name not in folded_device_name + and folded_device_name not in folded_accessory_name + ): + return f"{accessory_name} {device_name}" + return accessory_name @property def available(self) -> bool: diff --git a/homeassistant/components/homekit_controller/button.py b/homeassistant/components/homekit_controller/button.py index 7d2c737b509..e9c85dbe876 100644 --- a/homeassistant/components/homekit_controller/button.py +++ b/homeassistant/components/homekit_controller/button.py @@ -106,7 +106,7 @@ class HomeKitButton(CharacteristicEntity, ButtonEntity): @property def name(self) -> str: """Return the name of the device if any.""" - if name := super().name: + if name := self.accessory.name: return f"{name} {self.entity_description.name}" return f"{self.entity_description.name}" diff --git a/homeassistant/components/homekit_controller/number.py b/homeassistant/components/homekit_controller/number.py index 4e0f5cfa077..07d22c27314 100644 --- a/homeassistant/components/homekit_controller/number.py +++ b/homeassistant/components/homekit_controller/number.py @@ -93,11 +93,11 @@ class HomeKitNumber(CharacteristicEntity, NumberEntity): super().__init__(conn, info, char) @property - def name(self) -> str | None: + def name(self) -> str: """Return the name of the device if any.""" - if prefix := super().name: - return f"{prefix} {self.entity_description.name}" - return self.entity_description.name + if name := self.accessory.name: + return f"{name} {self.entity_description.name}" + return f"{self.entity_description.name}" def get_characteristic_types(self) -> list[str]: """Define the homekit characteristics the entity is tracking.""" diff --git a/homeassistant/components/homekit_controller/sensor.py b/homeassistant/components/homekit_controller/sensor.py index b7d7b8005ed..a3a722fea67 100644 --- a/homeassistant/components/homekit_controller/sensor.py +++ b/homeassistant/components/homekit_controller/sensor.py @@ -32,6 +32,7 @@ from homeassistant.helpers.typing import ConfigType from . import KNOWN_DEVICES, CharacteristicEntity, HomeKitEntity from .connection import HKDevice +from .utils import folded_name CO2_ICON = "mdi:molecule-co2" @@ -199,7 +200,24 @@ SIMPLE_SENSOR: dict[str, HomeKitSensorEntityDescription] = { } -class HomeKitHumiditySensor(HomeKitEntity, SensorEntity): +class HomeKitSensor(HomeKitEntity): + """Representation of a HomeKit sensor.""" + + @property + def name(self) -> str | None: + """Return the name of the device.""" + full_name = super().name + default_name = self.default_name + if ( + default_name + and full_name + and folded_name(default_name) not in folded_name(full_name) + ): + return f"{full_name} {default_name}" + return full_name + + +class HomeKitHumiditySensor(HomeKitSensor, SensorEntity): """Representation of a Homekit humidity sensor.""" _attr_device_class = SensorDeviceClass.HUMIDITY @@ -210,9 +228,9 @@ class HomeKitHumiditySensor(HomeKitEntity, SensorEntity): return [CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT] @property - def name(self) -> str: - """Return the name of the device.""" - return f"{super().name} Humidity" + def default_name(self) -> str: + """Return the default name of the device.""" + return "Humidity" @property def native_value(self) -> float: @@ -220,7 +238,7 @@ class HomeKitHumiditySensor(HomeKitEntity, SensorEntity): return self.service.value(CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT) -class HomeKitTemperatureSensor(HomeKitEntity, SensorEntity): +class HomeKitTemperatureSensor(HomeKitSensor, SensorEntity): """Representation of a Homekit temperature sensor.""" _attr_device_class = SensorDeviceClass.TEMPERATURE @@ -231,9 +249,9 @@ class HomeKitTemperatureSensor(HomeKitEntity, SensorEntity): return [CharacteristicsTypes.TEMPERATURE_CURRENT] @property - def name(self) -> str: - """Return the name of the device.""" - return f"{super().name} Temperature" + def default_name(self) -> str: + """Return the default name of the device.""" + return "Temperature" @property def native_value(self) -> float: @@ -241,7 +259,7 @@ class HomeKitTemperatureSensor(HomeKitEntity, SensorEntity): return self.service.value(CharacteristicsTypes.TEMPERATURE_CURRENT) -class HomeKitLightSensor(HomeKitEntity, SensorEntity): +class HomeKitLightSensor(HomeKitSensor, SensorEntity): """Representation of a Homekit light level sensor.""" _attr_device_class = SensorDeviceClass.ILLUMINANCE @@ -252,9 +270,9 @@ class HomeKitLightSensor(HomeKitEntity, SensorEntity): return [CharacteristicsTypes.LIGHT_LEVEL_CURRENT] @property - def name(self) -> str: - """Return the name of the device.""" - return f"{super().name} Light Level" + def default_name(self) -> str: + """Return the default name of the device.""" + return "Light Level" @property def native_value(self) -> int: @@ -273,9 +291,9 @@ class HomeKitCarbonDioxideSensor(HomeKitEntity, SensorEntity): return [CharacteristicsTypes.CARBON_DIOXIDE_LEVEL] @property - def name(self) -> str: - """Return the name of the device.""" - return f"{super().name} CO2" + def default_name(self) -> str: + """Return the default name of the device.""" + return "CO2" @property def native_value(self) -> int: @@ -283,7 +301,7 @@ class HomeKitCarbonDioxideSensor(HomeKitEntity, SensorEntity): return self.service.value(CharacteristicsTypes.CARBON_DIOXIDE_LEVEL) -class HomeKitBatterySensor(HomeKitEntity, SensorEntity): +class HomeKitBatterySensor(HomeKitSensor, SensorEntity): """Representation of a Homekit battery sensor.""" _attr_device_class = SensorDeviceClass.BATTERY @@ -298,9 +316,9 @@ class HomeKitBatterySensor(HomeKitEntity, SensorEntity): ] @property - def name(self) -> str: - """Return the name of the device.""" - return f"{super().name} Battery" + def default_name(self) -> str: + """Return the default name of the device.""" + return "Battery" @property def icon(self) -> str: @@ -374,7 +392,9 @@ class SimpleSensor(CharacteristicEntity, SensorEntity): @property def name(self) -> str: """Return the name of the device if any.""" - return f"{super().name} {self.entity_description.name}" + if name := self.accessory.name: + return f"{name} {self.entity_description.name}" + return f"{self.entity_description.name}" @property def native_value(self) -> str | int | float: diff --git a/homeassistant/components/homekit_controller/switch.py b/homeassistant/components/homekit_controller/switch.py index 07d0e21e59f..53b3958ecf6 100644 --- a/homeassistant/components/homekit_controller/switch.py +++ b/homeassistant/components/homekit_controller/switch.py @@ -147,11 +147,11 @@ class DeclarativeCharacteristicSwitch(CharacteristicEntity, SwitchEntity): super().__init__(conn, info, char) @property - def name(self) -> str | None: + def name(self) -> str: """Return the name of the device if any.""" - if prefix := super().name: - return f"{prefix} {self.entity_description.name}" - return self.entity_description.name + if name := self.accessory.name: + return f"{name} {self.entity_description.name}" + return f"{self.entity_description.name}" def get_characteristic_types(self) -> list[str]: """Define the homekit characteristics the entity cares about.""" diff --git a/homeassistant/components/homekit_controller/utils.py b/homeassistant/components/homekit_controller/utils.py index 6831c3cee4a..892040d535f 100644 --- a/homeassistant/components/homekit_controller/utils.py +++ b/homeassistant/components/homekit_controller/utils.py @@ -10,6 +10,11 @@ from homeassistant.core import Event, HomeAssistant from .const import CONTROLLER +def folded_name(name: str) -> str: + """Return a name that is used for matching a similar string.""" + return name.casefold().replace(" ", "") + + async def async_get_controller(hass: HomeAssistant) -> Controller: """Get or create an aiohomekit Controller instance.""" if existing := hass.data.get(CONTROLLER): diff --git a/tests/components/homekit_controller/fixtures/mss425f.json b/tests/components/homekit_controller/fixtures/mss425f.json new file mode 100644 index 00000000000..35766b32d22 --- /dev/null +++ b/tests/components/homekit_controller/fixtures/mss425f.json @@ -0,0 +1,212 @@ +[ + { + "aid": 1, + "services": [ + { + "iid": 1, + "type": "0000003E-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000014-0000-1000-8000-0026BB765291", + "iid": 2, + "perms": ["pw"], + "format": "bool", + "description": "Identify" + }, + { + "type": "00000020-0000-1000-8000-0026BB765291", + "iid": 3, + "perms": ["pr"], + "format": "string", + "value": "Meross", + "description": "Manufacturer", + "maxLen": 64 + }, + { + "type": "00000021-0000-1000-8000-0026BB765291", + "iid": 4, + "perms": ["pr"], + "format": "string", + "value": "MSS425F", + "description": "Model", + "maxLen": 64 + }, + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 5, + "perms": ["pr"], + "format": "string", + "value": "MSS425F-15cc", + "description": "Name", + "maxLen": 64 + }, + { + "type": "00000030-0000-1000-8000-0026BB765291", + "iid": 6, + "perms": ["pr"], + "format": "string", + "value": "HH41234", + "description": "Serial Number", + "maxLen": 64 + }, + { + "type": "00000052-0000-1000-8000-0026BB765291", + "iid": 7, + "perms": ["pr"], + "format": "string", + "value": "4.2.3", + "description": "Firmware Revision", + "maxLen": 64 + }, + { + "type": "00000053-0000-1000-8000-0026BB765291", + "iid": 8, + "perms": ["pr"], + "format": "string", + "value": "4.0.0", + "description": "Hardware Revision", + "maxLen": 64 + }, + { + "type": "34AB8811-AC7F-4340-BAC3-FD6A85F9943B", + "iid": 9, + "perms": ["pr"], + "format": "string", + "value": "2.0.1;16A75", + "maxLen": 64 + } + ] + }, + { + "iid": 10, + "type": "000000A2-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000037-0000-1000-8000-0026BB765291", + "iid": 11, + "perms": ["pr"], + "format": "string", + "value": "1.1.0", + "description": "Version", + "maxLen": 64 + } + ] + }, + { + "iid": 12, + "type": "00000047-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 13, + "perms": ["pr"], + "format": "string", + "value": "Outlet-1", + "description": "Name", + "maxLen": 64 + }, + { + "type": "00000025-0000-1000-8000-0026BB765291", + "iid": 14, + "perms": ["pr", "pw", "ev"], + "format": "bool", + "value": true, + "description": "On" + } + ] + }, + { + "iid": 15, + "type": "00000047-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 16, + "perms": ["pr"], + "format": "string", + "value": "Outlet-2", + "description": "Name", + "maxLen": 64 + }, + { + "type": "00000025-0000-1000-8000-0026BB765291", + "iid": 17, + "perms": ["pr", "pw", "ev"], + "format": "bool", + "value": true, + "description": "On" + } + ] + }, + { + "iid": 18, + "type": "00000047-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 19, + "perms": ["pr"], + "format": "string", + "value": "Outlet-3", + "description": "Name", + "maxLen": 64 + }, + { + "type": "00000025-0000-1000-8000-0026BB765291", + "iid": 20, + "perms": ["pr", "pw", "ev"], + "format": "bool", + "value": true, + "description": "On" + } + ] + }, + { + "iid": 21, + "type": "00000047-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 22, + "perms": ["pr"], + "format": "string", + "value": "Outlet-4", + "description": "Name", + "maxLen": 64 + }, + { + "type": "00000025-0000-1000-8000-0026BB765291", + "iid": 23, + "perms": ["pr", "pw", "ev"], + "format": "bool", + "value": true, + "description": "On" + } + ] + }, + { + "iid": 24, + "type": "00000047-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 25, + "perms": ["pr"], + "format": "string", + "value": "USB", + "description": "Name", + "maxLen": 64 + }, + { + "type": "00000025-0000-1000-8000-0026BB765291", + "iid": 26, + "perms": ["pr", "pw", "ev"], + "format": "bool", + "value": true, + "description": "On" + } + ] + } + ] + } +] diff --git a/tests/components/homekit_controller/fixtures/mss565.json b/tests/components/homekit_controller/fixtures/mss565.json new file mode 100644 index 00000000000..9ecb735dce3 --- /dev/null +++ b/tests/components/homekit_controller/fixtures/mss565.json @@ -0,0 +1,132 @@ +[ + { + "aid": 1, + "services": [ + { + "iid": 1, + "type": "0000003E-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000014-0000-1000-8000-0026BB765291", + "iid": 2, + "perms": ["pw"], + "format": "bool", + "description": "Identify" + }, + { + "type": "00000020-0000-1000-8000-0026BB765291", + "iid": 3, + "perms": ["pr"], + "format": "string", + "value": "Meross", + "description": "Manufacturer", + "maxLen": 64 + }, + { + "type": "00000021-0000-1000-8000-0026BB765291", + "iid": 4, + "perms": ["pr"], + "format": "string", + "value": "MSS565", + "description": "Model", + "maxLen": 64 + }, + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 5, + "perms": ["pr"], + "format": "string", + "value": "MSS565-28da", + "description": "Name", + "maxLen": 64 + }, + { + "type": "00000030-0000-1000-8000-0026BB765291", + "iid": 6, + "perms": ["pr"], + "format": "string", + "value": "BB1121", + "description": "Serial Number", + "maxLen": 64 + }, + { + "type": "00000052-0000-1000-8000-0026BB765291", + "iid": 7, + "perms": ["pr"], + "format": "string", + "value": "4.1.9", + "description": "Firmware Revision", + "maxLen": 64 + }, + { + "type": "00000053-0000-1000-8000-0026BB765291", + "iid": 8, + "perms": ["pr"], + "format": "string", + "value": "4.0.0", + "description": "Hardware Revision", + "maxLen": 64 + }, + { + "type": "34AB8811-AC7F-4340-BAC3-FD6A85F9943B", + "iid": 9, + "perms": ["pr"], + "format": "string", + "value": "2.0.1;16A75", + "maxLen": 64 + } + ] + }, + { + "iid": 10, + "type": "000000A2-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000037-0000-1000-8000-0026BB765291", + "iid": 11, + "perms": ["pr"], + "format": "string", + "value": "1.1.0", + "description": "Version", + "maxLen": 64 + } + ] + }, + { + "iid": 12, + "type": "00000043-0000-1000-8000-0026BB765291", + "characteristics": [ + { + "type": "00000025-0000-1000-8000-0026BB765291", + "iid": 13, + "perms": ["pr", "pw", "ev"], + "format": "bool", + "value": true, + "description": "On" + }, + { + "type": "00000008-0000-1000-8000-0026BB765291", + "iid": 14, + "perms": ["pr", "pw", "ev"], + "format": "int", + "value": 67, + "description": "Brightness", + "unit": "percentage", + "minValue": 0, + "maxValue": 100, + "minStep": 1 + }, + { + "type": "00000023-0000-1000-8000-0026BB765291", + "iid": 15, + "perms": ["pr"], + "format": "string", + "value": "Dimmer Switch", + "description": "Name", + "maxLen": 64 + } + ] + } + ] + } +] diff --git a/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py b/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py index b2428cdc42b..6950f4cb61e 100644 --- a/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py +++ b/tests/components/homekit_controller/specific_devices/test_aqara_gateway.py @@ -39,8 +39,8 @@ async def test_aqara_gateway_setup(hass): devices=[], entities=[ EntityTestInfo( - "alarm_control_panel.aqara_hub_1563", - friendly_name="Aqara Hub-1563", + "alarm_control_panel.aqara_hub_1563_security_system", + friendly_name="Aqara Hub-1563 Security System", unique_id="homekit-0000000123456789-66304", supported_features=SUPPORT_ALARM_ARM_NIGHT | SUPPORT_ALARM_ARM_HOME @@ -48,8 +48,8 @@ async def test_aqara_gateway_setup(hass): state="disarmed", ), EntityTestInfo( - "light.aqara_hub_1563", - friendly_name="Aqara Hub-1563", + "light.aqara_hub_1563_lightbulb_1563", + friendly_name="Aqara Hub-1563 Lightbulb-1563", unique_id="homekit-0000000123456789-65792", supported_features=0, capabilities={"supported_color_modes": ["hs"]}, @@ -98,8 +98,8 @@ async def test_aqara_gateway_e1_setup(hass): devices=[], entities=[ EntityTestInfo( - "alarm_control_panel.aqara_hub_e1_00a0", - friendly_name="Aqara-Hub-E1-00A0", + "alarm_control_panel.aqara_hub_e1_00a0_security_system", + friendly_name="Aqara-Hub-E1-00A0 Security System", unique_id="homekit-00aa00000a0-16", supported_features=SUPPORT_ALARM_ARM_NIGHT | SUPPORT_ALARM_ARM_HOME diff --git a/tests/components/homekit_controller/specific_devices/test_aqara_switch.py b/tests/components/homekit_controller/specific_devices/test_aqara_switch.py index e6dce42a1f7..16bef749429 100644 --- a/tests/components/homekit_controller/specific_devices/test_aqara_switch.py +++ b/tests/components/homekit_controller/specific_devices/test_aqara_switch.py @@ -38,8 +38,8 @@ async def test_aqara_switch_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="sensor.programmable_switch_battery", - friendly_name="Programmable Switch Battery", + entity_id="sensor.programmable_switch_battery_sensor", + friendly_name="Programmable Switch Battery Sensor", unique_id="homekit-111a1111a1a111-5", unit_of_measurement=PERCENTAGE, state="100", diff --git a/tests/components/homekit_controller/specific_devices/test_arlo_baby.py b/tests/components/homekit_controller/specific_devices/test_arlo_baby.py index 9afe152c7b3..2cb312fc7f5 100644 --- a/tests/components/homekit_controller/specific_devices/test_arlo_baby.py +++ b/tests/components/homekit_controller/specific_devices/test_arlo_baby.py @@ -37,9 +37,9 @@ async def test_arlo_baby_setup(hass): state="idle", ), EntityTestInfo( - entity_id="binary_sensor.arlobabya0", + entity_id="binary_sensor.arlobabya0_motion", unique_id="homekit-00A0000000000-500", - friendly_name="ArloBabyA0", + friendly_name="ArloBabyA0 Motion", state="off", ), EntityTestInfo( @@ -71,9 +71,9 @@ async def test_arlo_baby_setup(hass): state="1", ), EntityTestInfo( - entity_id="light.arlobabya0", + entity_id="light.arlobabya0_nightlight", unique_id="homekit-00A0000000000-1100", - friendly_name="ArloBabyA0", + friendly_name="ArloBabyA0 Nightlight", supported_features=0, capabilities={"supported_color_modes": ["hs"]}, state="off", diff --git a/tests/components/homekit_controller/specific_devices/test_connectsense.py b/tests/components/homekit_controller/specific_devices/test_connectsense.py index 2cbdf924319..fbb95fc3d89 100644 --- a/tests/components/homekit_controller/specific_devices/test_connectsense.py +++ b/tests/components/homekit_controller/specific_devices/test_connectsense.py @@ -59,8 +59,8 @@ async def test_connectsense_setup(hass): state="379.69299", ), EntityTestInfo( - entity_id="switch.inwall_outlet_0394de", - friendly_name="InWall Outlet-0394DE", + entity_id="switch.inwall_outlet_0394de_outlet_a", + friendly_name="InWall Outlet-0394DE Outlet A", unique_id="homekit-1020301376-13", state="on", ), @@ -89,8 +89,8 @@ async def test_connectsense_setup(hass): state="175.85001", ), EntityTestInfo( - entity_id="switch.inwall_outlet_0394de_2", - friendly_name="InWall Outlet-0394DE", + entity_id="switch.inwall_outlet_0394de_outlet_b", + friendly_name="InWall Outlet-0394DE Outlet B", unique_id="homekit-1020301376-25", state="on", ), diff --git a/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py b/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py index 88d483bd5bc..74525af1daf 100644 --- a/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py +++ b/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py @@ -43,8 +43,8 @@ async def test_koogeek_ls1_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="light.koogeek_ls1_20833f", - friendly_name="Koogeek-LS1-20833F", + entity_id="light.koogeek_ls1_20833f_light_strip", + friendly_name="Koogeek-LS1-20833F Light Strip", unique_id="homekit-AAAA011111111111-7", supported_features=0, capabilities={"supported_color_modes": ["hs"]}, @@ -75,7 +75,11 @@ async def test_recover_from_failure(hass, utcnow, failure_cls): pairing.testing.events_enabled = False helper = Helper( - hass, "light.koogeek_ls1_20833f", pairing, accessories[0], config_entry + hass, + "light.koogeek_ls1_20833f_light_strip", + pairing, + accessories[0], + config_entry, ) # Set light state on fake device to off diff --git a/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py b/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py index f93adc732ba..bf8c86b7a7d 100644 --- a/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py +++ b/tests/components/homekit_controller/specific_devices/test_koogeek_p1eu.py @@ -31,8 +31,8 @@ async def test_koogeek_p1eu_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="switch.koogeek_p1_a00aa0", - friendly_name="Koogeek-P1-A00AA0", + entity_id="switch.koogeek_p1_a00aa0_outlet", + friendly_name="Koogeek-P1-A00AA0 outlet", unique_id="homekit-EUCP03190xxxxx48-7", state="off", ), diff --git a/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py b/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py index ed940cb6376..8307dc72f22 100644 --- a/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py +++ b/tests/components/homekit_controller/specific_devices/test_koogeek_sw2.py @@ -37,11 +37,17 @@ async def test_koogeek_sw2_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="switch.koogeek_sw2_187a91", - friendly_name="Koogeek-SW2-187A91", + entity_id="switch.koogeek_sw2_187a91_switch_1", + friendly_name="Koogeek-SW2-187A91 Switch 1", unique_id="homekit-CNNT061751001372-8", state="off", ), + EntityTestInfo( + entity_id="switch.koogeek_sw2_187a91_switch_2", + friendly_name="Koogeek-SW2-187A91 Switch 2", + unique_id="homekit-CNNT061751001372-11", + state="off", + ), EntityTestInfo( entity_id="sensor.koogeek_sw2_187a91_power", friendly_name="Koogeek-SW2-187A91 Power", diff --git a/tests/components/homekit_controller/specific_devices/test_mss425f.py b/tests/components/homekit_controller/specific_devices/test_mss425f.py new file mode 100644 index 00000000000..3fe0ee739e6 --- /dev/null +++ b/tests/components/homekit_controller/specific_devices/test_mss425f.py @@ -0,0 +1,73 @@ +"""Tests for the Meross MSS425f power strip.""" + + +from homeassistant.const import STATE_ON, STATE_UNKNOWN +from homeassistant.helpers.entity import EntityCategory + +from tests.components.homekit_controller.common import ( + HUB_TEST_ACCESSORY_ID, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, + setup_accessories_from_file, + setup_test_accessories, +) + + +async def test_meross_mss425f_setup(hass): + """Test that a MSS425f can be correctly setup in HA.""" + accessories = await setup_accessories_from_file(hass, "mss425f.json") + await setup_test_accessories(hass, accessories) + + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id=HUB_TEST_ACCESSORY_ID, + name="MSS425F-15cc", + model="MSS425F", + manufacturer="Meross", + sw_version="4.2.3", + hw_version="4.0.0", + serial_number="HH41234", + devices=[], + entities=[ + EntityTestInfo( + entity_id="button.mss425f_15cc_identify", + friendly_name="MSS425F-15cc Identify", + unique_id="homekit-HH41234-aid:1-sid:1-cid:2", + entity_category=EntityCategory.DIAGNOSTIC, + state=STATE_UNKNOWN, + ), + EntityTestInfo( + entity_id="switch.mss425f_15cc_outlet_1", + friendly_name="MSS425F-15cc Outlet-1", + unique_id="homekit-HH41234-12", + state=STATE_ON, + ), + EntityTestInfo( + entity_id="switch.mss425f_15cc_outlet_2", + friendly_name="MSS425F-15cc Outlet-2", + unique_id="homekit-HH41234-15", + state=STATE_ON, + ), + EntityTestInfo( + entity_id="switch.mss425f_15cc_outlet_3", + friendly_name="MSS425F-15cc Outlet-3", + unique_id="homekit-HH41234-18", + state=STATE_ON, + ), + EntityTestInfo( + entity_id="switch.mss425f_15cc_outlet_4", + friendly_name="MSS425F-15cc Outlet-4", + unique_id="homekit-HH41234-21", + state=STATE_ON, + ), + EntityTestInfo( + entity_id="switch.mss425f_15cc_usb", + friendly_name="MSS425F-15cc USB", + unique_id="homekit-HH41234-24", + state=STATE_ON, + ), + ], + ), + ) diff --git a/tests/components/homekit_controller/specific_devices/test_mss565.py b/tests/components/homekit_controller/specific_devices/test_mss565.py new file mode 100644 index 00000000000..0045a5ec507 --- /dev/null +++ b/tests/components/homekit_controller/specific_devices/test_mss565.py @@ -0,0 +1,42 @@ +"""Tests for the Meross MSS565 wall switch.""" + + +from homeassistant.const import STATE_ON + +from tests.components.homekit_controller.common import ( + HUB_TEST_ACCESSORY_ID, + DeviceTestInfo, + EntityTestInfo, + assert_devices_and_entities_created, + setup_accessories_from_file, + setup_test_accessories, +) + + +async def test_meross_mss565_setup(hass): + """Test that a MSS565 can be correctly setup in HA.""" + accessories = await setup_accessories_from_file(hass, "mss565.json") + await setup_test_accessories(hass, accessories) + + await assert_devices_and_entities_created( + hass, + DeviceTestInfo( + unique_id=HUB_TEST_ACCESSORY_ID, + name="MSS565-28da", + model="MSS565", + manufacturer="Meross", + sw_version="4.1.9", + hw_version="4.0.0", + serial_number="BB1121", + devices=[], + entities=[ + EntityTestInfo( + entity_id="light.mss565_28da_dimmer_switch", + friendly_name="MSS565-28da Dimmer Switch", + unique_id="homekit-BB1121-12", + capabilities={"supported_color_modes": ["brightness"]}, + state=STATE_ON, + ), + ], + ), + ) diff --git a/tests/components/homekit_controller/specific_devices/test_mysa_living.py b/tests/components/homekit_controller/specific_devices/test_mysa_living.py index 5829bd4e165..1a3bcdb2271 100644 --- a/tests/components/homekit_controller/specific_devices/test_mysa_living.py +++ b/tests/components/homekit_controller/specific_devices/test_mysa_living.py @@ -32,8 +32,8 @@ async def test_mysa_living_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="climate.mysa_85dda9", - friendly_name="Mysa-85dda9", + entity_id="climate.mysa_85dda9_thermostat", + friendly_name="Mysa-85dda9 Thermostat", unique_id="homekit-AAAAAAA000-20", supported_features=SUPPORT_TARGET_TEMPERATURE, capabilities={ @@ -60,8 +60,8 @@ async def test_mysa_living_setup(hass): state="24.1", ), EntityTestInfo( - entity_id="light.mysa_85dda9", - friendly_name="Mysa-85dda9", + entity_id="light.mysa_85dda9_display", + friendly_name="Mysa-85dda9 Display", unique_id="homekit-AAAAAAA000-40", supported_features=0, capabilities={"supported_color_modes": ["brightness"]}, diff --git a/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py b/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py index 51ebbfdc345..eb9c36d0b79 100644 --- a/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py +++ b/tests/components/homekit_controller/specific_devices/test_ryse_smart_bridge.py @@ -45,15 +45,15 @@ async def test_ryse_smart_bridge_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="cover.master_bath_south", - friendly_name="Master Bath South", + entity_id="cover.master_bath_south_ryse_shade", + friendly_name="Master Bath South RYSE Shade", unique_id="homekit-00:00:00:00:00:00-2-48", supported_features=RYSE_SUPPORTED_FEATURES, state="closed", ), EntityTestInfo( - entity_id="sensor.master_bath_south_battery", - friendly_name="Master Bath South Battery", + entity_id="sensor.master_bath_south_ryse_shade_battery", + friendly_name="Master Bath South RYSE Shade Battery", unique_id="homekit-00:00:00:00:00:00-2-64", unit_of_measurement=PERCENTAGE, state="100", @@ -71,15 +71,15 @@ async def test_ryse_smart_bridge_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="cover.ryse_smartshade", - friendly_name="RYSE SmartShade", + entity_id="cover.ryse_smartshade_ryse_shade", + friendly_name="RYSE SmartShade RYSE Shade", unique_id="homekit-00:00:00:00:00:00-3-48", supported_features=RYSE_SUPPORTED_FEATURES, state="open", ), EntityTestInfo( - entity_id="sensor.ryse_smartshade_battery", - friendly_name="RYSE SmartShade Battery", + entity_id="sensor.ryse_smartshade_ryse_shade_battery", + friendly_name="RYSE SmartShade RYSE Shade Battery", unique_id="homekit-00:00:00:00:00:00-3-64", unit_of_measurement=PERCENTAGE, state="100", @@ -120,15 +120,15 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="cover.lr_left", - friendly_name="LR Left", + entity_id="cover.lr_left_ryse_shade", + friendly_name="LR Left RYSE Shade", unique_id="homekit-00:00:00:00:00:00-2-48", supported_features=RYSE_SUPPORTED_FEATURES, state="closed", ), EntityTestInfo( - entity_id="sensor.lr_left_battery", - friendly_name="LR Left Battery", + entity_id="sensor.lr_left_ryse_shade_battery", + friendly_name="LR Left RYSE Shade Battery", unique_id="homekit-00:00:00:00:00:00-2-64", unit_of_measurement=PERCENTAGE, state="89", @@ -146,15 +146,15 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="cover.lr_right", - friendly_name="LR Right", + entity_id="cover.lr_right_ryse_shade", + friendly_name="LR Right RYSE Shade", unique_id="homekit-00:00:00:00:00:00-3-48", supported_features=RYSE_SUPPORTED_FEATURES, state="closed", ), EntityTestInfo( - entity_id="sensor.lr_right_battery", - friendly_name="LR Right Battery", + entity_id="sensor.lr_right_ryse_shade_battery", + friendly_name="LR Right RYSE Shade Battery", unique_id="homekit-00:00:00:00:00:00-3-64", unit_of_measurement=PERCENTAGE, state="100", @@ -172,15 +172,15 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="cover.br_left", - friendly_name="BR Left", + entity_id="cover.br_left_ryse_shade", + friendly_name="BR Left RYSE Shade", unique_id="homekit-00:00:00:00:00:00-4-48", supported_features=RYSE_SUPPORTED_FEATURES, state="open", ), EntityTestInfo( - entity_id="sensor.br_left_battery", - friendly_name="BR Left Battery", + entity_id="sensor.br_left_ryse_shade_battery", + friendly_name="BR Left RYSE Shade Battery", unique_id="homekit-00:00:00:00:00:00-4-64", unit_of_measurement=PERCENTAGE, state="100", @@ -198,15 +198,15 @@ async def test_ryse_smart_bridge_four_shades_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="cover.rzss", - friendly_name="RZSS", + entity_id="cover.rzss_ryse_shade", + friendly_name="RZSS RYSE Shade", unique_id="homekit-00:00:00:00:00:00-5-48", supported_features=RYSE_SUPPORTED_FEATURES, state="open", ), EntityTestInfo( - entity_id="sensor.rzss_battery", - friendly_name="RZSS Battery", + entity_id="sensor.rzss_ryse_shade_battery", + friendly_name="RZSS RYSE Shade Battery", unique_id="homekit-00:00:00:00:00:00-5-64", unit_of_measurement=PERCENTAGE, state="0", diff --git a/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py b/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py index d3531e1c65f..f160169a43c 100644 --- a/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py +++ b/tests/components/homekit_controller/specific_devices/test_simpleconnect_fan.py @@ -34,8 +34,8 @@ async def test_simpleconnect_fan_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="fan.simpleconnect_fan_06f674", - friendly_name="SIMPLEconnect Fan-06F674", + entity_id="fan.simpleconnect_fan_06f674_hunter_fan", + friendly_name="SIMPLEconnect Fan-06F674 Hunter Fan", unique_id="homekit-1234567890abcd-8", supported_features=SUPPORT_DIRECTION | SUPPORT_SET_SPEED, capabilities={ diff --git a/tests/components/homekit_controller/specific_devices/test_velux_gateway.py b/tests/components/homekit_controller/specific_devices/test_velux_gateway.py index d8d73709c49..21aa91fc933 100644 --- a/tests/components/homekit_controller/specific_devices/test_velux_gateway.py +++ b/tests/components/homekit_controller/specific_devices/test_velux_gateway.py @@ -52,8 +52,8 @@ async def test_velux_cover_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="cover.velux_window", - friendly_name="VELUX Window", + entity_id="cover.velux_window_roof_window", + friendly_name="VELUX Window Roof Window", unique_id="homekit-1111111a114a111a-8", supported_features=SUPPORT_CLOSE | SUPPORT_SET_POSITION @@ -73,22 +73,22 @@ async def test_velux_cover_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="sensor.velux_sensor_temperature", - friendly_name="VELUX Sensor Temperature", + entity_id="sensor.velux_sensor_temperature_sensor", + friendly_name="VELUX Sensor Temperature sensor", unique_id="homekit-a11b111-8", unit_of_measurement=TEMP_CELSIUS, state="18.9", ), EntityTestInfo( - entity_id="sensor.velux_sensor_humidity", - friendly_name="VELUX Sensor Humidity", + entity_id="sensor.velux_sensor_humidity_sensor", + friendly_name="VELUX Sensor Humidity sensor", unique_id="homekit-a11b111-11", unit_of_measurement=PERCENTAGE, state="58", ), EntityTestInfo( - entity_id="sensor.velux_sensor_co2", - friendly_name="VELUX Sensor CO2", + entity_id="sensor.velux_sensor_carbon_dioxide_sensor", + friendly_name="VELUX Sensor Carbon Dioxide sensor", unique_id="homekit-a11b111-14", unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, state="400", diff --git a/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py b/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py index 6fa9ff63690..f788b016ba2 100644 --- a/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py +++ b/tests/components/homekit_controller/specific_devices/test_vocolinc_flowerbud.py @@ -46,8 +46,8 @@ async def test_vocolinc_flowerbud_setup(hass): state="off", ), EntityTestInfo( - entity_id="light.vocolinc_flowerbud_0d324b", - friendly_name="VOCOlinc-Flowerbud-0d324b", + entity_id="light.vocolinc_flowerbud_0d324b_mood_light", + friendly_name="VOCOlinc-Flowerbud-0d324b Mood Light", unique_id="homekit-AM01121849000327-9", supported_features=0, capabilities={"supported_color_modes": ["hs"]}, diff --git a/tests/components/homekit_controller/specific_devices/test_vocolinc_vp3.py b/tests/components/homekit_controller/specific_devices/test_vocolinc_vp3.py index da69b7fe309..3a3579b8781 100644 --- a/tests/components/homekit_controller/specific_devices/test_vocolinc_vp3.py +++ b/tests/components/homekit_controller/specific_devices/test_vocolinc_vp3.py @@ -31,8 +31,8 @@ async def test_vocolinc_vp3_setup(hass): devices=[], entities=[ EntityTestInfo( - entity_id="switch.vocolinc_vp3_123456", - friendly_name="VOCOlinc-VP3-123456", + entity_id="switch.vocolinc_vp3_123456_outlet", + friendly_name="VOCOlinc-VP3-123456 Outlet", unique_id="homekit-EU0121203xxxxx07-48", state="on", ), diff --git a/tests/components/homekit_controller/test_diagnostics.py b/tests/components/homekit_controller/test_diagnostics.py index 72ef571e214..e770279752e 100644 --- a/tests/components/homekit_controller/test_diagnostics.py +++ b/tests/components/homekit_controller/test_diagnostics.py @@ -234,28 +234,6 @@ async def test_config_entry(hass: HomeAssistant, hass_client: ClientSession, utc "sw_version": "2.2.15", "hw_version": "", "entities": [ - { - "original_name": "Koogeek-LS1-20833F", - "disabled": False, - "disabled_by": None, - "entity_category": None, - "device_class": None, - "original_device_class": None, - "icon": None, - "original_icon": None, - "unit_of_measurement": None, - "state": { - "entity_id": "light.koogeek_ls1_20833f", - "state": "off", - "attributes": { - "supported_color_modes": ["hs"], - "friendly_name": "Koogeek-LS1-20833F", - "supported_features": 0, - }, - "last_changed": "2023-01-01T00:00:00+00:00", - "last_updated": "2023-01-01T00:00:00+00:00", - }, - }, { "device_class": None, "disabled": False, @@ -276,6 +254,28 @@ async def test_config_entry(hass: HomeAssistant, hass_client: ClientSession, utc }, "unit_of_measurement": None, }, + { + "device_class": None, + "disabled": False, + "disabled_by": None, + "entity_category": None, + "icon": None, + "original_device_class": None, + "original_icon": None, + "original_name": "Koogeek-LS1-20833F Light Strip", + "state": { + "attributes": { + "friendly_name": "Koogeek-LS1-20833F Light Strip", + "supported_color_modes": ["hs"], + "supported_features": 0, + }, + "entity_id": "light.koogeek_ls1_20833f_light_strip", + "last_changed": "2023-01-01T00:00:00+00:00", + "last_updated": "2023-01-01T00:00:00+00:00", + "state": "off", + }, + "unit_of_measurement": None, + }, ], } ], @@ -504,28 +504,6 @@ async def test_device(hass: HomeAssistant, hass_client: ClientSession, utcnow): "sw_version": "2.2.15", "hw_version": "", "entities": [ - { - "original_name": "Koogeek-LS1-20833F", - "disabled": False, - "disabled_by": None, - "entity_category": None, - "device_class": None, - "original_device_class": None, - "icon": None, - "original_icon": None, - "unit_of_measurement": None, - "state": { - "entity_id": "light.koogeek_ls1_20833f", - "state": "off", - "attributes": { - "supported_color_modes": ["hs"], - "friendly_name": "Koogeek-LS1-20833F", - "supported_features": 0, - }, - "last_changed": "2023-01-01T00:00:00+00:00", - "last_updated": "2023-01-01T00:00:00+00:00", - }, - }, { "device_class": None, "disabled": False, @@ -536,7 +514,9 @@ async def test_device(hass: HomeAssistant, hass_client: ClientSession, utcnow): "original_icon": None, "original_name": "Koogeek-LS1-20833F Identify", "state": { - "attributes": {"friendly_name": "Koogeek-LS1-20833F Identify"}, + "attributes": { + "friendly_name": "Koogeek-LS1-20833F " "Identify" + }, "entity_id": "button.koogeek_ls1_20833f_identify", "last_changed": "2023-01-01T00:00:00+00:00", "last_updated": "2023-01-01T00:00:00+00:00", @@ -544,6 +524,28 @@ async def test_device(hass: HomeAssistant, hass_client: ClientSession, utcnow): }, "unit_of_measurement": None, }, + { + "device_class": None, + "disabled": False, + "disabled_by": None, + "entity_category": None, + "icon": None, + "original_device_class": None, + "original_icon": None, + "original_name": "Koogeek-LS1-20833F Light Strip", + "state": { + "attributes": { + "friendly_name": "Koogeek-LS1-20833F Light Strip", + "supported_color_modes": ["hs"], + "supported_features": 0, + }, + "entity_id": "light.koogeek_ls1_20833f_light_strip", + "last_changed": "2023-01-01T00:00:00+00:00", + "last_updated": "2023-01-01T00:00:00+00:00", + "state": "off", + }, + "unit_of_measurement": None, + }, ], }, } diff --git a/tests/components/homekit_controller/test_init.py b/tests/components/homekit_controller/test_init.py index 820b89e587d..84a6c8b86bf 100644 --- a/tests/components/homekit_controller/test_init.py +++ b/tests/components/homekit_controller/test_init.py @@ -16,8 +16,8 @@ from .common import Helper, remove_device from tests.components.homekit_controller.common import setup_test_component -ALIVE_DEVICE_NAME = "Light Bulb" -ALIVE_DEEVICE_ENTITY_ID = "light.testdevice" +ALIVE_DEVICE_NAME = "testdevice" +ALIVE_DEVICE_ENTITY_ID = "light.testdevice" def create_motion_sensor_service(accessory): @@ -72,7 +72,7 @@ async def test_device_remove_devices(hass, hass_ws_client): entry_id = config_entry.entry_id registry: EntityRegistry = er.async_get(hass) - entity = registry.entities[ALIVE_DEEVICE_ENTITY_ID] + entity = registry.entities[ALIVE_DEVICE_ENTITY_ID] device_registry = dr.async_get(hass) live_device_entry = device_registry.async_get(entity.device_id) diff --git a/tests/components/homekit_controller/test_light.py b/tests/components/homekit_controller/test_light.py index 39e44c57cc5..83bddf3d26a 100644 --- a/tests/components/homekit_controller/test_light.py +++ b/tests/components/homekit_controller/test_light.py @@ -12,7 +12,7 @@ from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_UNAVAILABLE from tests.components.homekit_controller.common import setup_test_component -LIGHT_BULB_NAME = "Light Bulb" +LIGHT_BULB_NAME = "TestDevice" LIGHT_BULB_ENTITY_ID = "light.testdevice"