core: Xiaomi miio integration does not show vacuum device

The problem

After core update, my vacuum Xiaomi 1s stopped working. There was already some updated done, but no change on my side. I’m able to add a vacuum to integration but there is no device created or entity.

image

What version of Home Assistant Core has the issue?

core-2021.11.1

What was the last working version of Home Assistant Core?

core-2021.10

What type of installation are you running?

Home Assistant OS

Integration causing the issue

Xiaomi Miio

Link to integration documentation on our website

https://www.home-assistant.io/integrations/xiaomi_miio

Example YAML snippet

No response

Anything in the logs that might be useful for us?

Logger: homeassistant.components.vacuum
Source: components/xiaomi_miio/vacuum.py:110
Integration: Odkurzacz (documentation, issues)
First occurred: 18:49:10 (1 occurrences)
Last logged: 18:49:10

Error while setting up xiaomi_miio platform for vacuum
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 249, in _async_setup_platform
    await asyncio.shield(task)
  File "/usr/src/homeassistant/homeassistant/components/xiaomi_miio/vacuum.py", line 110, in async_setup_entry
    hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE],
KeyError: 'e3d3933b148754a47f294e07392c7947'

Additional information

No response

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 9
  • Comments: 44 (14 by maintainers)

Most upvoted comments

As the issue is being fixed in the linked PR (thanks @OGKevin!), I want to give you some context with my maintainer hat on.

In the previous releases, avoiding strict model checks was a knowingly made choice to allow any upcoming but yet unknown vacuums to function without further changes. As roborock is still actively releasing new devices to the market that still use the same base functions, maintaining a list of models that are allowed to function wasn’t really an attractive idea.

Anyway, looks like this principle got lost when the integration got converted to use separate sensors, and I’m to blame for not spotting it happening. The reason for the weird errors listed in this issue and its dupes (instead of more clear “device not supported”) was also my fault when I created #59018 while being oblivious that it’d require more changes to support “unsupported devices”.

Going forward, we should not perform strict checks on the platform level based on the model information, but rather whitelist any extra functionality based on it. This way the base functionality should remain always accessible, and any new features can be added on those models that known to support them.

I started with a solution but I have not time to finish it atm, will continue later or tomorrow.

diff --git a/homeassistant/components/xiaomi_miio/__init__.py b/homeassistant/components/xiaomi_miio/__init__.py
index 5513485f51..e43ef263d9 100644
--- a/homeassistant/components/xiaomi_miio/__init__.py
+++ b/homeassistant/components/xiaomi_miio/__init__.py
@@ -66,6 +66,7 @@ from .const import (
     MODELS_PURIFIER_MIOT,
     MODELS_SWITCH,
     MODELS_VACUUM,
+    ROCKROBO_GENERIC,
     AuthException,
     SetupException,
 )
@@ -279,8 +280,12 @@ async def async_create_miio_device_and_coordinator(
     if (
         model not in MODELS_HUMIDIFIER
         and model not in MODELS_FAN
-        and model not in MODELS_VACUUM
-    ):
+    ) and (
+        (model not in MODELS_VACUUM) == (not model.startswith(ROCKROBO_GENERIC))):
+        # PASS True False --> False: not in model, start with generic
+        # FAIL True True -->  True: not in model, not start with generic --> This needs to fail but it passes, True AND True end result
+        # PASS False, False --> True: in model, start with generic --> This needs to pass but fails True AND True end result.
+        # PASS False, True --> False: in model, not start with generic
         return
 
     _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5])
@@ -304,7 +309,15 @@ async def async_create_miio_device_and_coordinator(
         device = AirPurifier(host, token)
     elif model.startswith("zhimi.airfresh."):
         device = AirFresh(host, token)
-    elif model in MODELS_VACUUM:
+    elif model in MODELS_VACUUM or model.startswith(ROCKROBO_GENERIC):
+        if model.startswith(ROCKROBO_GENERIC):
+            _LOGGER.warning(
+                "Vacuum model %s is not officially supported, please create an issue at "
+                "https://github.com/rytilahti/python-miio/issues and provide the model name if it works as "
+                "expected.",
+                model,
+            )
+
         device = Vacuum(host, token)
         update_method = _async_update_data_vacuum
         coordinator_class = DataUpdateCoordinator[VacuumCoordinatorData]
diff --git a/homeassistant/components/xiaomi_miio/const.py b/homeassistant/components/xiaomi_miio/const.py
index 60c16a0717..3e43eed573 100644
--- a/homeassistant/components/xiaomi_miio/const.py
+++ b/homeassistant/components/xiaomi_miio/const.py
@@ -213,7 +213,7 @@ MODELS_VACUUM = [
     ROCKROBO_S6,
     ROCKROBO_S6_MAXV,
     ROCKROBO_S6_PURE,
-    ROCKROBO_S7,
+    # ROCKROBO_S7,
     ROCKROBO_GENERIC,
 ]
 MODELS_VACUUM_WITH_MOP = [

But basically, this is a condition where the vacuum has already been setup but its model is not supported so the coordinator does not get created, so this if statement needs to be adjusted to allow creation of the coordinator somehow. This was my first thought but I need a lil more time to come with a proper bool expression as it turns out its not that simple 😄. Or gotta take a diff approach. But either way, my suspicion is correct.

Was able to reproduce by removing my model from the list and then start HA.

I do not understand what’s going on? Why until 2021.11 a lot of vacuum cleaners were supported and worked great, but now some unsupported models appear? None of this looks like product improvements…

The code for vacuum was made a little more strict when it comes to supported models. As the code for vacuums in one point was doing a strict check and in another place a more loose/generic check. Both me and one of the maintainers were not sure why it was like this and it has been changed to strict in all places. As with the introduction of the sensors, we need to know which model supports which sensors so that only the needed sensors are created. Hence, all places for vacuum now does a strict check.

https://github.com/home-assistant/core/pull/54990#discussion_r693467738

It was not clear for me nor for the maintainers that:

  1. there are so many supported devices that have never been marked as supported
  2. folks using “unsupported” devices under a different model name instead of reporting it as supported.

This issue makes it clear on why one of the checks was generic. So, I will add it back in a PR with a warning asking folks to report it so that all sensors are created accordingly.

@bieniu I think its just this again: https://github.com/home-assistant/core/issues/58550#issuecomment-953642020

Hence my thought that its due to unsupported models and the coordinator not being created as the model is not in the list. The reported models are indeed not in the list.

I’ll create a PR that assumes all vacuums are vacuums that support the basic vacuum sensors and emit a warning that its not listed as officially supported.

Same here, there is not a vacum entity

For all having this problem, I temporary switch to https://github.com/al-one/hass-xiaomi-miot - there vacum works fine there!

@alting @basdejong95 @vicfergar

xiaomi mijia 1s vacuum MODEL: roborock.vacuum.m1s

Upgraded and all working now.

Thank you maintenance team.

Same issue (Mijia s1)