Huawei LTE SSDP improvements (#81643)

* Recognize more SSDP friendly names as "ours"

* Trigger on SoyeaLink devices

* Pass discovered URL through context, it does not persist via user_input

* Use manufacturer from SSDP

* Actually use serial number if available, update URL for configured

* Remove heuristic friendly name filtering against non-LTE devices
This commit is contained in:
Ville Skyttä 2022-12-15 00:48:25 +02:00 committed by GitHub
parent 9a25e75947
commit f02b6f1119
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 44 additions and 34 deletions

View file

@ -56,9 +56,11 @@ from .const import (
ADMIN_SERVICES,
ALL_KEYS,
ATTR_UNIQUE_ID,
CONF_MANUFACTURER,
CONF_UNAUTHENTICATED_MODE,
CONNECTION_TIMEOUT,
DEFAULT_DEVICE_NAME,
DEFAULT_MANUFACTURER,
DEFAULT_NOTIFY_SERVICE_NAME,
DOMAIN,
KEY_DEVICE_BASIC_INFORMATION,
@ -412,9 +414,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
device_info = DeviceInfo(
configuration_url=router.url,
connections=router.device_connections,
default_manufacturer=DEFAULT_MANUFACTURER,
identifiers=router.device_identifiers,
manufacturer=entry.data.get(CONF_MANUFACTURER),
name=router.device_name,
manufacturer="Huawei",
)
hw_version = None
sw_version = None

View file

@ -34,6 +34,7 @@ from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from .const import (
CONF_MANUFACTURER,
CONF_TRACK_WIRED_CLIENTS,
CONF_UNAUTHENTICATED_MODE,
CONNECTION_TIMEOUT,
@ -208,7 +209,12 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
)
await self.hass.async_add_executor_job(self._logout, conn)
user_input[CONF_MAC] = get_device_macs(info, wlan_settings)
user_input.update(
{
CONF_MAC: get_device_macs(info, wlan_settings),
CONF_MANUFACTURER: self.context.get(CONF_MANUFACTURER),
}
)
if not self.unique_id:
if serial_number := info.get("SerialNumber"):
@ -228,16 +234,6 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_ssdp(self, discovery_info: ssdp.SsdpServiceInfo) -> FlowResult:
"""Handle SSDP initiated config flow."""
await self.async_set_unique_id(discovery_info.upnp[ssdp.ATTR_UPNP_UDN])
self._abort_if_unique_id_configured()
# Attempt to distinguish from other non-LTE Huawei router devices, at least
# some ones we are interested in have "Mobile Wi-Fi" friendlyName.
if (
"mobile"
not in discovery_info.upnp.get(ssdp.ATTR_UPNP_FRIENDLY_NAME, "").lower()
):
return self.async_abort(reason="not_huawei_lte")
if TYPE_CHECKING:
assert discovery_info.ssdp_location
@ -248,18 +244,22 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
)
)
if serial_number := discovery_info.upnp.get(ssdp.ATTR_UPNP_SERIAL):
await self.async_set_unique_id(serial_number)
self._abort_if_unique_id_configured()
else:
await self._async_handle_discovery_without_unique_id()
unique_id = discovery_info.upnp.get(
ssdp.ATTR_UPNP_SERIAL, discovery_info.upnp[ssdp.ATTR_UPNP_UDN]
)
await self.async_set_unique_id(unique_id)
self._abort_if_unique_id_configured(updates={CONF_URL: url})
user_input = {CONF_URL: url}
self.context["title_placeholders"] = {
CONF_NAME: discovery_info.upnp.get(ssdp.ATTR_UPNP_FRIENDLY_NAME)
}
return await self._async_show_user_form(user_input)
self.context.update(
{
"title_placeholders": {
CONF_NAME: discovery_info.upnp.get(ssdp.ATTR_UPNP_FRIENDLY_NAME)
},
CONF_MANUFACTURER: discovery_info.upnp.get(ssdp.ATTR_UPNP_MANUFACTURER),
CONF_URL: url,
}
)
return await self._async_show_user_form()
async def async_step_reauth(self, entry_data: Mapping[str, Any]) -> FlowResult:
"""Perform reauth upon an API authentication error."""

View file

@ -4,10 +4,12 @@ DOMAIN = "huawei_lte"
ATTR_UNIQUE_ID = "unique_id"
CONF_MANUFACTURER = "manufacturer"
CONF_TRACK_WIRED_CLIENTS = "track_wired_clients"
CONF_UNAUTHENTICATED_MODE = "unauthenticated_mode"
DEFAULT_DEVICE_NAME = "LTE"
DEFAULT_MANUFACTURER = "Huawei Technologies Co., Ltd."
DEFAULT_NOTIFY_SERVICE_NAME = DOMAIN
DEFAULT_TRACK_WIRED_CLIENTS = True
DEFAULT_UNAUTHENTICATED_MODE = False

View file

@ -12,6 +12,14 @@
{
"deviceType": "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"manufacturer": "Huawei"
},
{
"deviceType": "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"manufacturer": "Huawei Technologies Co., Ltd."
},
{
"deviceType": "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"manufacturer": "SOYEA TECHNOLOGY CO., LTD."
}
],
"codeowners": ["@scop", "@fphammerle"],

View file

@ -1,7 +1,6 @@
{
"config": {
"abort": {
"not_huawei_lte": "Not a Huawei LTE device",
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
},
"error": {

View file

@ -1,7 +1,6 @@
{
"config": {
"abort": {
"not_huawei_lte": "Not a Huawei LTE device",
"reauth_successful": "Re-authentication was successful"
},
"error": {

View file

@ -146,6 +146,14 @@ SSDP = {
"deviceType": "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"manufacturer": "Huawei",
},
{
"deviceType": "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"manufacturer": "Huawei Technologies Co., Ltd.",
},
{
"deviceType": "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
"manufacturer": "SOYEA TECHNOLOGY CO., LTD.",
},
],
"hue": [
{

View file

@ -235,15 +235,6 @@ async def test_success(hass, login_requests_mock):
"errors": {},
},
),
(
{
ssdp.ATTR_UPNP_FRIENDLY_NAME: "Some other device",
},
{
"type": data_entry_flow.FlowResultType.ABORT,
"reason": "not_huawei_lte",
},
),
),
)
async def test_ssdp(hass, upnp_data, expected_result):