python-roborock 7.4.3__tar.gz → 7.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_roborock-7.4.3 → python_roborock-7.6.0}/PKG-INFO +1 -1
- {python_roborock-7.4.3 → python_roborock-7.6.0}/pyproject.toml +1 -1
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q7/__init__.py +10 -0
- python_roborock-7.6.0/roborock/map/b01_map_parser.py +383 -0
- python_roborock-7.6.0/roborock/map/proto/b01_scmap.proto +151 -0
- python_roborock-7.6.0/roborock/map/proto/b01_scmap_pb2.py +72 -0
- python_roborock-7.4.3/roborock/map/b01_map_parser.py +0 -133
- python_roborock-7.4.3/roborock/map/proto/b01_scmap.proto +0 -70
- python_roborock-7.4.3/roborock/map/proto/b01_scmap_pb2.py +0 -48
- {python_roborock-7.4.3 → python_roborock-7.6.0}/.gitignore +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/LICENSE +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/README.md +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/broadcast_protocol.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/callbacks.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/cli.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/const.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/b01_q10/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/b01_q7/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/code_mappings.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/containers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/dyad/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/dyad/dyad_containers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/mower/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/mower/mower_code_mappings.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/mower/mower_containers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/v1/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/v1/v1_clean_modes.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/v1/v1_code_mappings.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/v1/v1_containers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/zeo/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/data/zeo/zeo_containers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/device_features.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/README.md +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/cache.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/device.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/device_manager.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/file_cache.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/rpc/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/rpc/a01_channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/rpc/b01_q10_channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/rpc/b01_q7_channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/rpc/v1_channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/a01/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/a01/device_feature.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/button_light.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/child_lock.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/clean_history.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/command.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/common.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/consumable.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/do_not_disturb.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/dust_collection.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/map.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/maps.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/network_info.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/remote.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/status.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/vacuum.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q10/volume.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q7/clean_summary.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q7/map.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/b01/q7/map_content.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/common.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/traits_mixin.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/child_lock.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/command.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/common.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/consumeable.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/device_features.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/dust_collection_mode.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/home.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/led_status.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/map_content.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/maps.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/network_info.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/obstacle_photos.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/rooms.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/routines.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/smart_wash_params.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/status.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/volume.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/traits/v1/wash_towel_mode.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/transport/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/transport/channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/transport/local_channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/devices/transport/mqtt_channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/diagnostics.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/exceptions.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/b01_grid_layers.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/b01_q10_map_parser.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/b01_q10_overlays.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/b01_q10_render.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/map_parser.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/proto/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/map/room_colors.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/mqtt/health_manager.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/mqtt/roborock_session.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/mqtt/session.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/protocol.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/protocols/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/protocols/b01_q10_protocol.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/protocols/b01_q7_protocol.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/protocols/v1_protocol.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/py.typed +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/roborock_message.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/roborock_typing.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/testing/__init__.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/testing/a01_simulator.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/testing/b01_q10_simulator.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/testing/channel.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/testing/cloud.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/testing/simulator.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/testing/v1_simulator.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/util.py +0 -0
- {python_roborock-7.4.3 → python_roborock-7.6.0}/roborock/web_api.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: python-roborock
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.6.0
|
|
4
4
|
Summary: A package to control Roborock vacuums.
|
|
5
5
|
Project-URL: Repository, https://github.com/python-roborock/python-roborock
|
|
6
6
|
Project-URL: Documentation, https://python-roborock.readthedocs.io/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-roborock"
|
|
3
|
-
version = "7.
|
|
3
|
+
version = "7.6.0"
|
|
4
4
|
description = "A package to control Roborock vacuums."
|
|
5
5
|
authors = [{ name = "humbertogontijo", email = "humbertogontijo@users.noreply.github.com" }, {name="Lash-L"}, {name="allenporter"}]
|
|
6
6
|
requires-python = ">=3.11, <4"
|
|
@@ -131,6 +131,16 @@ class Q7PropertiesApi(Trait):
|
|
|
131
131
|
"""Enable or disable the child lock."""
|
|
132
132
|
await self.set_prop(RoborockB01Props.CHILD_LOCK, int(enabled))
|
|
133
133
|
|
|
134
|
+
async def set_dust_collection(self, enabled: bool) -> None:
|
|
135
|
+
"""Enable or disable automatic dust collection at the dock."""
|
|
136
|
+
await self.set_prop(RoborockB01Props.DUST_AUTO_STATE, int(enabled))
|
|
137
|
+
|
|
138
|
+
async def set_dust_collection_frequency(self, frequency: int) -> None:
|
|
139
|
+
"""Set how often the dock auto-empties, in cleans per emptying (1 = every clean)."""
|
|
140
|
+
if frequency < 1:
|
|
141
|
+
raise ValueError(f"frequency must be a positive number of cleans, got {frequency}")
|
|
142
|
+
await self.set_prop(RoborockB01Props.DUST_FREQUENCY, frequency)
|
|
143
|
+
|
|
134
144
|
async def set_do_not_disturb(self, enabled: bool, begin_time: int, end_time: int) -> None:
|
|
135
145
|
"""Configure do-not-disturb.
|
|
136
146
|
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
"""Module for parsing B01/Q7 map content.
|
|
2
|
+
|
|
3
|
+
The inner SCMap blob is parsed with protobuf messages generated from
|
|
4
|
+
`roborock/map/proto/b01_scmap.proto`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import io
|
|
8
|
+
import math
|
|
9
|
+
from collections import deque
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
from google.protobuf.message import DecodeError
|
|
13
|
+
from PIL import Image
|
|
14
|
+
from vacuum_map_parser_base.config.color import ColorsPalette, SupportedColor
|
|
15
|
+
from vacuum_map_parser_base.config.drawable import Drawable
|
|
16
|
+
from vacuum_map_parser_base.config.image_config import ImageConfig
|
|
17
|
+
from vacuum_map_parser_base.map_data import Area, ImageData, MapData, Path, Point, Room
|
|
18
|
+
|
|
19
|
+
from roborock.exceptions import RoborockException
|
|
20
|
+
from roborock.map.proto.b01_scmap_pb2 import RobotMap # type: ignore[attr-defined]
|
|
21
|
+
|
|
22
|
+
from .map_parser import MapParserConfig, ParsedMapData, _create_image_generator
|
|
23
|
+
from .room_colors import adjacency_aware_room_colors
|
|
24
|
+
|
|
25
|
+
_MAP_FILE_FORMAT = "PNG"
|
|
26
|
+
|
|
27
|
+
_FLOOR = 127
|
|
28
|
+
_WALL = 128
|
|
29
|
+
|
|
30
|
+
_B01_DRAWABLES = [
|
|
31
|
+
Drawable.CHARGER,
|
|
32
|
+
Drawable.NO_GO_AREAS,
|
|
33
|
+
Drawable.PATH,
|
|
34
|
+
Drawable.ROOM_NAMES,
|
|
35
|
+
Drawable.VACUUM_POSITION,
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class B01MapParserConfig:
|
|
41
|
+
"""Configuration for the B01/Q7 map parser."""
|
|
42
|
+
|
|
43
|
+
map_scale: int = 4
|
|
44
|
+
"""Scale factor for the rendered map image."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class B01MapParser:
|
|
48
|
+
"""Decoder/parser for B01/Q7 SCMap payloads."""
|
|
49
|
+
|
|
50
|
+
def __init__(self, config: B01MapParserConfig | None = None) -> None:
|
|
51
|
+
self._config = config or B01MapParserConfig()
|
|
52
|
+
|
|
53
|
+
def parse(self, payload: bytes) -> ParsedMapData:
|
|
54
|
+
"""Parse an inflated SCMap payload and return a PNG + MapData."""
|
|
55
|
+
parsed = _parse_scmap_payload(payload)
|
|
56
|
+
size_x, size_y, grid = _extract_grid(parsed)
|
|
57
|
+
room_names = _extract_room_names(parsed)
|
|
58
|
+
|
|
59
|
+
room_pixels = _assign_room_pixels(parsed, grid, size_x=size_x, size_y=size_y)
|
|
60
|
+
carpet_pixels = _carpet_pixel_indices(parsed, grid, size_x=size_x, size_y=size_y)
|
|
61
|
+
image = _render_occupancy_image(
|
|
62
|
+
grid, room_pixels, carpet_pixels, size_x=size_x, size_y=size_y, scale=self._config.map_scale
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
map_data = MapData()
|
|
66
|
+
map_data.image = ImageData(
|
|
67
|
+
size=size_x * size_y,
|
|
68
|
+
top=0,
|
|
69
|
+
left=0,
|
|
70
|
+
height=size_y,
|
|
71
|
+
width=size_x,
|
|
72
|
+
image_config=ImageConfig(scale=self._config.map_scale),
|
|
73
|
+
data=image,
|
|
74
|
+
# Overlay points are stored in the rendered image's top-down pixel
|
|
75
|
+
# space. ImageDimensions applies V1's bottom-up flip before drawing,
|
|
76
|
+
# so this adapter cancels it (same approach as the Q10 renderer).
|
|
77
|
+
img_transformation=lambda p: Point(p.x, size_y - p.y - 1, p.a),
|
|
78
|
+
)
|
|
79
|
+
if room_names:
|
|
80
|
+
map_data.additional_parameters["room_names"] = room_names
|
|
81
|
+
|
|
82
|
+
projector = _WorldToPixel(parsed)
|
|
83
|
+
has_drawables = _place_poses(map_data, parsed, projector)
|
|
84
|
+
map_data.rooms = _extract_rooms(parsed, projector, room_names)
|
|
85
|
+
has_drawables = has_drawables or bool(map_data.rooms)
|
|
86
|
+
if carpet_pixels:
|
|
87
|
+
# Same contract as the Q10 parser: flat top-down grid indices.
|
|
88
|
+
map_data.carpet_map = {(size_y - 1 - index // size_x) * size_x + index % size_x for index in carpet_pixels}
|
|
89
|
+
|
|
90
|
+
if has_drawables:
|
|
91
|
+
generator = _create_image_generator(
|
|
92
|
+
MapParserConfig(map_scale=self._config.map_scale),
|
|
93
|
+
drawables=_B01_DRAWABLES,
|
|
94
|
+
)
|
|
95
|
+
generator.draw_map(map_data)
|
|
96
|
+
image = map_data.image.data
|
|
97
|
+
|
|
98
|
+
image_bytes = io.BytesIO()
|
|
99
|
+
image.save(image_bytes, format=_MAP_FILE_FORMAT)
|
|
100
|
+
|
|
101
|
+
return ParsedMapData(
|
|
102
|
+
image_content=image_bytes.getvalue(),
|
|
103
|
+
map_data=map_data,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def parse_map_type(payload: bytes) -> int:
|
|
108
|
+
"""Return the SCMap frame's map type without rendering the image.
|
|
109
|
+
|
|
110
|
+
Type 0 is the live map of the current cleaning run, other types are
|
|
111
|
+
historic or saved maps.
|
|
112
|
+
"""
|
|
113
|
+
return _parse_scmap_payload(payload).mapType
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _parse_scmap_payload(payload: bytes) -> RobotMap:
|
|
117
|
+
"""Parse inflated SCMap bytes into a generated protobuf message."""
|
|
118
|
+
parsed = RobotMap()
|
|
119
|
+
try:
|
|
120
|
+
parsed.ParseFromString(payload)
|
|
121
|
+
except DecodeError as err:
|
|
122
|
+
raise RoborockException("Failed to parse B01 SCMap") from err
|
|
123
|
+
return parsed
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _extract_grid(parsed: RobotMap) -> tuple[int, int, bytes]:
|
|
127
|
+
if not parsed.HasField("mapHead") or not parsed.HasField("mapData"):
|
|
128
|
+
raise RoborockException("Failed to parse B01 map header/grid")
|
|
129
|
+
|
|
130
|
+
size_x = parsed.mapHead.sizeX if parsed.mapHead.HasField("sizeX") else 0
|
|
131
|
+
size_y = parsed.mapHead.sizeY if parsed.mapHead.HasField("sizeY") else 0
|
|
132
|
+
if not size_x or not size_y or not parsed.mapData.HasField("mapData"):
|
|
133
|
+
raise RoborockException("Failed to parse B01 map header/grid")
|
|
134
|
+
|
|
135
|
+
map_data = parsed.mapData.mapData
|
|
136
|
+
expected_len = size_x * size_y
|
|
137
|
+
if len(map_data) < expected_len:
|
|
138
|
+
raise RoborockException("B01 map data shorter than expected dimensions")
|
|
139
|
+
|
|
140
|
+
return size_x, size_y, map_data[:expected_len]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class _WorldToPixel:
|
|
144
|
+
"""Project SCMap world coordinates (meters) into top-down image pixels."""
|
|
145
|
+
|
|
146
|
+
def __init__(self, parsed: RobotMap) -> None:
|
|
147
|
+
head = parsed.mapHead
|
|
148
|
+
self._min_x = head.minX
|
|
149
|
+
self._min_y = head.minY
|
|
150
|
+
self._max_x = head.maxX
|
|
151
|
+
self._max_y = head.maxY
|
|
152
|
+
self._resolution = head.resolution or 0.05
|
|
153
|
+
self._size_y = head.sizeY
|
|
154
|
+
|
|
155
|
+
def in_bounds(self, x: float, y: float) -> bool:
|
|
156
|
+
"""Whether a world point lies inside the map (rejects placeholder poses)."""
|
|
157
|
+
return self._min_x <= x <= self._max_x and self._min_y <= y <= self._max_y
|
|
158
|
+
|
|
159
|
+
def to_pixel(self, x: float, y: float) -> tuple[float, float]:
|
|
160
|
+
"""World meters to top-down image pixel coordinates."""
|
|
161
|
+
px = (x - self._min_x) / self._resolution
|
|
162
|
+
py = self._size_y - 1 - (y - self._min_y) / self._resolution
|
|
163
|
+
return px, py
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _place_poses(map_data: MapData, parsed: RobotMap, projector: _WorldToPixel) -> bool:
|
|
167
|
+
"""Populate charger, robot position and path from the decoded SCMap."""
|
|
168
|
+
has_drawables = False
|
|
169
|
+
|
|
170
|
+
if parsed.HasField("chargeStation") and projector.in_bounds(parsed.chargeStation.x, parsed.chargeStation.y):
|
|
171
|
+
px, py = projector.to_pixel(parsed.chargeStation.x, parsed.chargeStation.y)
|
|
172
|
+
map_data.charger = Point(px, py, math.degrees(parsed.chargeStation.phi))
|
|
173
|
+
has_drawables = True
|
|
174
|
+
|
|
175
|
+
if parsed.HasField("currentPose") and projector.in_bounds(parsed.currentPose.x, parsed.currentPose.y):
|
|
176
|
+
px, py = projector.to_pixel(parsed.currentPose.x, parsed.currentPose.y)
|
|
177
|
+
map_data.vacuum_position = Point(px, py, math.degrees(parsed.currentPose.phi))
|
|
178
|
+
has_drawables = True
|
|
179
|
+
elif map_data.charger is not None:
|
|
180
|
+
# A saved map carries no live pose; show the robot at its dock.
|
|
181
|
+
map_data.vacuum_position = Point(map_data.charger.x, map_data.charger.y, map_data.charger.a)
|
|
182
|
+
|
|
183
|
+
areas = [
|
|
184
|
+
Area(*(coord for point in area.points for coord in projector.to_pixel(point.x, point.y)))
|
|
185
|
+
for area in parsed.areaInfo
|
|
186
|
+
if len(area.points) == 4
|
|
187
|
+
]
|
|
188
|
+
if areas:
|
|
189
|
+
# areaInfo type semantics are not yet mapped per zone kind; render all
|
|
190
|
+
# restricted areas through the no-go drawable for now.
|
|
191
|
+
map_data.no_go_areas = areas
|
|
192
|
+
has_drawables = True
|
|
193
|
+
|
|
194
|
+
if parsed.HasField("historyPose"):
|
|
195
|
+
pixels = [
|
|
196
|
+
Point(*projector.to_pixel(point.x, point.y))
|
|
197
|
+
for point in parsed.historyPose.points
|
|
198
|
+
if projector.in_bounds(point.x, point.y)
|
|
199
|
+
]
|
|
200
|
+
if pixels:
|
|
201
|
+
map_data.path = Path(len(pixels), 1, 0, [pixels])
|
|
202
|
+
has_drawables = True
|
|
203
|
+
|
|
204
|
+
return has_drawables
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _extract_rooms(parsed: RobotMap, projector: _WorldToPixel, room_names: dict[int, str]) -> dict[int, Room] | None:
|
|
208
|
+
"""Build room bounding boxes (image-pixel space) from room outlines."""
|
|
209
|
+
rooms: dict[int, Room] = {}
|
|
210
|
+
label_positions = {
|
|
211
|
+
room.roomId: projector.to_pixel(room.roomNamePost.x, room.roomNamePost.y)
|
|
212
|
+
for room in parsed.roomDataInfo
|
|
213
|
+
if room.HasField("roomNamePost")
|
|
214
|
+
}
|
|
215
|
+
size_y = parsed.mapHead.sizeY
|
|
216
|
+
for outline in parsed.roomOutline:
|
|
217
|
+
if not outline.points:
|
|
218
|
+
continue
|
|
219
|
+
room_id = outline.roomId
|
|
220
|
+
# Outline points are top-down after the same vertical flip as the raster.
|
|
221
|
+
xs = [point.x for point in outline.points]
|
|
222
|
+
ys = [size_y - 1 - point.y for point in outline.points]
|
|
223
|
+
pos = label_positions.get(room_id)
|
|
224
|
+
rooms[room_id] = Room(
|
|
225
|
+
min(xs),
|
|
226
|
+
min(ys),
|
|
227
|
+
max(xs),
|
|
228
|
+
max(ys),
|
|
229
|
+
room_id,
|
|
230
|
+
room_names.get(room_id),
|
|
231
|
+
pos[0] if pos else None,
|
|
232
|
+
pos[1] if pos else None,
|
|
233
|
+
)
|
|
234
|
+
return rooms or None
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _extract_room_names(parsed: RobotMap) -> dict[int, str]:
|
|
238
|
+
# Expose room id/name mapping without inventing room geometry/polygons.
|
|
239
|
+
room_names: dict[int, str] = {}
|
|
240
|
+
for room in parsed.roomDataInfo:
|
|
241
|
+
if room.HasField("roomId"):
|
|
242
|
+
room_id = room.roomId
|
|
243
|
+
room_names[room_id] = room.roomName if room.HasField("roomName") else f"Room {room_id}"
|
|
244
|
+
return room_names
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _assign_room_pixels(parsed: RobotMap, grid: bytes, *, size_x: int, size_y: int) -> bytearray:
|
|
248
|
+
"""Assign a room id to each floor pixel by flood-filling from room labels.
|
|
249
|
+
|
|
250
|
+
The grid itself carries no room ids; room geometry arrives as boundary
|
|
251
|
+
pixel chains (``roomOutline``). Each room is filled from its label
|
|
252
|
+
position, bounded by walls and by any room's outline pixels, all in the
|
|
253
|
+
raw (bottom-up) grid space.
|
|
254
|
+
"""
|
|
255
|
+
assignment = bytearray(len(grid))
|
|
256
|
+
outlines = {outline.roomId: outline for outline in parsed.roomOutline if outline.points}
|
|
257
|
+
if not outlines:
|
|
258
|
+
return assignment
|
|
259
|
+
|
|
260
|
+
barrier = {
|
|
261
|
+
point.y * size_x + point.x
|
|
262
|
+
for outline in outlines.values()
|
|
263
|
+
for point in outline.points
|
|
264
|
+
if point.x < size_x and point.y < size_y
|
|
265
|
+
}
|
|
266
|
+
floor_count = grid.count(_FLOOR)
|
|
267
|
+
# ponytail: leak guard — a gapped outline would flood the whole floor, so a
|
|
268
|
+
# fill larger than half of it is discarded instead of tracing outline gaps.
|
|
269
|
+
max_fill = floor_count // 2
|
|
270
|
+
|
|
271
|
+
head = parsed.mapHead
|
|
272
|
+
label_positions = {
|
|
273
|
+
room.roomId: (
|
|
274
|
+
int((room.roomNamePost.x - head.minX) / head.resolution),
|
|
275
|
+
int((room.roomNamePost.y - head.minY) / head.resolution),
|
|
276
|
+
)
|
|
277
|
+
for room in parsed.roomDataInfo
|
|
278
|
+
if room.HasField("roomNamePost")
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
for room_id, outline in outlines.items():
|
|
282
|
+
seed = label_positions.get(room_id)
|
|
283
|
+
if seed is None:
|
|
284
|
+
continue
|
|
285
|
+
col, row = seed
|
|
286
|
+
start = row * size_x + col
|
|
287
|
+
if not (0 <= col < size_x and 0 <= row < size_y) or grid[start] != _FLOOR:
|
|
288
|
+
continue
|
|
289
|
+
filled: list[int] = []
|
|
290
|
+
queue = deque([start])
|
|
291
|
+
seen = {start}
|
|
292
|
+
while queue and len(filled) <= max_fill:
|
|
293
|
+
index = queue.popleft()
|
|
294
|
+
filled.append(index)
|
|
295
|
+
for neighbor in (index - 1, index + 1, index - size_x, index + size_x):
|
|
296
|
+
if (
|
|
297
|
+
0 <= neighbor < len(grid)
|
|
298
|
+
and neighbor not in seen
|
|
299
|
+
and grid[neighbor] == _FLOOR
|
|
300
|
+
and assignment[neighbor] == 0
|
|
301
|
+
and neighbor not in barrier
|
|
302
|
+
# Row-wrap guard for the horizontal neighbors.
|
|
303
|
+
and abs(neighbor % size_x - index % size_x) <= 1
|
|
304
|
+
):
|
|
305
|
+
seen.add(neighbor)
|
|
306
|
+
queue.append(neighbor)
|
|
307
|
+
if len(filled) > max_fill:
|
|
308
|
+
continue
|
|
309
|
+
for index in filled:
|
|
310
|
+
assignment[index] = room_id
|
|
311
|
+
# Color the room's own boundary ring too where it sits on floor.
|
|
312
|
+
for point in outline.points:
|
|
313
|
+
index = point.y * size_x + point.x
|
|
314
|
+
if index < len(grid) and grid[index] == _FLOOR and assignment[index] == 0:
|
|
315
|
+
assignment[index] = room_id
|
|
316
|
+
|
|
317
|
+
return assignment
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _carpet_pixel_indices(parsed: RobotMap, grid: bytes, *, size_x: int, size_y: int) -> set[int]:
|
|
321
|
+
"""Raw-grid indices of floor pixels covered by enabled carpets."""
|
|
322
|
+
head = parsed.mapHead
|
|
323
|
+
resolution = head.resolution or 0.05
|
|
324
|
+
indices: set[int] = set()
|
|
325
|
+
for carpet in parsed.carpetInfo:
|
|
326
|
+
if not carpet.points or (carpet.HasField("enabled") and not carpet.enabled):
|
|
327
|
+
continue
|
|
328
|
+
cols = [int((point.x - head.minX) / resolution) for point in carpet.points]
|
|
329
|
+
rows = [int((point.y - head.minY) / resolution) for point in carpet.points]
|
|
330
|
+
for row in range(max(min(rows), 0), min(max(rows), size_y - 1) + 1):
|
|
331
|
+
for col in range(max(min(cols), 0), min(max(cols), size_x - 1) + 1):
|
|
332
|
+
index = row * size_x + col
|
|
333
|
+
if grid[index] == _FLOOR:
|
|
334
|
+
indices.add(index)
|
|
335
|
+
return indices
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def _render_occupancy_image(
|
|
339
|
+
grid: bytes, room_pixels: bytearray, carpet_pixels: set[int], *, size_x: int, size_y: int, scale: int
|
|
340
|
+
) -> Image.Image:
|
|
341
|
+
"""Render the B01 occupancy grid with per-room colors."""
|
|
342
|
+
|
|
343
|
+
colors = ColorsPalette()
|
|
344
|
+
room_colors = {
|
|
345
|
+
room_id: tuple(color[:3]) + (255,)
|
|
346
|
+
for room_id, color in adjacency_aware_room_colors(
|
|
347
|
+
room_pixels, size_x, colors, lambda value: value or None
|
|
348
|
+
).items()
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
# The observed occupancy grid contains only:
|
|
352
|
+
# - 0: outside/unknown
|
|
353
|
+
# - 127: floor/free
|
|
354
|
+
# - 128: wall/obstacle
|
|
355
|
+
# Same V1 palette roles as the Q10 renderer: transparent outside, grey
|
|
356
|
+
# walls/obstacles, MAP_INSIDE for floor not assigned to any room.
|
|
357
|
+
outside = (0, 0, 0, 0)
|
|
358
|
+
floor = tuple(colors.get_color(SupportedColor.MAP_INSIDE)[:3]) + (255,)
|
|
359
|
+
base_colors = {
|
|
360
|
+
0: outside,
|
|
361
|
+
_FLOOR: floor,
|
|
362
|
+
_WALL: tuple(colors.get_color(SupportedColor.GREY_WALL)[:3]) + (255,),
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
rgba = bytearray()
|
|
366
|
+
for index, value in enumerate(grid):
|
|
367
|
+
if value == _FLOOR and (room_id := room_pixels[index]):
|
|
368
|
+
color = room_colors.get(room_id, floor)
|
|
369
|
+
else:
|
|
370
|
+
color = base_colors.get(value, floor)
|
|
371
|
+
if index in carpet_pixels and (index // size_x + index % size_x) % 2 == 0:
|
|
372
|
+
# Checkerboard stipple, like the V1 carpet texture.
|
|
373
|
+
color = tuple(min(channel + 60, 255) for channel in color[:3]) + (255,)
|
|
374
|
+
rgba.extend(color)
|
|
375
|
+
|
|
376
|
+
# RGBA so the shared V1 ImageGenerator can alpha-composite overlay glyphs.
|
|
377
|
+
img = Image.frombytes("RGBA", (size_x, size_y), bytes(rgba))
|
|
378
|
+
img = img.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
|
|
379
|
+
|
|
380
|
+
if scale > 1:
|
|
381
|
+
img = img.resize((size_x * scale, size_y * scale), resample=Image.Resampling.NEAREST)
|
|
382
|
+
|
|
383
|
+
return img
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// Checked-in B01/Q7 SCMap schema for the generated runtime protobuf module.
|
|
2
|
+
// Regenerate the checked-in Python module after edits with:
|
|
3
|
+
// python -m grpc_tools.protoc -I. --python_out=. roborock/map/proto/b01_scmap.proto
|
|
4
|
+
// The generated file `b01_scmap_pb2.py` is checked in for runtime use and should
|
|
5
|
+
// not be edited by hand.
|
|
6
|
+
syntax = "proto2";
|
|
7
|
+
|
|
8
|
+
package b01.scmap;
|
|
9
|
+
|
|
10
|
+
message DevicePointInfo {
|
|
11
|
+
optional float x = 1;
|
|
12
|
+
optional float y = 2;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
message MapBoundaryInfo {
|
|
16
|
+
optional string mapMd5 = 1;
|
|
17
|
+
optional uint32 vMinX = 2;
|
|
18
|
+
optional uint32 vMaxX = 3;
|
|
19
|
+
optional uint32 vMinY = 4;
|
|
20
|
+
optional uint32 vMaxY = 5;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
message MapExtInfo {
|
|
24
|
+
optional uint32 taskBeginDate = 1;
|
|
25
|
+
optional uint32 mapUploadDate = 2;
|
|
26
|
+
optional uint32 mapValid = 3;
|
|
27
|
+
optional uint32 radian = 4;
|
|
28
|
+
optional uint32 force = 5;
|
|
29
|
+
optional uint32 cleanPath = 6;
|
|
30
|
+
optional MapBoundaryInfo boudaryInfo = 7;
|
|
31
|
+
optional uint32 mapVersion = 8;
|
|
32
|
+
optional uint32 mapValueType = 9;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
message MapHeadInfo {
|
|
36
|
+
optional uint32 mapHeadId = 1;
|
|
37
|
+
optional uint32 sizeX = 2;
|
|
38
|
+
optional uint32 sizeY = 3;
|
|
39
|
+
optional float minX = 4;
|
|
40
|
+
optional float minY = 5;
|
|
41
|
+
optional float maxX = 6;
|
|
42
|
+
optional float maxY = 7;
|
|
43
|
+
optional float resolution = 8;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
message MapDataInfo {
|
|
47
|
+
optional bytes mapData = 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
message MapInfo {
|
|
51
|
+
optional uint32 mapId = 1;
|
|
52
|
+
optional string mapName = 2;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
message DevicePoseDataInfo {
|
|
56
|
+
optional uint32 update = 1;
|
|
57
|
+
optional float x = 2;
|
|
58
|
+
optional float y = 3;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
message DeviceHistoryPoseInfo {
|
|
62
|
+
optional uint32 poseId = 1;
|
|
63
|
+
repeated DevicePoseDataInfo points = 2;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
message DevicePoseInfo {
|
|
67
|
+
optional float x = 1;
|
|
68
|
+
optional float y = 2;
|
|
69
|
+
optional float phi = 3;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
message DeviceCurrentPoseInfo {
|
|
73
|
+
optional uint32 poseId = 1;
|
|
74
|
+
optional uint32 update = 2;
|
|
75
|
+
optional float x = 3;
|
|
76
|
+
optional float y = 4;
|
|
77
|
+
optional float phi = 5;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
message DeviceAreaDataInfo {
|
|
81
|
+
optional uint32 status = 1;
|
|
82
|
+
optional uint32 type = 2;
|
|
83
|
+
optional uint32 areaIndex = 3;
|
|
84
|
+
repeated DevicePointInfo points = 4;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
message RoomMatrixInfo {
|
|
88
|
+
optional bytes matrix = 1;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
message RoomOutlinePointInfo {
|
|
92
|
+
optional uint32 x = 1;
|
|
93
|
+
optional uint32 y = 2;
|
|
94
|
+
optional uint32 value = 3;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
message RoomBorderPointInfo {
|
|
98
|
+
optional uint32 x = 1;
|
|
99
|
+
optional uint32 y = 2;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
message RoomBorderInfo {
|
|
103
|
+
repeated RoomBorderPointInfo points = 1;
|
|
104
|
+
repeated uint32 roomIds = 2;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
message RoomOutlineInfo {
|
|
108
|
+
optional uint32 roomId = 1;
|
|
109
|
+
repeated RoomOutlinePointInfo points = 2;
|
|
110
|
+
repeated RoomBorderInfo borders = 3;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
message CarpetDataInfo {
|
|
114
|
+
optional uint32 carpetId = 1;
|
|
115
|
+
optional uint32 type = 2;
|
|
116
|
+
optional uint32 unknown3 = 3;
|
|
117
|
+
repeated DevicePointInfo points = 4;
|
|
118
|
+
optional uint32 enabled = 6;
|
|
119
|
+
optional uint32 unknown7 = 7;
|
|
120
|
+
optional uint32 unknown8 = 8;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
message RoomDataInfo {
|
|
124
|
+
optional uint32 roomId = 1;
|
|
125
|
+
optional string roomName = 2;
|
|
126
|
+
optional uint32 roomTypeId = 3;
|
|
127
|
+
optional uint32 meterialId = 4;
|
|
128
|
+
optional uint32 cleanState = 5;
|
|
129
|
+
optional uint32 roomClean = 6;
|
|
130
|
+
optional uint32 roomCleanIndex = 7;
|
|
131
|
+
optional DevicePointInfo roomNamePost = 8;
|
|
132
|
+
optional uint32 colorId = 10;
|
|
133
|
+
optional uint32 floor_direction = 11;
|
|
134
|
+
optional uint32 global_seq = 12;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
message RobotMap {
|
|
138
|
+
optional uint32 mapType = 1;
|
|
139
|
+
optional MapExtInfo mapExtInfo = 2;
|
|
140
|
+
optional MapHeadInfo mapHead = 3;
|
|
141
|
+
optional MapDataInfo mapData = 4;
|
|
142
|
+
repeated MapInfo mapInfo = 5;
|
|
143
|
+
optional DeviceHistoryPoseInfo historyPose = 6;
|
|
144
|
+
optional DevicePoseInfo chargeStation = 7;
|
|
145
|
+
optional DeviceCurrentPoseInfo currentPose = 8;
|
|
146
|
+
repeated DeviceAreaDataInfo areaInfo = 9;
|
|
147
|
+
repeated RoomDataInfo roomDataInfo = 12;
|
|
148
|
+
optional RoomMatrixInfo roomMatrix = 13;
|
|
149
|
+
repeated RoomOutlineInfo roomOutline = 14;
|
|
150
|
+
repeated CarpetDataInfo carpetInfo = 20;
|
|
151
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: roborock/map/proto/b01_scmap.proto
|
|
5
|
+
# Protobuf Python Version: 6.31.1
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
6,
|
|
15
|
+
31,
|
|
16
|
+
1,
|
|
17
|
+
'',
|
|
18
|
+
'roborock/map/proto/b01_scmap.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"roborock/map/proto/b01_scmap.proto\x12\tb01.scmap\"\'\n\x0f\x44\x65vicePointInfo\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\"]\n\x0fMapBoundaryInfo\x12\x0e\n\x06mapMd5\x18\x01 \x01(\t\x12\r\n\x05vMinX\x18\x02 \x01(\r\x12\r\n\x05vMaxX\x18\x03 \x01(\r\x12\r\n\x05vMinY\x18\x04 \x01(\r\x12\r\n\x05vMaxY\x18\x05 \x01(\r\"\xd9\x01\n\nMapExtInfo\x12\x15\n\rtaskBeginDate\x18\x01 \x01(\r\x12\x15\n\rmapUploadDate\x18\x02 \x01(\r\x12\x10\n\x08mapValid\x18\x03 \x01(\r\x12\x0e\n\x06radian\x18\x04 \x01(\r\x12\r\n\x05\x66orce\x18\x05 \x01(\r\x12\x11\n\tcleanPath\x18\x06 \x01(\r\x12/\n\x0b\x62oudaryInfo\x18\x07 \x01(\x0b\x32\x1a.b01.scmap.MapBoundaryInfo\x12\x12\n\nmapVersion\x18\x08 \x01(\r\x12\x14\n\x0cmapValueType\x18\t \x01(\r\"\x8a\x01\n\x0bMapHeadInfo\x12\x11\n\tmapHeadId\x18\x01 \x01(\r\x12\r\n\x05sizeX\x18\x02 \x01(\r\x12\r\n\x05sizeY\x18\x03 \x01(\r\x12\x0c\n\x04minX\x18\x04 \x01(\x02\x12\x0c\n\x04minY\x18\x05 \x01(\x02\x12\x0c\n\x04maxX\x18\x06 \x01(\x02\x12\x0c\n\x04maxY\x18\x07 \x01(\x02\x12\x12\n\nresolution\x18\x08 \x01(\x02\"\x1e\n\x0bMapDataInfo\x12\x0f\n\x07mapData\x18\x01 \x01(\x0c\")\n\x07MapInfo\x12\r\n\x05mapId\x18\x01 \x01(\r\x12\x0f\n\x07mapName\x18\x02 \x01(\t\":\n\x12\x44\x65vicePoseDataInfo\x12\x0e\n\x06update\x18\x01 \x01(\r\x12\t\n\x01x\x18\x02 \x01(\x02\x12\t\n\x01y\x18\x03 \x01(\x02\"V\n\x15\x44\x65viceHistoryPoseInfo\x12\x0e\n\x06poseId\x18\x01 \x01(\r\x12-\n\x06points\x18\x02 \x03(\x0b\x32\x1d.b01.scmap.DevicePoseDataInfo\"3\n\x0e\x44\x65vicePoseInfo\x12\t\n\x01x\x18\x01 \x01(\x02\x12\t\n\x01y\x18\x02 \x01(\x02\x12\x0b\n\x03phi\x18\x03 \x01(\x02\"Z\n\x15\x44\x65viceCurrentPoseInfo\x12\x0e\n\x06poseId\x18\x01 \x01(\r\x12\x0e\n\x06update\x18\x02 \x01(\r\x12\t\n\x01x\x18\x03 \x01(\x02\x12\t\n\x01y\x18\x04 \x01(\x02\x12\x0b\n\x03phi\x18\x05 \x01(\x02\"q\n\x12\x44\x65viceAreaDataInfo\x12\x0e\n\x06status\x18\x01 \x01(\r\x12\x0c\n\x04type\x18\x02 \x01(\r\x12\x11\n\tareaIndex\x18\x03 \x01(\r\x12*\n\x06points\x18\x04 \x03(\x0b\x32\x1a.b01.scmap.DevicePointInfo\" \n\x0eRoomMatrixInfo\x12\x0e\n\x06matrix\x18\x01 \x01(\x0c\";\n\x14RoomOutlinePointInfo\x12\t\n\x01x\x18\x01 \x01(\r\x12\t\n\x01y\x18\x02 \x01(\r\x12\r\n\x05value\x18\x03 \x01(\r\"+\n\x13RoomBorderPointInfo\x12\t\n\x01x\x18\x01 \x01(\r\x12\t\n\x01y\x18\x02 \x01(\r\"Q\n\x0eRoomBorderInfo\x12.\n\x06points\x18\x01 \x03(\x0b\x32\x1e.b01.scmap.RoomBorderPointInfo\x12\x0f\n\x07roomIds\x18\x02 \x03(\r\"~\n\x0fRoomOutlineInfo\x12\x0e\n\x06roomId\x18\x01 \x01(\r\x12/\n\x06points\x18\x02 \x03(\x0b\x32\x1f.b01.scmap.RoomOutlinePointInfo\x12*\n\x07\x62orders\x18\x03 \x03(\x0b\x32\x19.b01.scmap.RoomBorderInfo\"\xa3\x01\n\x0e\x43\x61rpetDataInfo\x12\x10\n\x08\x63\x61rpetId\x18\x01 \x01(\r\x12\x0c\n\x04type\x18\x02 \x01(\r\x12\x10\n\x08unknown3\x18\x03 \x01(\r\x12*\n\x06points\x18\x04 \x03(\x0b\x32\x1a.b01.scmap.DevicePointInfo\x12\x0f\n\x07\x65nabled\x18\x06 \x01(\r\x12\x10\n\x08unknown7\x18\x07 \x01(\r\x12\x10\n\x08unknown8\x18\x08 \x01(\r\"\x87\x02\n\x0cRoomDataInfo\x12\x0e\n\x06roomId\x18\x01 \x01(\r\x12\x10\n\x08roomName\x18\x02 \x01(\t\x12\x12\n\nroomTypeId\x18\x03 \x01(\r\x12\x12\n\nmeterialId\x18\x04 \x01(\r\x12\x12\n\ncleanState\x18\x05 \x01(\r\x12\x11\n\troomClean\x18\x06 \x01(\r\x12\x16\n\x0eroomCleanIndex\x18\x07 \x01(\r\x12\x30\n\x0croomNamePost\x18\x08 \x01(\x0b\x32\x1a.b01.scmap.DevicePointInfo\x12\x0f\n\x07\x63olorId\x18\n \x01(\r\x12\x17\n\x0f\x66loor_direction\x18\x0b \x01(\r\x12\x12\n\nglobal_seq\x18\x0c \x01(\r\"\xcc\x04\n\x08RobotMap\x12\x0f\n\x07mapType\x18\x01 \x01(\r\x12)\n\nmapExtInfo\x18\x02 \x01(\x0b\x32\x15.b01.scmap.MapExtInfo\x12\'\n\x07mapHead\x18\x03 \x01(\x0b\x32\x16.b01.scmap.MapHeadInfo\x12\'\n\x07mapData\x18\x04 \x01(\x0b\x32\x16.b01.scmap.MapDataInfo\x12#\n\x07mapInfo\x18\x05 \x03(\x0b\x32\x12.b01.scmap.MapInfo\x12\x35\n\x0bhistoryPose\x18\x06 \x01(\x0b\x32 .b01.scmap.DeviceHistoryPoseInfo\x12\x30\n\rchargeStation\x18\x07 \x01(\x0b\x32\x19.b01.scmap.DevicePoseInfo\x12\x35\n\x0b\x63urrentPose\x18\x08 \x01(\x0b\x32 .b01.scmap.DeviceCurrentPoseInfo\x12/\n\x08\x61reaInfo\x18\t \x03(\x0b\x32\x1d.b01.scmap.DeviceAreaDataInfo\x12-\n\x0croomDataInfo\x18\x0c \x03(\x0b\x32\x17.b01.scmap.RoomDataInfo\x12-\n\nroomMatrix\x18\r \x01(\x0b\x32\x19.b01.scmap.RoomMatrixInfo\x12/\n\x0broomOutline\x18\x0e \x03(\x0b\x32\x1a.b01.scmap.RoomOutlineInfo\x12-\n\ncarpetInfo\x18\x14 \x03(\x0b\x32\x19.b01.scmap.CarpetDataInfo')
|
|
28
|
+
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'roborock.map.proto.b01_scmap_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
DESCRIPTOR._loaded_options = None
|
|
34
|
+
_globals['_DEVICEPOINTINFO']._serialized_start=49
|
|
35
|
+
_globals['_DEVICEPOINTINFO']._serialized_end=88
|
|
36
|
+
_globals['_MAPBOUNDARYINFO']._serialized_start=90
|
|
37
|
+
_globals['_MAPBOUNDARYINFO']._serialized_end=183
|
|
38
|
+
_globals['_MAPEXTINFO']._serialized_start=186
|
|
39
|
+
_globals['_MAPEXTINFO']._serialized_end=403
|
|
40
|
+
_globals['_MAPHEADINFO']._serialized_start=406
|
|
41
|
+
_globals['_MAPHEADINFO']._serialized_end=544
|
|
42
|
+
_globals['_MAPDATAINFO']._serialized_start=546
|
|
43
|
+
_globals['_MAPDATAINFO']._serialized_end=576
|
|
44
|
+
_globals['_MAPINFO']._serialized_start=578
|
|
45
|
+
_globals['_MAPINFO']._serialized_end=619
|
|
46
|
+
_globals['_DEVICEPOSEDATAINFO']._serialized_start=621
|
|
47
|
+
_globals['_DEVICEPOSEDATAINFO']._serialized_end=679
|
|
48
|
+
_globals['_DEVICEHISTORYPOSEINFO']._serialized_start=681
|
|
49
|
+
_globals['_DEVICEHISTORYPOSEINFO']._serialized_end=767
|
|
50
|
+
_globals['_DEVICEPOSEINFO']._serialized_start=769
|
|
51
|
+
_globals['_DEVICEPOSEINFO']._serialized_end=820
|
|
52
|
+
_globals['_DEVICECURRENTPOSEINFO']._serialized_start=822
|
|
53
|
+
_globals['_DEVICECURRENTPOSEINFO']._serialized_end=912
|
|
54
|
+
_globals['_DEVICEAREADATAINFO']._serialized_start=914
|
|
55
|
+
_globals['_DEVICEAREADATAINFO']._serialized_end=1027
|
|
56
|
+
_globals['_ROOMMATRIXINFO']._serialized_start=1029
|
|
57
|
+
_globals['_ROOMMATRIXINFO']._serialized_end=1061
|
|
58
|
+
_globals['_ROOMOUTLINEPOINTINFO']._serialized_start=1063
|
|
59
|
+
_globals['_ROOMOUTLINEPOINTINFO']._serialized_end=1122
|
|
60
|
+
_globals['_ROOMBORDERPOINTINFO']._serialized_start=1124
|
|
61
|
+
_globals['_ROOMBORDERPOINTINFO']._serialized_end=1167
|
|
62
|
+
_globals['_ROOMBORDERINFO']._serialized_start=1169
|
|
63
|
+
_globals['_ROOMBORDERINFO']._serialized_end=1250
|
|
64
|
+
_globals['_ROOMOUTLINEINFO']._serialized_start=1252
|
|
65
|
+
_globals['_ROOMOUTLINEINFO']._serialized_end=1378
|
|
66
|
+
_globals['_CARPETDATAINFO']._serialized_start=1381
|
|
67
|
+
_globals['_CARPETDATAINFO']._serialized_end=1544
|
|
68
|
+
_globals['_ROOMDATAINFO']._serialized_start=1547
|
|
69
|
+
_globals['_ROOMDATAINFO']._serialized_end=1810
|
|
70
|
+
_globals['_ROBOTMAP']._serialized_start=1813
|
|
71
|
+
_globals['_ROBOTMAP']._serialized_end=2401
|
|
72
|
+
# @@protoc_insertion_point(module_scope)
|