Skip to content

Commit 19c6ec6

Browse files
committed
chore: Hook up the trait to the device and CLI
1 parent 13a1c0a commit 19c6ec6

File tree

6 files changed

+61
-4
lines changed

6 files changed

+61
-4
lines changed

roborock/cli.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
from pyshark.packet.packet import Packet # type: ignore
4343

4444
from roborock import SHORT_MODEL_TO_ENUM, DeviceFeatures, RoborockCommand, RoborockException
45-
from roborock.containers import DeviceData, HomeData, NetworkInfo, RoborockBase, UserData
45+
from roborock.containers import CombinedMapInfo, DeviceData, HomeData, NetworkInfo, RoborockBase, UserData
4646
from roborock.devices.cache import Cache, CacheData
4747
from roborock.devices.device import RoborockDevice
4848
from roborock.devices.device_manager import DeviceManager, create_device_manager, create_home_data_api
@@ -116,6 +116,7 @@ class ConnectionCache(RoborockBase):
116116
email: str
117117
home_data: HomeData | None = None
118118
network_info: dict[str, NetworkInfo] | None = None
119+
home_cache: dict[int, CombinedMapInfo] | None = None
119120

120121

121122
class DeviceConnectionManager:
@@ -258,14 +259,21 @@ def finish_session(self) -> None:
258259

259260
async def get(self) -> CacheData:
260261
"""Get cached value."""
262+
_LOGGER.debug("Getting cache data")
261263
connection_cache = self.cache_data()
262-
return CacheData(home_data=connection_cache.home_data, network_info=connection_cache.network_info or {})
264+
return CacheData(
265+
home_data=connection_cache.home_data,
266+
network_info=connection_cache.network_info or {},
267+
home_cache=connection_cache.home_cache,
268+
)
263269

264270
async def set(self, value: CacheData) -> None:
265271
"""Set value in the cache."""
272+
_LOGGER.debug("Setting cache data")
266273
connection_cache = self.cache_data()
267274
connection_cache.home_data = value.home_data
268275
connection_cache.network_info = value.network_info
276+
connection_cache.home_cache = value.home_cache
269277
self.update(connection_cache)
270278

271279

@@ -533,6 +541,42 @@ async def rooms(ctx, device_id: str):
533541
await _display_v1_trait(context, device_id, lambda v1: v1.rooms)
534542

535543

544+
@session.command()
545+
@click.option("--device_id", required=True)
546+
@click.option("--refresh", is_flag=True, default=False, help="Refresh status before discovery.")
547+
@click.pass_context
548+
@async_command
549+
async def home(ctx, device_id: str, refresh: bool):
550+
"""Discover and cache home layout (maps and rooms)."""
551+
context: RoborockContext = ctx.obj
552+
device_manager = await context.get_device_manager()
553+
device = await device_manager.get_device(device_id)
554+
if device.v1_properties is None:
555+
raise RoborockException(f"Device {device.name} does not support V1 protocol")
556+
557+
# Ensure we have the latest status before discovery
558+
await device.v1_properties.status.refresh()
559+
560+
home_trait = device.v1_properties.home
561+
await home_trait.discover_home()
562+
if refresh:
563+
await home_trait.refresh()
564+
565+
# Display the discovered home cache
566+
if home_trait.home_cache:
567+
cache_summary = {
568+
map_flag: {
569+
"name": map_data.name,
570+
"room_count": len(map_data.rooms),
571+
"rooms": [{"segment_id": room.segment_id, "name": room.name} for room in map_data.rooms],
572+
}
573+
for map_flag, map_data in home_trait.home_cache.items()
574+
}
575+
click.echo(dump_json(cache_summary))
576+
else:
577+
click.echo("No maps discovered")
578+
579+
536580
@click.command()
537581
@click.option("--device_id", required=True)
538582
@click.option("--cmd", required=True)
@@ -780,6 +824,7 @@ def write_markdown_table(product_features: dict[str, dict[str, any]], all_featur
780824
cli.add_command(consumables)
781825
cli.add_command(reset_consumable)
782826
cli.add_command(rooms)
827+
cli.add_command(home)
783828

784829

785830
def main():

roborock/devices/device_manager.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ def device_creator(home_data: HomeData, device: HomeDataDevice, product: HomeDat
157157
channel.rpc_channel,
158158
channel.mqtt_rpc_channel,
159159
channel.map_rpc_channel,
160+
cache,
160161
map_parser_config=map_parser_config,
161162
)
162163
case DeviceVersion.A01:

roborock/devices/traits/v1/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from dataclasses import dataclass, field, fields
55

66
from roborock.containers import HomeData, HomeDataProduct
7+
from roborock.devices.cache import Cache
78
from roborock.devices.traits import Trait
89
from roborock.devices.v1_rpc_channel import V1RpcChannel
910
from roborock.map.map_parser import MapParserConfig
@@ -12,6 +13,7 @@
1213
from .common import V1TraitMixin
1314
from .consumeable import ConsumableTrait
1415
from .do_not_disturb import DoNotDisturbTrait
16+
from .home import HomeTrait
1517
from .map_content import MapContentTrait
1618
from .maps import MapsTrait
1719
from .rooms import RoomsTrait
@@ -30,6 +32,7 @@
3032
"MapsTrait",
3133
"MapContentTrait",
3234
"ConsumableTrait",
35+
"HomeTrait",
3336
]
3437

