Skip to content

Commit a490330

Browse files
committed
fix: Allow startup with unsupported devices
Raise and catch when finding an unsupported device. We will allow the device manager to continue with the devices that are supported, ignoring the ones that are not supoprted. We test with an unsupported protocol version but it also applies to unsupported q10 devices.
1 parent 4986727 commit a490330

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

roborock/devices/device_manager.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class DeviceVersion(enum.StrEnum):
5151
UNKNOWN = "unknown"
5252

5353

54+
class UnsupportedDeviceError(RoborockException):
55+
"""Exception raised when a device is unsupported."""
56+
57+
5458
class DeviceManager:
5559
"""Central manager for Roborock device discovery and connections."""
5660

@@ -95,11 +99,19 @@ async def discover_devices(self, prefer_cache: bool = True) -> list[RoborockDevi
9599
# These are connected serially to avoid overwhelming the MQTT broker
96100
new_devices = {}
97101
start_tasks = []
102+
supported_devices_counter = self._diagnostics.subkey("supported_devices")
103+
unsupported_devices_counter = self._diagnostics.subkey("unsupported_devices")
98104
for duid, (device, product) in device_products.items():
99105
_LOGGER.debug("[%s] Discovered device %s %s", duid, product.summary_info(), device.summary_info())
100106
if duid in self._devices:
101107
continue
102-
new_device = self._device_creator(home_data, device, product)
108+
try:
109+
new_device = self._device_creator(home_data, device, product)
110+
except UnsupportedDeviceError:
111+
_LOGGER.info("Skipping unsupported device %s %s", product.summary_info(), device.summary_info())
112+
unsupported_devices_counter.increment(device.pv)
113+
continue
114+
supported_devices_counter.increment(device.pv)
103115
start_tasks.append(new_device.start_connect())
104116
new_devices[duid] = new_device
105117

@@ -228,16 +240,16 @@ def device_creator(home_data: HomeData, device: HomeDataDevice, product: HomeDat
228240
channel = create_mqtt_channel(user_data, mqtt_params, mqtt_session, device)
229241
model_part = product.model.split(".")[-1]
230242
if "ss" in model_part:
231-
raise NotImplementedError(
243+
raise UnsupportedDeviceError(
232244
f"Device {device.name} has unsupported version B01_{product.model.strip('.')[-1]}"
233245
)
234246
elif "sc" in model_part:
235247
# Q7 devices start with 'sc' in their model naming.
236248
trait = b01.q7.create(channel)
237249
else:
238-
raise NotImplementedError(f"Device {device.name} has unsupported B01 model: {product.model}")
250+
raise UnsupportedDeviceError(f"Device {device.name} has unsupported B01 model: {product.model}")
239251
case _:
240-
raise NotImplementedError(f"Device {device.name} has unsupported version {device.pv}")
252+
raise UnsupportedDeviceError(f"Device {device.name} has unsupported version {device.pv}")
241253

242254
dev = RoborockDevice(device, product, channel, trait)
243255
if ready_callback:

tests/devices/test_device_manager.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pytest
1010

1111
from roborock.data import HomeData, UserData
12+
from roborock.data.containers import HomeDataDevice
1213
from roborock.devices.cache import InMemoryCache
1314
from roborock.devices.device import RoborockDevice
1415
from roborock.devices.device_manager import UserParams, create_device_manager, create_web_api_wrapper
@@ -362,3 +363,54 @@ async def test_diagnostics_collection(home_data: HomeData) -> None:
362363
assert diagnostics.get("fetch_home_data") == 1
363364

364365
await device_manager.close()
366+
367+
368+
async def test_unsupported_protocol_versio() -> None:
369+
"""Test the DeviceManager with some supported and unsupported product IDs."""
370+
with patch("roborock.devices.device_manager.UserWebApiClient.get_home_data") as mock_home_data:
371+
home_data = HomeData.from_dict({
372+
"id": 1,
373+
"name": "Test Home",
374+
"devices": [
375+
{
376+
"duid": "device-uid-1",
377+
"name": "Device 1",
378+
"pv": "1.0",
379+
"productId": "product-id-1",
380+
"localKey": mock_data.LOCAL_KEY,
381+
},
382+
{
383+
"duid": "device-uid-2",
384+
"name": "Device 2",
385+
"pv": "unknown-pv", # Fake new protocol version we've never seen
386+
"productId": "product-id-2",
387+
"localKey": mock_data.LOCAL_KEY,
388+
},
389+
],
390+
"products": [
391+
{
392+
"id": "product-id-1",
393+
"name": "Roborock S7 MaxV",
394+
"model": "roborock.vacuum.a27",
395+
"category": "robot.vacuum.cleaner",
396+
},
397+
{
398+
"id": "product-id-2",
399+
"name": "New Roborock Model",
400+
"model": "roborock.vacuum.newmodel",
401+
"category": "robot.vacuum.cleaner",
402+
},
403+
],
404+
})
405+
mock_home_data.return_value = home_data
406+
407+
device_manager = await create_device_manager(USER_PARAMS)
408+
409+
# Only the supported device should be created. The other device is ignored
410+
devices = await device_manager.get_devices()
411+
assert [device.duid for device in devices] == ["device-uid-1"]
412+
413+
# Verify diagnostics
414+
data = device_manager.diagnostic_data()
415+
assert data.get("supported_devices") == {"1.0": 1}
416+
assert data.get("unsupported_devices") == {"unknown-pv": 1}

0 commit comments

Comments
 (0)