From 1c9a9be197dae67f0428d2599fa47f882cc5ef81 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sun, 28 Feb 2021 21:25:40 +0100 Subject: [PATCH] Fix Xiaomi Miio discovery (#47134) --- .../components/xiaomi_miio/config_flow.py | 17 +++++++---- .../components/xiaomi_miio/strings.json | 28 +++++++++---------- .../xiaomi_miio/test_config_flow.py | 14 ++++------ 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/xiaomi_miio/config_flow.py b/homeassistant/components/xiaomi_miio/config_flow.py index c9c363b61eb..9eaf4c1effa 100644 --- a/homeassistant/components/xiaomi_miio/config_flow.py +++ b/homeassistant/components/xiaomi_miio/config_flow.py @@ -1,5 +1,6 @@ """Config flow to configure Xiaomi Miio.""" import logging +from re import search import voluptuous as vol @@ -24,7 +25,6 @@ from .device import ConnectXiaomiDevice _LOGGER = logging.getLogger(__name__) DEFAULT_GATEWAY_NAME = "Xiaomi Gateway" -DEFAULT_DEVICE_NAME = "Xiaomi Device" DEVICE_SETTINGS = { vol.Required(CONF_TOKEN): vol.All(str, vol.Length(min=32, max=32)), @@ -57,14 +57,21 @@ class XiaomiMiioFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): name = discovery_info.get("name") self.host = discovery_info.get("host") self.mac = discovery_info.get("properties", {}).get("mac") + if self.mac is None: + poch = discovery_info.get("properties", {}).get("poch", "") + result = search(r"mac=\w+", poch) + if result is not None: + self.mac = result.group(0).split("=")[1] if not name or not self.host or not self.mac: return self.async_abort(reason="not_xiaomi_miio") + self.mac = format_mac(self.mac) + # Check which device is discovered. for gateway_model in MODELS_GATEWAY: if name.startswith(gateway_model.replace(".", "-")): - unique_id = format_mac(self.mac) + unique_id = self.mac await self.async_set_unique_id(unique_id) self._abort_if_unique_id_configured({CONF_HOST: self.host}) @@ -76,12 +83,12 @@ class XiaomiMiioFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): for device_model in MODELS_ALL_DEVICES: if name.startswith(device_model.replace(".", "-")): - unique_id = format_mac(self.mac) + unique_id = self.mac await self.async_set_unique_id(unique_id) self._abort_if_unique_id_configured({CONF_HOST: self.host}) self.context.update( - {"title_placeholders": {"name": f"Miio Device {self.host}"}} + {"title_placeholders": {"name": f"{device_model} {self.host}"}} ) return await self.async_step_device() @@ -133,7 +140,7 @@ class XiaomiMiioFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): ) # Setup all other Miio Devices - name = user_input.get(CONF_NAME, DEFAULT_DEVICE_NAME) + name = user_input.get(CONF_NAME, model) for device_model in MODELS_ALL_DEVICES: if model.startswith(device_model): diff --git a/homeassistant/components/xiaomi_miio/strings.json b/homeassistant/components/xiaomi_miio/strings.json index 90710baebca..e3d9376bc31 100644 --- a/homeassistant/components/xiaomi_miio/strings.json +++ b/homeassistant/components/xiaomi_miio/strings.json @@ -1,24 +1,24 @@ { "config": { - "flow_title": "Xiaomi Miio: {name}", - "step": { - "device": { - "title": "Connect to a Xiaomi Miio Device or Xiaomi Gateway", - "description": "You will need the 32 character [%key:common::config_flow::data::api_token%], see https://www.home-assistant.io/integrations/vacuum.xiaomi_miio/#retrieving-the-access-token for instructions. Please note, that this [%key:common::config_flow::data::api_token%] is different from the key used by the Xiaomi Aqara integration.", - "data": { - "host": "[%key:common::config_flow::data::ip%]", - "token": "[%key:common::config_flow::data::api_token%]", - "model": "Device model (Optional)" - } - } + "abort": { + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", + "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]" }, "error": { "cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", "unknown_device": "The device model is not known, not able to setup the device using config flow." }, - "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", - "already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]" + "flow_title": "Xiaomi Miio: {name}", + "step": { + "device": { + "data": { + "host": "[%key:common::config_flow::data::ip%]", + "model": "Device model (Optional)", + "token": "[%key:common::config_flow::data::api_token%]" + }, + "description": "You will need the 32 character [%key:common::config_flow::data::api_token%], see https://www.home-assistant.io/integrations/xiaomi_miio#retrieving-the-access-token for instructions. Please note, that this [%key:common::config_flow::data::api_token%] is different from the key used by the Xiaomi Aqara integration.", + "title": "Connect to a Xiaomi Miio Device or Xiaomi Gateway" + } } } } diff --git a/tests/components/xiaomi_miio/test_config_flow.py b/tests/components/xiaomi_miio/test_config_flow.py index f4f7b5e2b46..f53fe6e40b4 100644 --- a/tests/components/xiaomi_miio/test_config_flow.py +++ b/tests/components/xiaomi_miio/test_config_flow.py @@ -6,10 +6,7 @@ from miio import DeviceException from homeassistant import config_entries from homeassistant.components import zeroconf from homeassistant.components.xiaomi_miio import const -from homeassistant.components.xiaomi_miio.config_flow import ( - DEFAULT_DEVICE_NAME, - DEFAULT_GATEWAY_NAME, -) +from homeassistant.components.xiaomi_miio.config_flow import DEFAULT_GATEWAY_NAME from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TOKEN ZEROCONF_NAME = "name" @@ -21,6 +18,7 @@ TEST_TOKEN = "12345678901234567890123456789012" TEST_NAME = "Test_Gateway" TEST_MODEL = const.MODELS_GATEWAY[0] TEST_MAC = "ab:cd:ef:gh:ij:kl" +TEST_MAC_DEVICE = "abcdefghijkl" TEST_GATEWAY_ID = TEST_MAC TEST_HARDWARE_VERSION = "AB123" TEST_FIRMWARE_VERSION = "1.2.3_456" @@ -294,7 +292,7 @@ async def test_config_flow_step_device_manual_model_succes(hass): ) assert result["type"] == "create_entry" - assert result["title"] == DEFAULT_DEVICE_NAME + assert result["title"] == overwrite_model assert result["data"] == { const.CONF_FLOW_TYPE: const.CONF_DEVICE, CONF_HOST: TEST_HOST, @@ -328,7 +326,7 @@ async def config_flow_device_success(hass, model_to_test): ) assert result["type"] == "create_entry" - assert result["title"] == DEFAULT_DEVICE_NAME + assert result["title"] == model_to_test assert result["data"] == { const.CONF_FLOW_TYPE: const.CONF_DEVICE, CONF_HOST: TEST_HOST, @@ -346,7 +344,7 @@ async def zeroconf_device_success(hass, zeroconf_name_to_test, model_to_test): data={ zeroconf.ATTR_HOST: TEST_HOST, ZEROCONF_NAME: zeroconf_name_to_test, - ZEROCONF_PROP: {ZEROCONF_MAC: TEST_MAC}, + ZEROCONF_PROP: {"poch": f"0:mac={TEST_MAC_DEVICE}\x00"}, }, ) @@ -368,7 +366,7 @@ async def zeroconf_device_success(hass, zeroconf_name_to_test, model_to_test): ) assert result["type"] == "create_entry" - assert result["title"] == DEFAULT_DEVICE_NAME + assert result["title"] == model_to_test assert result["data"] == { const.CONF_FLOW_TYPE: const.CONF_DEVICE, CONF_HOST: TEST_HOST,