3538

@@ -49,6 +52,7 @@ class PropertiesApi(Trait):
4952
maps: MapsTrait
5053
map_content: MapContentTrait
5154
consumables: ConsumableTrait
55+
home: HomeTrait
5256

5357
# In the future optional fields can be added below based on supported features
5458

@@ -59,13 +63,15 @@ def __init__(
5963
rpc_channel: V1RpcChannel,
6064
mqtt_rpc_channel: V1RpcChannel,
6165
map_rpc_channel: V1RpcChannel,
66+
cache: Cache,
6267
map_parser_config: MapParserConfig | None = None,
6368
) -> None:
6469
"""Initialize the V1TraitProps."""
6570
self.status = StatusTrait(product)
6671
self.rooms = RoomsTrait(home_data)
6772
self.maps = MapsTrait(self.status)
6873
self.map_content = MapContentTrait(map_parser_config)
74+
self.home = HomeTrait(self.maps, self.rooms, cache)
6975
# This is a hack to allow setting the rpc_channel on all traits. This is
7076
# used so we can preserve the dataclass behavior when the values in the
7177
# traits are updated, but still want to allow them to have a reference
@@ -90,7 +96,8 @@ def create(
9096
rpc_channel: V1RpcChannel,
9197
mqtt_rpc_channel: V1RpcChannel,
9298
map_rpc_channel: V1RpcChannel,
99+
cache: Cache,
93100
map_parser_config: MapParserConfig | None = None,
94101
) -> PropertiesApi:
95102
"""Create traits for V1 devices."""
96-
return PropertiesApi(product, home_data, rpc_channel, mqtt_rpc_channel, map_rpc_channel, map_parser_config)
103+
return PropertiesApi(product, home_data, rpc_channel, mqtt_rpc_channel, map_rpc_channel, cache, map_parser_config)

roborock/devices/traits/v1/home.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ async def discover_home(self) -> None:
7070
raise RoborockException("Cannot perform home discovery without current map info")
7171

7272
home_cache = await self._build_home_cache()
73+
_LOGGER.debug("Home discovery complete, caching data for %d maps", len(home_cache))
7374
cache_data = await self._cache.get()
7475
cache_data.home_cache = home_cache
7576
await self._cache.set(cache_data)

tests/devices/test_v1_device.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from syrupy import SnapshotAssertion
99

1010
from roborock.containers import HomeData, S7MaxVStatus, UserData
11+
from roborock.devices.cache import NoCache
1112
from roborock.devices.device import RoborockDevice
1213
from roborock.devices.traits import v1
1314
from roborock.devices.traits.v1.common import V1TraitMixin
@@ -53,7 +54,7 @@ def device_fixture(channel: AsyncMock, rpc_channel: AsyncMock, mqtt_rpc_channel:
5354
return RoborockDevice(
5455
device_info=HOME_DATA.devices[0],
5556
channel=channel,
56-
trait=v1.create(HOME_DATA.products[0], HOME_DATA, rpc_channel, mqtt_rpc_channel, map_rpc_channel=AsyncMock()),
57+
trait=v1.create(HOME_DATA.products[0], HOME_DATA, rpc_channel, mqtt_rpc_channel, AsyncMock(), NoCache()),
5758
)
5859

5960

tests/devices/traits/v1/fixtures.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pytest
66

77
from roborock.containers import HomeData, S7MaxVStatus, UserData
8+
from roborock.devices.cache import NoCache
89
from roborock.devices.device import RoborockDevice
910
from roborock.devices.traits import v1
1011

@@ -53,5 +54,6 @@ def device_fixture(
5354
mock_rpc_channel,
5455
mock_mqtt_rpc_channel,
5556
mock_map_rpc_channel,
57+
NoCache(),
5658
),
5759
)

0 commit comments

Comments
 (0)