Fix updating device path from discovery in zha (#55124)
parent
6f75a853f8
commit
ce0a42a407
|
@ -102,14 +102,17 @@ class ZhaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
device = discovery_info["device"]
|
||||
manufacturer = discovery_info["manufacturer"]
|
||||
description = discovery_info["description"]
|
||||
await self.async_set_unique_id(
|
||||
f"{vid}:{pid}_{serial_number}_{manufacturer}_{description}"
|
||||
)
|
||||
self._abort_if_unique_id_configured(
|
||||
updates={
|
||||
CONF_DEVICE: {CONF_DEVICE_PATH: self._device_path},
|
||||
}
|
||||
)
|
||||
dev_path = await self.hass.async_add_executor_job(usb.get_serial_by_id, device)
|
||||
unique_id = f"{vid}:{pid}_{serial_number}_{manufacturer}_{description}"
|
||||
if current_entry := await self.async_set_unique_id(unique_id):
|
||||
self._abort_if_unique_id_configured(
|
||||
updates={
|
||||
CONF_DEVICE: {
|
||||
**current_entry.data[CONF_DEVICE],
|
||||
CONF_DEVICE_PATH: dev_path,
|
||||
},
|
||||
}
|
||||
)
|
||||
# Check if already configured
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
@ -127,7 +130,6 @@ class ZhaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
if vid == "10C4" and pid == "8A2A" and "ZigBee" not in description:
|
||||
return self.async_abort(reason="not_zha_device")
|
||||
|
||||
dev_path = await self.hass.async_add_executor_job(usb.get_serial_by_id, device)
|
||||
self._auto_detected_data = await detect_radios(dev_path)
|
||||
if self._auto_detected_data is None:
|
||||
return self.async_abort(reason="not_zha_device")
|
||||
|
@ -166,12 +168,15 @@ class ZhaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
host = discovery_info[CONF_HOST]
|
||||
device_path = f"socket://{host}:6638"
|
||||
|
||||
await self.async_set_unique_id(node_name)
|
||||
self._abort_if_unique_id_configured(
|
||||
updates={
|
||||
CONF_DEVICE: {CONF_DEVICE_PATH: device_path},
|
||||
}
|
||||
)
|
||||
if current_entry := await self.async_set_unique_id(node_name):
|
||||
self._abort_if_unique_id_configured(
|
||||
updates={
|
||||
CONF_DEVICE: {
|
||||
**current_entry.data[CONF_DEVICE],
|
||||
CONF_DEVICE_PATH: device_path,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Check if already configured
|
||||
if self._async_current_entries():
|
||||
|
|
|
@ -5,6 +5,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
|||
import pytest
|
||||
import serial.tools.list_ports
|
||||
import zigpy.config
|
||||
from zigpy.config import CONF_DEVICE, CONF_DEVICE_PATH
|
||||
|
||||
from homeassistant import setup
|
||||
from homeassistant.components.ssdp import (
|
||||
|
@ -13,7 +14,13 @@ from homeassistant.components.ssdp import (
|
|||
ATTR_UPNP_SERIAL,
|
||||
)
|
||||
from homeassistant.components.zha import config_flow
|
||||
from homeassistant.components.zha.core.const import CONF_RADIO_TYPE, DOMAIN, RadioType
|
||||
from homeassistant.components.zha.core.const import (
|
||||
CONF_BAUDRATE,
|
||||
CONF_FLOWCONTROL,
|
||||
CONF_RADIO_TYPE,
|
||||
DOMAIN,
|
||||
RadioType,
|
||||
)
|
||||
from homeassistant.config_entries import (
|
||||
SOURCE_SSDP,
|
||||
SOURCE_USB,
|
||||
|
@ -21,7 +28,11 @@ from homeassistant.config_entries import (
|
|||
SOURCE_ZEROCONF,
|
||||
)
|
||||
from homeassistant.const import CONF_SOURCE
|
||||
from homeassistant.data_entry_flow import RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_FORM
|
||||
from homeassistant.data_entry_flow import (
|
||||
RESULT_TYPE_ABORT,
|
||||
RESULT_TYPE_CREATE_ENTRY,
|
||||
RESULT_TYPE_FORM,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
@ -57,15 +68,51 @@ async def test_discovery(detect_mock, hass):
|
|||
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == "socket://192.168.1.200:6638"
|
||||
assert result["data"] == {
|
||||
"device": {
|
||||
"baudrate": 115200,
|
||||
"flow_control": None,
|
||||
"path": "socket://192.168.1.200:6638",
|
||||
CONF_DEVICE: {
|
||||
CONF_BAUDRATE: 115200,
|
||||
CONF_FLOWCONTROL: None,
|
||||
CONF_DEVICE_PATH: "socket://192.168.1.200:6638",
|
||||
},
|
||||
CONF_RADIO_TYPE: "znp",
|
||||
}
|
||||
|
||||
|
||||
@patch("homeassistant.components.zha.async_setup_entry", AsyncMock(return_value=True))
|
||||
@patch("zigpy_znp.zigbee.application.ControllerApplication.probe", return_value=True)
|
||||
async def test_discovery_via_zeroconf_ip_change(detect_mock, hass):
|
||||
"""Test zeroconf flow -- radio detected."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="tube_zb_gw_cc2652p2_poe",
|
||||
data={
|
||||
CONF_DEVICE: {
|
||||
CONF_DEVICE_PATH: "socket://192.168.1.5:6638",
|
||||
CONF_BAUDRATE: 115200,
|
||||
CONF_FLOWCONTROL: None,
|
||||
}
|
||||
},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
service_info = {
|
||||
"host": "192.168.1.22",
|
||||
"port": 6053,
|
||||
"hostname": "tube_zb_gw_cc2652p2_poe.local.",
|
||||
"properties": {"address": "tube_zb_gw_cc2652p2_poe.local"},
|
||||
}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"zha", context={"source": SOURCE_ZEROCONF}, data=service_info
|
||||
)
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
assert entry.data[CONF_DEVICE] == {
|
||||
CONF_DEVICE_PATH: "socket://192.168.1.22:6638",
|
||||
CONF_BAUDRATE: 115200,
|
||||
CONF_FLOWCONTROL: None,
|
||||
}
|
||||
|
||||
|
||||
@patch("zigpy_znp.zigbee.application.ControllerApplication.probe", return_value=True)
|
||||
async def test_discovery_via_usb(detect_mock, hass):
|
||||
"""Test usb flow -- radio detected."""
|
||||
|
@ -117,7 +164,7 @@ async def test_discovery_via_usb_no_radio(detect_mock, hass):
|
|||
"zha", context={"source": SOURCE_USB}, data=discovery_info
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert result["type"] == "abort"
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "not_zha_device"
|
||||
|
||||
|
||||
|
@ -136,7 +183,7 @@ async def test_discovery_via_usb_rejects_nortek_zwave(detect_mock, hass):
|
|||
"zha", context={"source": SOURCE_USB}, data=discovery_info
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert result["type"] == "abort"
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "not_zha_device"
|
||||
|
||||
|
||||
|
@ -144,7 +191,9 @@ async def test_discovery_via_usb_rejects_nortek_zwave(detect_mock, hass):
|
|||
async def test_discovery_via_usb_already_setup(detect_mock, hass):
|
||||
"""Test usb flow -- already setup."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
MockConfigEntry(domain=DOMAIN, data={"usb_path": "/dev/ttyUSB1"}).add_to_hass(hass)
|
||||
MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_DEVICE: {CONF_DEVICE_PATH: "/dev/ttyUSB1"}}
|
||||
).add_to_hass(hass)
|
||||
|
||||
discovery_info = {
|
||||
"device": "/dev/ttyZIGBEE",
|
||||
|
@ -159,10 +208,49 @@ async def test_discovery_via_usb_already_setup(detect_mock, hass):
|
|||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
|
||||
|
||||
@patch("homeassistant.components.zha.async_setup_entry", AsyncMock(return_value=True))
|
||||
async def test_discovery_via_usb_path_changes(hass):
|
||||
"""Test usb flow already setup and the path changes."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id="AAAA:AAAA_1234_test_zigbee radio",
|
||||
data={
|
||||
CONF_DEVICE: {
|
||||
CONF_DEVICE_PATH: "/dev/ttyUSB1",
|
||||
CONF_BAUDRATE: 115200,
|
||||
CONF_FLOWCONTROL: None,
|
||||
}
|
||||
},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
discovery_info = {
|
||||
"device": "/dev/ttyZIGBEE",
|
||||
"pid": "AAAA",
|
||||
"vid": "AAAA",
|
||||
"serial_number": "1234",
|
||||
"description": "zigbee radio",
|
||||
"manufacturer": "test",
|
||||
}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"zha", context={"source": SOURCE_USB}, data=discovery_info
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
assert entry.data[CONF_DEVICE] == {
|
||||
CONF_DEVICE_PATH: "/dev/ttyZIGBEE",
|
||||
CONF_BAUDRATE: 115200,
|
||||
CONF_FLOWCONTROL: None,
|
||||
}
|
||||
|
||||
|
||||
@patch("zigpy_znp.zigbee.application.ControllerApplication.probe", return_value=True)
|
||||
async def test_discovery_via_usb_deconz_already_discovered(detect_mock, hass):
|
||||
"""Test usb flow -- deconz discovered."""
|
||||
|
@ -204,7 +292,9 @@ async def test_discovery_already_setup(detect_mock, hass):
|
|||
"properties": {"name": "tube_123456"},
|
||||
}
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
MockConfigEntry(domain=DOMAIN, data={"usb_path": "/dev/ttyUSB1"}).add_to_hass(hass)
|
||||
MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_DEVICE: {CONF_DEVICE_PATH: "/dev/ttyUSB1"}}
|
||||
).add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
"zha", context={"source": SOURCE_ZEROCONF}, data=service_info
|
||||
|
@ -310,7 +400,9 @@ async def test_pick_radio_flow(hass, radio_type):
|
|||
|
||||
async def test_user_flow_existing_config_entry(hass):
|
||||
"""Test if config entry already exists."""
|
||||
MockConfigEntry(domain=DOMAIN, data={"usb_path": "/dev/ttyUSB1"}).add_to_hass(hass)
|
||||
MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_DEVICE: {CONF_DEVICE_PATH: "/dev/ttyUSB1"}}
|
||||
).add_to_hass(hass)
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={CONF_SOURCE: SOURCE_USER}
|
||||
|
|
Loading…
Reference in New Issue