Make use of entry id rather than unique id when storing deconz entry in hass.data (#52584)
* Make use of entry id rather than unique id when storing entry in hass data * Update homeassistant/components/deconz/services.py Co-authored-by: Franck Nijhof <frenck@frenck.nl> Co-authored-by: Franck Nijhof <frenck@frenck.nl>pull/52513/head
parent
7ba1fdea70
commit
605f65b75d
|
@ -20,8 +20,7 @@ async def async_setup_entry(hass, config_entry):
|
|||
Load config, group, light and sensor data for server information.
|
||||
Start websocket for push notification of state changes from deCONZ.
|
||||
"""
|
||||
if DOMAIN not in hass.data:
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
||||
await async_update_group_unique_id(hass, config_entry)
|
||||
|
||||
|
@ -33,7 +32,7 @@ async def async_setup_entry(hass, config_entry):
|
|||
if not await gateway.async_setup():
|
||||
return False
|
||||
|
||||
hass.data[DOMAIN][config_entry.unique_id] = gateway
|
||||
hass.data[DOMAIN][config_entry.entry_id] = gateway
|
||||
|
||||
await gateway.async_update_device_registry()
|
||||
|
||||
|
@ -48,7 +47,7 @@ async def async_setup_entry(hass, config_entry):
|
|||
|
||||
async def async_unload_entry(hass, config_entry):
|
||||
"""Unload deCONZ config entry."""
|
||||
gateway = hass.data[DOMAIN].pop(config_entry.unique_id)
|
||||
gateway = hass.data[DOMAIN].pop(config_entry.entry_id)
|
||||
|
||||
if not hass.data[DOMAIN]:
|
||||
await async_unload_services(hass)
|
||||
|
|
|
@ -33,8 +33,8 @@ from .errors import AuthenticationRequired, CannotConnect
|
|||
|
||||
@callback
|
||||
def get_gateway_from_config_entry(hass, config_entry):
|
||||
"""Return gateway with a matching bridge id."""
|
||||
return hass.data[DECONZ_DOMAIN][config_entry.unique_id]
|
||||
"""Return gateway with a matching config entry ID."""
|
||||
return hass.data[DECONZ_DOMAIN][config_entry.entry_id]
|
||||
|
||||
|
||||
class DeconzGateway:
|
||||
|
|
|
@ -59,14 +59,29 @@ async def async_setup_services(hass):
|
|||
service = service_call.service
|
||||
service_data = service_call.data
|
||||
|
||||
gateway = get_master_gateway(hass)
|
||||
if CONF_BRIDGE_ID in service_data:
|
||||
found_gateway = False
|
||||
bridge_id = normalize_bridge_id(service_data[CONF_BRIDGE_ID])
|
||||
|
||||
for possible_gateway in hass.data[DOMAIN].values():
|
||||
if possible_gateway.bridgeid == bridge_id:
|
||||
gateway = possible_gateway
|
||||
found_gateway = True
|
||||
break
|
||||
|
||||
if not found_gateway:
|
||||
LOGGER.error("Could not find the gateway %s", bridge_id)
|
||||
return
|
||||
|
||||
if service == SERVICE_CONFIGURE_DEVICE:
|
||||
await async_configure_service(hass, service_data)
|
||||
await async_configure_service(gateway, service_data)
|
||||
|
||||
elif service == SERVICE_DEVICE_REFRESH:
|
||||
await async_refresh_devices_service(hass, service_data)
|
||||
await async_refresh_devices_service(gateway)
|
||||
|
||||
elif service == SERVICE_REMOVE_ORPHANED_ENTRIES:
|
||||
await async_remove_orphaned_entries_service(hass, service_data)
|
||||
await async_remove_orphaned_entries_service(gateway)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
|
@ -102,7 +117,7 @@ async def async_unload_services(hass):
|
|||
hass.services.async_remove(DOMAIN, SERVICE_REMOVE_ORPHANED_ENTRIES)
|
||||
|
||||
|
||||
async def async_configure_service(hass, data):
|
||||
async def async_configure_service(gateway, data):
|
||||
"""Set attribute of device in deCONZ.
|
||||
|
||||
Entity is used to resolve to a device path (e.g. '/lights/1').
|
||||
|
@ -118,10 +133,6 @@ async def async_configure_service(hass, data):
|
|||
See Dresden Elektroniks REST API documentation for details:
|
||||
http://dresden-elektronik.github.io/deconz-rest-doc/rest/
|
||||
"""
|
||||
gateway = get_master_gateway(hass)
|
||||
if CONF_BRIDGE_ID in data:
|
||||
gateway = hass.data[DOMAIN][normalize_bridge_id(data[CONF_BRIDGE_ID])]
|
||||
|
||||
field = data.get(SERVICE_FIELD, "")
|
||||
entity_id = data.get(SERVICE_ENTITY)
|
||||
data = data[SERVICE_DATA]
|
||||
|
@ -136,31 +147,21 @@ async def async_configure_service(hass, data):
|
|||
await gateway.api.request("put", field, json=data)
|
||||
|
||||
|
||||
async def async_refresh_devices_service(hass, data):
|
||||
async def async_refresh_devices_service(gateway):
|
||||
"""Refresh available devices from deCONZ."""
|
||||
gateway = get_master_gateway(hass)
|
||||
if CONF_BRIDGE_ID in data:
|
||||
gateway = hass.data[DOMAIN][normalize_bridge_id(data[CONF_BRIDGE_ID])]
|
||||
|
||||
gateway.ignore_state_updates = True
|
||||
await gateway.api.refresh_state()
|
||||
gateway.ignore_state_updates = False
|
||||
|
||||
gateway.async_add_device_callback(NEW_GROUP, force=True)
|
||||
gateway.async_add_device_callback(NEW_LIGHT, force=True)
|
||||
gateway.async_add_device_callback(NEW_SCENE, force=True)
|
||||
gateway.async_add_device_callback(NEW_SENSOR, force=True)
|
||||
for new_device_type in [NEW_GROUP, NEW_LIGHT, NEW_SCENE, NEW_SENSOR]:
|
||||
gateway.async_add_device_callback(new_device_type, force=True)
|
||||
|
||||
|
||||
async def async_remove_orphaned_entries_service(hass, data):
|
||||
async def async_remove_orphaned_entries_service(gateway):
|
||||
"""Remove orphaned deCONZ entries from device and entity registries."""
|
||||
gateway = get_master_gateway(hass)
|
||||
if CONF_BRIDGE_ID in data:
|
||||
gateway = hass.data[DOMAIN][normalize_bridge_id(data[CONF_BRIDGE_ID])]
|
||||
|
||||
device_registry, entity_registry = await asyncio.gather(
|
||||
hass.helpers.device_registry.async_get_registry(),
|
||||
hass.helpers.entity_registry.async_get_registry(),
|
||||
gateway.hass.helpers.device_registry.async_get_registry(),
|
||||
gateway.hass.helpers.entity_registry.async_get_registry(),
|
||||
)
|
||||
|
||||
entity_entries = async_entries_for_config_entry(
|
||||
|
|
|
@ -61,8 +61,8 @@ async def test_setup_entry_successful(hass, aioclient_mock):
|
|||
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
assert hass.data[DECONZ_DOMAIN]
|
||||
assert config_entry.unique_id in hass.data[DECONZ_DOMAIN]
|
||||
assert hass.data[DECONZ_DOMAIN][config_entry.unique_id].master
|
||||
assert config_entry.entry_id in hass.data[DECONZ_DOMAIN]
|
||||
assert hass.data[DECONZ_DOMAIN][config_entry.entry_id].master
|
||||
|
||||
|
||||
async def test_setup_entry_multiple_gateways(hass, aioclient_mock):
|
||||
|
@ -80,8 +80,8 @@ async def test_setup_entry_multiple_gateways(hass, aioclient_mock):
|
|||
)
|
||||
|
||||
assert len(hass.data[DECONZ_DOMAIN]) == 2
|
||||
assert hass.data[DECONZ_DOMAIN][config_entry.unique_id].master
|
||||
assert not hass.data[DECONZ_DOMAIN][config_entry2.unique_id].master
|
||||
assert hass.data[DECONZ_DOMAIN][config_entry.entry_id].master
|
||||
assert not hass.data[DECONZ_DOMAIN][config_entry2.entry_id].master
|
||||
|
||||
|
||||
async def test_unload_entry(hass, aioclient_mock):
|
||||
|
@ -112,7 +112,7 @@ async def test_unload_entry_multiple_gateways(hass, aioclient_mock):
|
|||
assert await async_unload_entry(hass, config_entry)
|
||||
|
||||
assert len(hass.data[DECONZ_DOMAIN]) == 1
|
||||
assert hass.data[DECONZ_DOMAIN][config_entry2.unique_id].master
|
||||
assert hass.data[DECONZ_DOMAIN][config_entry2.entry_id].master
|
||||
|
||||
|
||||
async def test_update_group_unique_id(hass):
|
||||
|
|
|
@ -152,8 +152,27 @@ async def test_configure_service_with_entity_and_field(hass, aioclient_mock):
|
|||
assert aioclient_mock.mock_calls[1][2] == {"on": True, "attr1": 10, "attr2": 20}
|
||||
|
||||
|
||||
async def test_configure_service_with_faulty_bridgeid(hass, aioclient_mock):
|
||||
"""Test that service fails on a bad bridge id."""
|
||||
await setup_deconz_integration(hass, aioclient_mock)
|
||||
aioclient_mock.clear_requests()
|
||||
|
||||
data = {
|
||||
CONF_BRIDGE_ID: "Bad bridge id",
|
||||
SERVICE_FIELD: "/lights/1",
|
||||
SERVICE_DATA: {"on": True},
|
||||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
DECONZ_DOMAIN, SERVICE_CONFIGURE_DEVICE, service_data=data
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(aioclient_mock.mock_calls) == 0
|
||||
|
||||
|
||||
async def test_configure_service_with_faulty_field(hass, aioclient_mock):
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
"""Test that service fails on a bad field."""
|
||||
await setup_deconz_integration(hass, aioclient_mock)
|
||||
|
||||
data = {SERVICE_FIELD: "light/2", SERVICE_DATA: {}}
|
||||
|
@ -166,7 +185,7 @@ async def test_configure_service_with_faulty_field(hass, aioclient_mock):
|
|||
|
||||
|
||||
async def test_configure_service_with_faulty_entity(hass, aioclient_mock):
|
||||
"""Test that service invokes pydeconz with the correct path and data."""
|
||||
"""Test that service on a non existing entity."""
|
||||
await setup_deconz_integration(hass, aioclient_mock)
|
||||
aioclient_mock.clear_requests()
|
||||
|
||||
|
|
Loading…
Reference in New Issue