Fix Konnected multiple discovery of panels (#59953)

* Konnected - Fix multiple discovery of panels.

This resolves an issue which creates multiple discoveries of a Konnected panel if it is restarted and fails to connect to home assistant.

See #57467.

* Revert changes to user step, add handling to ssdp step.

* Add abort reason string to strings.json

* Abort ssdp discovery if device is already known.

* Add test for multiple discovery fix.

* Remove unrelated file change.

* Add ssdp discovery abort tests.

* Add missing abort reason check.

* Add "already_configured" to strings.

* Use "cannot_connect" abort reason.
This commit is contained in:
h2zero 2021-11-24 03:35:00 -07:00 committed by GitHub
parent 74cfbf5f42
commit f4f945e65e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 99 additions and 3 deletions

View file

@ -267,10 +267,28 @@ class KonnectedFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
else:
# extract host/port from ssdp_location
netloc = urlparse(discovery_info["ssdp_location"]).netloc.split(":")
return await self.async_step_user(
user_input={CONF_HOST: netloc[0], CONF_PORT: int(netloc[1])}
self._async_abort_entries_match(
{CONF_HOST: netloc[0], CONF_PORT: int(netloc[1])}
)
try:
status = await get_status(self.hass, netloc[0], int(netloc[1]))
except CannotConnect:
return self.async_abort(reason="cannot_connect")
else:
self.data[CONF_HOST] = netloc[0]
self.data[CONF_PORT] = int(netloc[1])
self.data[CONF_ID] = status.get(
"chipId", status["mac"].replace(":", "")
)
self.data[CONF_MODEL] = status.get("model", KONN_MODEL)
KonnectedFlowHandler.discovered_hosts[self.data[CONF_ID]] = {
CONF_HOST: self.data[CONF_HOST],
CONF_PORT: self.data[CONF_PORT],
}
return await self.async_step_confirm()
return self.async_abort(reason="unknown")
async def async_step_user(self, user_input=None):

View file

@ -24,7 +24,8 @@
"unknown": "[%key:common::config_flow::error::unknown%]",
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
"not_konn_panel": "Not a recognized Konnected.io device"
"not_konn_panel": "Not a recognized Konnected.io device",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
}
},
"options": {

View file

@ -109,6 +109,7 @@ async def test_ssdp(hass, mock_panel):
"model": "Konnected",
}
# Test success
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_SSDP},
@ -128,6 +129,82 @@ async def test_ssdp(hass, mock_panel):
"port": 1234,
}
# Test abort if connection failed
mock_panel.get_status.side_effect = config_flow.CannotConnect
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_SSDP},
data={
"ssdp_location": "http://1.2.3.4:1234/Device.xml",
"manufacturer": config_flow.KONN_MANUFACTURER,
"modelName": config_flow.KONN_MODEL,
},
)
assert result["type"] == "abort"
assert result["reason"] == "cannot_connect"
# Test abort if invalid data
mock_panel.get_status.side_effect = KeyError
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_SSDP},
data={
"ssdp_location": "http://1.2.3.4:1234/Device.xml",
},
)
assert result["type"] == "abort"
assert result["reason"] == "unknown"
# Test abort if invalid manufacturer
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_SSDP},
data={
"ssdp_location": "http://1.2.3.4:1234/Device.xml",
"manufacturer": "SHOULD_FAIL",
"modelName": config_flow.KONN_MODEL,
},
)
assert result["type"] == "abort"
assert result["reason"] == "not_konn_panel"
# Test abort if invalid model
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_SSDP},
data={
"ssdp_location": "http://1.2.3.4:1234/Device.xml",
"manufacturer": config_flow.KONN_MANUFACTURER,
"modelName": "SHOULD_FAIL",
},
)
assert result["type"] == "abort"
assert result["reason"] == "not_konn_panel"
# Test abort if already configured
config_entry = MockConfigEntry(
domain=config_flow.DOMAIN,
data={config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_PORT: 1234},
)
config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_SSDP},
data={
"ssdp_location": "http://1.2.3.4:1234/Device.xml",
"manufacturer": config_flow.KONN_MANUFACTURER,
"modelName": config_flow.KONN_MODEL,
},
)
assert result["type"] == "abort"
assert result["reason"] == "already_configured"
async def test_import_no_host_user_finish(hass, mock_panel):
"""Test importing a panel with no host info."""