mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
deCONZ - Improve ssdp discovery by storing uuid in config entry (#26882)
* Improve ssdp discovery by storing uuid in config entry so discovery can update any deconz entry, loaded or not
This commit is contained in:
parent
cc611615aa
commit
4582b6e668
@ -4,8 +4,8 @@ import voluptuous as vol
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
|
||||
from .config_flow import get_master_gateway
|
||||
from .const import CONF_BRIDGEID, CONF_MASTER_GATEWAY, DOMAIN
|
||||
from .gateway import DeconzGateway
|
||||
from .const import CONF_BRIDGEID, CONF_MASTER_GATEWAY, CONF_UUID, DOMAIN
|
||||
from .gateway import DeconzGateway, get_gateway_from_config_entry
|
||||
from .services import async_setup_services, async_unload_services
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
@ -39,6 +39,9 @@ async def async_setup_entry(hass, config_entry):
|
||||
|
||||
await gateway.async_update_device_registry()
|
||||
|
||||
if CONF_UUID not in config_entry.data:
|
||||
await async_add_uuid_to_config_entry(hass, config_entry)
|
||||
|
||||
await async_setup_services(hass)
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, gateway.shutdown)
|
||||
@ -68,11 +71,14 @@ async def async_update_master_gateway(hass, config_entry):
|
||||
Makes sure there is always one master available.
|
||||
"""
|
||||
master = not get_master_gateway(hass)
|
||||
|
||||
old_options = dict(config_entry.options)
|
||||
|
||||
new_options = {CONF_MASTER_GATEWAY: master}
|
||||
|
||||
options = {**old_options, **new_options}
|
||||
options = {**config_entry.options, CONF_MASTER_GATEWAY: master}
|
||||
|
||||
hass.config_entries.async_update_entry(config_entry, options=options)
|
||||
|
||||
|
||||
async def async_add_uuid_to_config_entry(hass, config_entry):
|
||||
"""Add UUID to config entry to help discovery identify entries."""
|
||||
gateway = get_gateway_from_config_entry(hass, config_entry)
|
||||
config = {**config_entry.data, CONF_UUID: gateway.api.config.uuid}
|
||||
|
||||
hass.config_entries.async_update_entry(config_entry, data=config)
|
||||
|
@ -5,7 +5,7 @@ import async_timeout
|
||||
import voluptuous as vol
|
||||
|
||||
from pydeconz.errors import ResponseError, RequestError
|
||||
from pydeconz.utils import async_discovery, async_get_api_key, async_get_bridgeid
|
||||
from pydeconz.utils import async_discovery, async_get_api_key, async_get_gateway_config
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PORT
|
||||
@ -16,6 +16,7 @@ from .const import (
|
||||
CONF_ALLOW_CLIP_SENSOR,
|
||||
CONF_ALLOW_DECONZ_GROUPS,
|
||||
CONF_BRIDGEID,
|
||||
CONF_UUID,
|
||||
DEFAULT_ALLOW_CLIP_SENSOR,
|
||||
DEFAULT_ALLOW_DECONZ_GROUPS,
|
||||
DEFAULT_PORT,
|
||||
@ -144,9 +145,11 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
|
||||
try:
|
||||
with async_timeout.timeout(10):
|
||||
self.deconz_config[CONF_BRIDGEID] = await async_get_bridgeid(
|
||||
gateway_config = await async_get_gateway_config(
|
||||
session, **self.deconz_config
|
||||
)
|
||||
self.deconz_config[CONF_BRIDGEID] = gateway_config.bridgeid
|
||||
self.deconz_config[CONF_UUID] = gateway_config.uuid
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
return self.async_abort(reason="no_bridges")
|
||||
@ -172,14 +175,10 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
return self.async_abort(reason="not_deconz_bridge")
|
||||
|
||||
uuid = discovery_info[ATTR_UUID].replace("uuid:", "")
|
||||
gateways = {
|
||||
gateway.api.config.uuid: gateway
|
||||
for gateway in self.hass.data.get(DOMAIN, {}).values()
|
||||
}
|
||||
|
||||
if uuid in gateways:
|
||||
entry = gateways[uuid].config_entry
|
||||
return await self._update_entry(entry, discovery_info[CONF_HOST])
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||
if uuid == entry.data.get(CONF_UUID):
|
||||
return await self._update_entry(entry, discovery_info[CONF_HOST])
|
||||
|
||||
bridgeid = discovery_info[ATTR_SERIAL]
|
||||
if any(
|
||||
|
@ -5,13 +5,15 @@ _LOGGER = logging.getLogger(__package__)
|
||||
|
||||
DOMAIN = "deconz"
|
||||
|
||||
CONF_BRIDGEID = "bridgeid"
|
||||
CONF_UUID = "uuid"
|
||||
|
||||
DEFAULT_PORT = 80
|
||||
DEFAULT_ALLOW_CLIP_SENSOR = False
|
||||
DEFAULT_ALLOW_DECONZ_GROUPS = True
|
||||
|
||||
CONF_ALLOW_CLIP_SENSOR = "allow_clip_sensor"
|
||||
CONF_ALLOW_DECONZ_GROUPS = "allow_deconz_groups"
|
||||
CONF_BRIDGEID = "bridgeid"
|
||||
CONF_MASTER_GATEWAY = "master"
|
||||
|
||||
SUPPORTED_PLATFORMS = [
|
||||
|
@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/components/deconz",
|
||||
"requirements": [
|
||||
"pydeconz==62"
|
||||
"pydeconz==63"
|
||||
],
|
||||
"ssdp": {
|
||||
"manufacturer": [
|
||||
|
@ -1129,7 +1129,7 @@ pydaikin==1.6.1
|
||||
pydanfossair==0.1.0
|
||||
|
||||
# homeassistant.components.deconz
|
||||
pydeconz==62
|
||||
pydeconz==63
|
||||
|
||||
# homeassistant.components.delijn
|
||||
pydelijn==0.5.1
|
||||
|
@ -294,7 +294,7 @@ pyblackbird==0.5
|
||||
pychromecast==4.0.1
|
||||
|
||||
# homeassistant.components.deconz
|
||||
pydeconz==62
|
||||
pydeconz==63
|
||||
|
||||
# homeassistant.components.zwave
|
||||
pydispatcher==2.0.5
|
||||
|
@ -209,22 +209,25 @@ async def test_bridge_discovery_update_existing_entry(hass):
|
||||
"""Test if a discovered bridge has already been configured."""
|
||||
entry = MockConfigEntry(
|
||||
domain=config_flow.DOMAIN,
|
||||
data={config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_BRIDGEID: "id"},
|
||||
data={
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_BRIDGEID: "123ABC",
|
||||
config_flow.CONF_UUID: "456DEF",
|
||||
},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
gateway = Mock()
|
||||
gateway.config_entry = entry
|
||||
gateway.api.config.uuid = "1234"
|
||||
hass.data[config_flow.DOMAIN] = {"id": gateway}
|
||||
hass.data[config_flow.DOMAIN] = {"123ABC": gateway}
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
data={
|
||||
config_flow.CONF_HOST: "mock-deconz",
|
||||
ATTR_SERIAL: "id",
|
||||
ATTR_SERIAL: "123ABC",
|
||||
ATTR_MANUFACTURERURL: config_flow.DECONZ_MANUFACTURERURL,
|
||||
config_flow.ATTR_UUID: "uuid:1234",
|
||||
config_flow.ATTR_UUID: "uuid:456DEF",
|
||||
},
|
||||
context={"source": "ssdp"},
|
||||
)
|
||||
@ -238,7 +241,7 @@ async def test_create_entry(hass, aioclient_mock):
|
||||
"""Test that _create_entry work and that bridgeid can be requested."""
|
||||
aioclient_mock.get(
|
||||
"http://1.2.3.4:80/api/1234567890ABCDEF/config",
|
||||
json={"bridgeid": "id"},
|
||||
json={"bridgeid": "123ABC", "uuid": "456DEF"},
|
||||
headers={"content-type": "application/json"},
|
||||
)
|
||||
|
||||
@ -253,12 +256,13 @@ async def test_create_entry(hass, aioclient_mock):
|
||||
result = await flow._create_entry()
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
assert result["title"] == "deCONZ-id"
|
||||
assert result["title"] == "deCONZ-123ABC"
|
||||
assert result["data"] == {
|
||||
config_flow.CONF_BRIDGEID: "id",
|
||||
config_flow.CONF_BRIDGEID: "123ABC",
|
||||
config_flow.CONF_HOST: "1.2.3.4",
|
||||
config_flow.CONF_PORT: 80,
|
||||
config_flow.CONF_API_KEY: "1234567890ABCDEF",
|
||||
config_flow.CONF_UUID: "456DEF",
|
||||
}
|
||||
|
||||
|
||||
@ -273,7 +277,7 @@ async def test_create_entry_timeout(hass, aioclient_mock):
|
||||
}
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.deconz.config_flow.async_get_bridgeid",
|
||||
"homeassistant.components.deconz.config_flow.async_get_gateway_config",
|
||||
side_effect=asyncio.TimeoutError,
|
||||
):
|
||||
result = await flow._create_entry()
|
||||
|
@ -20,6 +20,7 @@ ENTRY_CONFIG = {
|
||||
deconz.config_flow.CONF_BRIDGEID: BRIDGEID,
|
||||
deconz.config_flow.CONF_HOST: "1.2.3.4",
|
||||
deconz.config_flow.CONF_PORT: 80,
|
||||
deconz.config_flow.CONF_UUID: "456DEF",
|
||||
}
|
||||
|
||||
DECONZ_CONFIG = {
|
||||
@ -147,7 +148,7 @@ async def test_update_address(hass):
|
||||
deconz.config_flow.CONF_PORT: 80,
|
||||
ssdp.ATTR_SERIAL: BRIDGEID,
|
||||
ssdp.ATTR_MANUFACTURERURL: deconz.config_flow.DECONZ_MANUFACTURERURL,
|
||||
deconz.config_flow.ATTR_UUID: "uuid:1234",
|
||||
deconz.config_flow.ATTR_UUID: "uuid:456DEF",
|
||||
},
|
||||
context={"source": "ssdp"},
|
||||
)
|
||||
|
@ -1,33 +1,34 @@
|
||||
"""Test deCONZ component setup process."""
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import asyncio
|
||||
|
||||
from asynctest import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.components import deconz
|
||||
|
||||
from tests.common import mock_coro, MockConfigEntry
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
ENTRY1_HOST = "1.2.3.4"
|
||||
ENTRY1_PORT = 80
|
||||
ENTRY1_API_KEY = "1234567890ABCDEF"
|
||||
ENTRY1_BRIDGEID = "12345ABC"
|
||||
ENTRY1_UUID = "456DEF"
|
||||
|
||||
ENTRY2_HOST = "2.3.4.5"
|
||||
ENTRY2_PORT = 80
|
||||
ENTRY2_API_KEY = "1234567890ABCDEF"
|
||||
ENTRY2_BRIDGEID = "23456DEF"
|
||||
ENTRY2_UUID = "789ACE"
|
||||
|
||||
|
||||
async def setup_entry(hass, entry):
|
||||
"""Test that setup entry works."""
|
||||
with patch.object(
|
||||
deconz.DeconzGateway, "async_setup", return_value=mock_coro(True)
|
||||
deconz.DeconzGateway, "async_setup", return_value=True
|
||||
), patch.object(
|
||||
deconz.DeconzGateway,
|
||||
"async_update_device_registry",
|
||||
return_value=mock_coro(True),
|
||||
deconz.DeconzGateway, "async_update_device_registry", return_value=True
|
||||
):
|
||||
assert await deconz.async_setup_entry(hass, entry) is True
|
||||
|
||||
@ -67,6 +68,7 @@ async def test_setup_entry_successful(hass):
|
||||
deconz.config_flow.CONF_PORT: ENTRY1_PORT,
|
||||
deconz.config_flow.CONF_API_KEY: ENTRY1_API_KEY,
|
||||
deconz.CONF_BRIDGEID: ENTRY1_BRIDGEID,
|
||||
deconz.CONF_UUID: ENTRY1_UUID,
|
||||
},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
@ -86,6 +88,7 @@ async def test_setup_entry_multiple_gateways(hass):
|
||||
deconz.config_flow.CONF_PORT: ENTRY1_PORT,
|
||||
deconz.config_flow.CONF_API_KEY: ENTRY1_API_KEY,
|
||||
deconz.CONF_BRIDGEID: ENTRY1_BRIDGEID,
|
||||
deconz.CONF_UUID: ENTRY1_UUID,
|
||||
},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
@ -97,6 +100,7 @@ async def test_setup_entry_multiple_gateways(hass):
|
||||
deconz.config_flow.CONF_PORT: ENTRY2_PORT,
|
||||
deconz.config_flow.CONF_API_KEY: ENTRY2_API_KEY,
|
||||
deconz.CONF_BRIDGEID: ENTRY2_BRIDGEID,
|
||||
deconz.CONF_UUID: ENTRY2_UUID,
|
||||
},
|
||||
)
|
||||
entry2.add_to_hass(hass)
|
||||
@ -119,15 +123,14 @@ async def test_unload_entry(hass):
|
||||
deconz.config_flow.CONF_PORT: ENTRY1_PORT,
|
||||
deconz.config_flow.CONF_API_KEY: ENTRY1_API_KEY,
|
||||
deconz.CONF_BRIDGEID: ENTRY1_BRIDGEID,
|
||||
deconz.CONF_UUID: ENTRY1_UUID,
|
||||
},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
await setup_entry(hass, entry)
|
||||
|
||||
with patch.object(
|
||||
deconz.DeconzGateway, "async_reset", return_value=mock_coro(True)
|
||||
):
|
||||
with patch.object(deconz.DeconzGateway, "async_reset", return_value=True):
|
||||
assert await deconz.async_unload_entry(hass, entry)
|
||||
|
||||
assert not hass.data[deconz.DOMAIN]
|
||||
@ -142,6 +145,7 @@ async def test_unload_entry_multiple_gateways(hass):
|
||||
deconz.config_flow.CONF_PORT: ENTRY1_PORT,
|
||||
deconz.config_flow.CONF_API_KEY: ENTRY1_API_KEY,
|
||||
deconz.CONF_BRIDGEID: ENTRY1_BRIDGEID,
|
||||
deconz.CONF_UUID: ENTRY1_UUID,
|
||||
},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
@ -153,6 +157,7 @@ async def test_unload_entry_multiple_gateways(hass):
|
||||
deconz.config_flow.CONF_PORT: ENTRY2_PORT,
|
||||
deconz.config_flow.CONF_API_KEY: ENTRY2_API_KEY,
|
||||
deconz.CONF_BRIDGEID: ENTRY2_BRIDGEID,
|
||||
deconz.CONF_UUID: ENTRY2_UUID,
|
||||
},
|
||||
)
|
||||
entry2.add_to_hass(hass)
|
||||
@ -160,9 +165,7 @@ async def test_unload_entry_multiple_gateways(hass):
|
||||
await setup_entry(hass, entry)
|
||||
await setup_entry(hass, entry2)
|
||||
|
||||
with patch.object(
|
||||
deconz.DeconzGateway, "async_reset", return_value=mock_coro(True)
|
||||
):
|
||||
with patch.object(deconz.DeconzGateway, "async_reset", return_value=True):
|
||||
assert await deconz.async_unload_entry(hass, entry)
|
||||
|
||||
assert ENTRY2_BRIDGEID in hass.data[deconz.DOMAIN]
|
||||
|
Loading…
x
Reference in New Issue
Block a user