mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
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>
This commit is contained in:
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.
|
Load config, group, light and sensor data for server information.
|
||||||
Start websocket for push notification of state changes from deCONZ.
|
Start websocket for push notification of state changes from deCONZ.
|
||||||
"""
|
"""
|
||||||
if DOMAIN not in hass.data:
|
hass.data.setdefault(DOMAIN, {})
|
||||||
hass.data[DOMAIN] = {}
|
|
||||||
|
|
||||||
await async_update_group_unique_id(hass, config_entry)
|
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():
|
if not await gateway.async_setup():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
hass.data[DOMAIN][config_entry.unique_id] = gateway
|
hass.data[DOMAIN][config_entry.entry_id] = gateway
|
||||||
|
|
||||||
await gateway.async_update_device_registry()
|
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):
|
async def async_unload_entry(hass, config_entry):
|
||||||
"""Unload deCONZ 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]:
|
if not hass.data[DOMAIN]:
|
||||||
await async_unload_services(hass)
|
await async_unload_services(hass)
|
||||||
|
@ -33,8 +33,8 @@ from .errors import AuthenticationRequired, CannotConnect
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def get_gateway_from_config_entry(hass, config_entry):
|
def get_gateway_from_config_entry(hass, config_entry):
|
||||||
"""Return gateway with a matching bridge id."""
|
"""Return gateway with a matching config entry ID."""
|
||||||
return hass.data[DECONZ_DOMAIN][config_entry.unique_id]
|
return hass.data[DECONZ_DOMAIN][config_entry.entry_id]
|
||||||
|
|
||||||
|
|
||||||
class DeconzGateway:
|
class DeconzGateway:
|
||||||
|
@ -59,14 +59,29 @@ async def async_setup_services(hass):
|
|||||||
service = service_call.service
|
service = service_call.service
|
||||||
service_data = service_call.data
|
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:
|
if service == SERVICE_CONFIGURE_DEVICE:
|
||||||
await async_configure_service(hass, service_data)
|
await async_configure_service(gateway, service_data)
|
||||||
|
|
||||||
elif service == SERVICE_DEVICE_REFRESH:
|
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:
|
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(
|
hass.services.async_register(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -102,7 +117,7 @@ async def async_unload_services(hass):
|
|||||||
hass.services.async_remove(DOMAIN, SERVICE_REMOVE_ORPHANED_ENTRIES)
|
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.
|
"""Set attribute of device in deCONZ.
|
||||||
|
|
||||||
Entity is used to resolve to a device path (e.g. '/lights/1').
|
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:
|
See Dresden Elektroniks REST API documentation for details:
|
||||||
http://dresden-elektronik.github.io/deconz-rest-doc/rest/
|
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, "")
|
field = data.get(SERVICE_FIELD, "")
|
||||||
entity_id = data.get(SERVICE_ENTITY)
|
entity_id = data.get(SERVICE_ENTITY)
|
||||||
data = data[SERVICE_DATA]
|
data = data[SERVICE_DATA]
|
||||||
@ -136,31 +147,21 @@ async def async_configure_service(hass, data):
|
|||||||
await gateway.api.request("put", field, json=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."""
|
"""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
|
gateway.ignore_state_updates = True
|
||||||
await gateway.api.refresh_state()
|
await gateway.api.refresh_state()
|
||||||
gateway.ignore_state_updates = False
|
gateway.ignore_state_updates = False
|
||||||
|
|
||||||
gateway.async_add_device_callback(NEW_GROUP, force=True)
|
for new_device_type in [NEW_GROUP, NEW_LIGHT, NEW_SCENE, NEW_SENSOR]:
|
||||||
gateway.async_add_device_callback(NEW_LIGHT, force=True)
|
gateway.async_add_device_callback(new_device_type, force=True)
|
||||||
gateway.async_add_device_callback(NEW_SCENE, force=True)
|
|
||||||
gateway.async_add_device_callback(NEW_SENSOR, 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."""
|
"""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(
|
device_registry, entity_registry = await asyncio.gather(
|
||||||
hass.helpers.device_registry.async_get_registry(),
|
gateway.hass.helpers.device_registry.async_get_registry(),
|
||||||
hass.helpers.entity_registry.async_get_registry(),
|
gateway.hass.helpers.entity_registry.async_get_registry(),
|
||||||
)
|
)
|
||||||
|
|
||||||
entity_entries = async_entries_for_config_entry(
|
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)
|
config_entry = await setup_deconz_integration(hass, aioclient_mock)
|
||||||
|
|
||||||
assert hass.data[DECONZ_DOMAIN]
|
assert hass.data[DECONZ_DOMAIN]
|
||||||
assert config_entry.unique_id in hass.data[DECONZ_DOMAIN]
|
assert config_entry.entry_id in hass.data[DECONZ_DOMAIN]
|
||||||
assert hass.data[DECONZ_DOMAIN][config_entry.unique_id].master
|
assert hass.data[DECONZ_DOMAIN][config_entry.entry_id].master
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_entry_multiple_gateways(hass, aioclient_mock):
|
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 len(hass.data[DECONZ_DOMAIN]) == 2
|
||||||
assert hass.data[DECONZ_DOMAIN][config_entry.unique_id].master
|
assert hass.data[DECONZ_DOMAIN][config_entry.entry_id].master
|
||||||
assert not hass.data[DECONZ_DOMAIN][config_entry2.unique_id].master
|
assert not hass.data[DECONZ_DOMAIN][config_entry2.entry_id].master
|
||||||
|
|
||||||
|
|
||||||
async def test_unload_entry(hass, aioclient_mock):
|
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 await async_unload_entry(hass, config_entry)
|
||||||
|
|
||||||
assert len(hass.data[DECONZ_DOMAIN]) == 1
|
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):
|
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}
|
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):
|
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)
|
await setup_deconz_integration(hass, aioclient_mock)
|
||||||
|
|
||||||
data = {SERVICE_FIELD: "light/2", SERVICE_DATA: {}}
|
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):
|
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)
|
await setup_deconz_integration(hass, aioclient_mock)
|
||||||
aioclient_mock.clear_requests()
|
aioclient_mock.clear_requests()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user