mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Have homekit_controller use device registry (#23874)
* Add device registry support * HK doesn't use mac as a connection id
This commit is contained in:
parent
edf34eea94
commit
5b0d1415ad
@ -3,6 +3,7 @@ import logging
|
|||||||
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
from homeassistant.helpers import device_registry as dr
|
||||||
|
|
||||||
# We need an import from .config_flow, without it .config_flow is never loaded.
|
# We need an import from .config_flow, without it .config_flow is never loaded.
|
||||||
from .config_flow import HomekitControllerFlowHandler # noqa: F401
|
from .config_flow import HomekitControllerFlowHandler # noqa: F401
|
||||||
@ -139,6 +140,29 @@ class HomeKitEntity(Entity):
|
|||||||
"""Return True if entity is available."""
|
"""Return True if entity is available."""
|
||||||
return self._available
|
return self._available
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self):
|
||||||
|
"""Return the device info."""
|
||||||
|
accessory_serial = self._accessory_info['serial-number']
|
||||||
|
|
||||||
|
device_info = {
|
||||||
|
'identifiers': {
|
||||||
|
(DOMAIN, 'serial-number', accessory_serial),
|
||||||
|
},
|
||||||
|
'name': self._accessory_info['name'],
|
||||||
|
'manufacturer': self._accessory_info.get('manufacturer', ''),
|
||||||
|
'model': self._accessory_info.get('model', ''),
|
||||||
|
'sw_version': self._accessory_info.get('firmware.revision', ''),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Some devices only have a single accessory - we don't add a via_hub
|
||||||
|
# otherwise it would be self referential.
|
||||||
|
bridge_serial = self._accessory.connection_info['serial-number']
|
||||||
|
if accessory_serial != bridge_serial:
|
||||||
|
device_info['via_hub'] = (DOMAIN, 'serial-number', bridge_serial)
|
||||||
|
|
||||||
|
return device_info
|
||||||
|
|
||||||
def get_characteristic_types(self):
|
def get_characteristic_types(self):
|
||||||
"""Define the homekit characteristics the entity cares about."""
|
"""Define the homekit characteristics the entity cares about."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -153,6 +177,21 @@ async def async_setup_entry(hass, entry):
|
|||||||
del hass.data[KNOWN_DEVICES][conn.unique_id]
|
del hass.data[KNOWN_DEVICES][conn.unique_id]
|
||||||
raise ConfigEntryNotReady
|
raise ConfigEntryNotReady
|
||||||
|
|
||||||
|
conn_info = conn.connection_info
|
||||||
|
|
||||||
|
device_registry = await dr.async_get_registry(hass)
|
||||||
|
device_registry.async_get_or_create(
|
||||||
|
config_entry_id=entry.entry_id,
|
||||||
|
identifiers={
|
||||||
|
(DOMAIN, 'serial-number', conn_info['serial-number']),
|
||||||
|
(DOMAIN, 'accessory-id', conn.unique_id),
|
||||||
|
},
|
||||||
|
name=conn.name,
|
||||||
|
manufacturer=conn_info.get('manufacturer'),
|
||||||
|
model=conn_info.get('model'),
|
||||||
|
sw_version=conn_info.get('firmware.revision'),
|
||||||
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,3 +218,13 @@ class HKDevice():
|
|||||||
This id is random and will change if a device undergoes a hard reset.
|
This id is random and will change if a device undergoes a hard reset.
|
||||||
"""
|
"""
|
||||||
return self.pairing_data['AccessoryPairingID']
|
return self.pairing_data['AccessoryPairingID']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def connection_info(self):
|
||||||
|
"""Return accessory information for the main accessory."""
|
||||||
|
return get_bridge_information(self.accessories)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Name of the bridge accessory."""
|
||||||
|
return get_accessory_name(self.connection_info) or self.unique_id
|
||||||
|
@ -39,3 +39,16 @@ async def test_aqara_gateway_setup(hass):
|
|||||||
assert light_state.attributes['supported_features'] == (
|
assert light_state.attributes['supported_features'] == (
|
||||||
SUPPORT_BRIGHTNESS | SUPPORT_COLOR
|
SUPPORT_BRIGHTNESS | SUPPORT_COLOR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
device_registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
# All the entities are services of the same accessory
|
||||||
|
# So it looks at the protocol like a single physical device
|
||||||
|
assert alarm.device_id == light.device_id
|
||||||
|
|
||||||
|
device = device_registry.async_get(light.device_id)
|
||||||
|
assert device.manufacturer == 'Aqara'
|
||||||
|
assert device.name == 'Aqara Hub-1563'
|
||||||
|
assert device.model == 'ZHWA11LM'
|
||||||
|
assert device.sw_version == '1.4.7'
|
||||||
|
assert device.hub_device_id is None
|
||||||
|
@ -67,6 +67,24 @@ async def test_ecobee3_setup(hass):
|
|||||||
occ3 = entity_registry.async_get('binary_sensor.basement')
|
occ3 = entity_registry.async_get('binary_sensor.basement')
|
||||||
assert occ3.unique_id == 'homekit-AB3C-56'
|
assert occ3.unique_id == 'homekit-AB3C-56'
|
||||||
|
|
||||||
|
device_registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
climate_device = device_registry.async_get(climate.device_id)
|
||||||
|
assert climate_device.manufacturer == 'ecobee Inc.'
|
||||||
|
assert climate_device.name == 'HomeW'
|
||||||
|
assert climate_device.model == 'ecobee3'
|
||||||
|
assert climate_device.sw_version == '4.2.394'
|
||||||
|
assert climate_device.hub_device_id is None
|
||||||
|
|
||||||
|
# Check that an attached sensor has its own device entity that
|
||||||
|
# is linked to the bridge
|
||||||
|
sensor_device = device_registry.async_get(occ1.device_id)
|
||||||
|
assert sensor_device.manufacturer == 'ecobee Inc.'
|
||||||
|
assert sensor_device.name == 'Kitchen'
|
||||||
|
assert sensor_device.model == 'REMOTE SENSOR'
|
||||||
|
assert sensor_device.sw_version == '1.0.0'
|
||||||
|
assert sensor_device.hub_device_id == climate_device.id
|
||||||
|
|
||||||
|
|
||||||
async def test_ecobee3_setup_from_cache(hass, hass_storage):
|
async def test_ecobee3_setup_from_cache(hass, hass_storage):
|
||||||
"""Test that Ecbobee can be correctly setup from its cached entity map."""
|
"""Test that Ecbobee can be correctly setup from its cached entity map."""
|
||||||
|
@ -38,6 +38,15 @@ async def test_koogeek_ls1_setup(hass):
|
|||||||
SUPPORT_BRIGHTNESS | SUPPORT_COLOR
|
SUPPORT_BRIGHTNESS | SUPPORT_COLOR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
device_registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
device = device_registry.async_get(entry.device_id)
|
||||||
|
assert device.manufacturer == 'Koogeek'
|
||||||
|
assert device.name == 'Koogeek-LS1-20833F'
|
||||||
|
assert device.model == 'LS1'
|
||||||
|
assert device.sw_version == '2.2.15'
|
||||||
|
assert device.hub_device_id is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('failure_cls', [
|
@pytest.mark.parametrize('failure_cls', [
|
||||||
AccessoryDisconnectedError, EncryptionError
|
AccessoryDisconnectedError, EncryptionError
|
||||||
|
@ -27,3 +27,15 @@ async def test_lennox_e30_setup(hass):
|
|||||||
assert climate_state.attributes['supported_features'] == (
|
assert climate_state.attributes['supported_features'] == (
|
||||||
SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE
|
SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
device_registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
device = device_registry.async_get(climate.device_id)
|
||||||
|
assert device.manufacturer == 'Lennox'
|
||||||
|
assert device.name == 'Lennox'
|
||||||
|
assert device.model == 'E30 2B'
|
||||||
|
assert device.sw_version == '3.40.XX'
|
||||||
|
|
||||||
|
# The fixture contains a single accessory - so its a single device
|
||||||
|
# and no bridge
|
||||||
|
assert device.hub_device_id is None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user