From 6bbe477d662dd71b064d98aabc0db2438dcc06f5 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 25 Jun 2021 21:25:51 +0200 Subject: [PATCH] Improve Xiaomi Miio error handling (#52009) * Xiaomi Miio inprove error logging * improve error handeling * fix styling * fix styling * Update homeassistant/components/xiaomi_miio/device.py Co-authored-by: Martin Hjelmare * Update homeassistant/components/xiaomi_miio/gateway.py Co-authored-by: Martin Hjelmare * Update homeassistant/components/xiaomi_miio/gateway.py Co-authored-by: Martin Hjelmare * break long line * Clean up Co-authored-by: Martin Hjelmare --- .../components/xiaomi_miio/device.py | 13 +++- .../components/xiaomi_miio/gateway.py | 65 +++++++++++++------ 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/xiaomi_miio/device.py b/homeassistant/components/xiaomi_miio/device.py index cb91726ecad..081b910efdb 100644 --- a/homeassistant/components/xiaomi_miio/device.py +++ b/homeassistant/components/xiaomi_miio/device.py @@ -1,8 +1,10 @@ """Code to handle a Xiaomi Device.""" import logging +from construct.core import ChecksumError from miio import Device, DeviceException +from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.helpers import device_registry as dr from homeassistant.helpers.entity import Entity @@ -33,17 +35,24 @@ class ConnectXiaomiDevice: async def async_connect_device(self, host, token): """Connect to the Xiaomi Device.""" _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) + try: self._device = Device(host, token) # get the device info self._device_info = await self._hass.async_add_executor_job( self._device.info ) - except DeviceException: + except DeviceException as error: + if isinstance(error.__cause__, ChecksumError): + raise ConfigEntryAuthFailed(error) from error + _LOGGER.error( - "DeviceException during setup of xiaomi device with host %s", host + "DeviceException during setup of xiaomi device with host %s: %s", + host, + error, ) return False + _LOGGER.debug( "%s %s %s detected", self._device_info.model, diff --git a/homeassistant/components/xiaomi_miio/gateway.py b/homeassistant/components/xiaomi_miio/gateway.py index 7dd84cf7812..17f42f4bffa 100644 --- a/homeassistant/components/xiaomi_miio/gateway.py +++ b/homeassistant/components/xiaomi_miio/gateway.py @@ -1,6 +1,7 @@ """Code to handle a Xiaomi Gateway.""" import logging +from construct.core import ChecksumError from micloud import MiCloud from miio import DeviceException, gateway from miio.gateway.gateway import GATEWAY_MODEL_EU @@ -75,19 +76,44 @@ class ConnectXiaomiGateway: self._gateway_device = gateway.Gateway(self._host, self._token) # get the gateway info self._gateway_info = self._gateway_device.info() + except DeviceException as error: + if isinstance(error.__cause__, ChecksumError): + raise ConfigEntryAuthFailed(error) from error - # get the connected sub devices - if self._use_cloud or self._gateway_info.model == GATEWAY_MODEL_EU: - if ( - self._cloud_username is None - or self._cloud_password is None - or self._cloud_country is None - ): - raise ConfigEntryAuthFailed( - "Missing cloud credentials in Xiaomi Miio configuration" - ) + _LOGGER.error( + "DeviceException during setup of xiaomi gateway with host %s: %s", + self._host, + error, + ) + return False - # use miio-cloud + # get the connected sub devices + use_cloud = self._use_cloud or self._gateway_info.model == GATEWAY_MODEL_EU + if not use_cloud: + # use local query (not supported by all gateway types) + try: + self._gateway_device.discover_devices() + except DeviceException as error: + _LOGGER.info( + "DeviceException during getting subdevices of xiaomi gateway" + " with host %s, trying cloud to obtain subdevices: %s", + self._host, + error, + ) + use_cloud = True + + if use_cloud: + # use miio-cloud + if ( + self._cloud_username is None + or self._cloud_password is None + or self._cloud_country is None + ): + raise ConfigEntryAuthFailed( + "Missing cloud credentials in Xiaomi Miio configuration" + ) + + try: miio_cloud = MiCloud(self._cloud_username, self._cloud_password) if not miio_cloud.login(): raise ConfigEntryAuthFailed( @@ -95,16 +121,13 @@ class ConnectXiaomiGateway: ) devices_raw = miio_cloud.get_devices(self._cloud_country) self._gateway_device.get_devices_from_dict(devices_raw) - else: - # use local query (not supported by all gateway types) - self._gateway_device.discover_devices() - - except DeviceException: - _LOGGER.error( - "DeviceException during setup of xiaomi gateway with host %s", - self._host, - ) - return False + except DeviceException as error: + _LOGGER.error( + "DeviceException during setup of xiaomi gateway with host %s: %s", + self._host, + error, + ) + return False return True