python-roborock 7.4.3__py3-none-any.whl → 7.6.0__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-roborock
3
- Version: 7.4.3
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/
@@ -67,7 +67,7 @@ roborock/devices/traits/b01/q10/remote.py,sha256=8-fg4SA5M-tdMufHPeD9hIcax7y9Qh7
67
67
  roborock/devices/traits/b01/q10/status.py,sha256=JAPixbsQ8jfN3OvI7o_NxISXFk8l7rGHFYcL4pH97Jk,859
68
68
  roborock/devices/traits/b01/q10/vacuum.py,sha256=w2FftNH5n-Tb-9drR3-5OiMy85FJfTDNmtt34LklC8w,4374
69
69
  roborock/devices/traits/b01/q10/volume.py,sha256=UnT0yYDQntxYwnpv4_NVychm0FnGAYRAWA_FJR4yJag,1001
70
- roborock/devices/traits/b01/q7/__init__.py,sha256=wHe2uncF49MlfPwyIgs0xbwnQo8q0eDEyHTh33iHq80,8549
70
+ roborock/devices/traits/b01/q7/__init__.py,sha256=tbsZSe2VojCN7uRdHPm74on8WrexJePzQ2ewTLcFjWo,9124
71
71
  roborock/devices/traits/b01/q7/clean_summary.py,sha256=M43iJVeYjrkBV6ZxXdHtn4Rd5Mx-KAK7WLU5fABiN8I,2742
72
72
  roborock/devices/traits/b01/q7/map.py,sha256=NfPQAEwNCUsb0SYGMxmGeq4q4rEHqDJK0zTD5cE-ESs,1299
73
73
  roborock/devices/traits/b01/q7/map_content.py,sha256=O4UMnmX0-K-jxhOaknUZpWJSwxUuaTd2_D9_AP-elGY,4920
@@ -100,15 +100,15 @@ roborock/devices/transport/local_channel.py,sha256=xnCzhIMa6V01Okaoa5KlUFw7k0col
100
100
  roborock/devices/transport/mqtt_channel.py,sha256=dpL1mZIoI4Glk3hfUO9JweWFHG1tZWLrWbt9f4RbvhQ,4789
101
101
  roborock/map/__init__.py,sha256=L3WHujuxUHCTTPaOElkJsTN_FkYhw01drfR-W4blgFc,146
102
102
  roborock/map/b01_grid_layers.py,sha256=b87MsGXslqLR_5H_4z4aj1wQqYgeTuULWqt4_txOF-M,12303
103
- roborock/map/b01_map_parser.py,sha256=tTeeWH4fA4Pv4DvqN7PBQs92DuWTaD2rvD44Mo_t3OY,4433
103
+ roborock/map/b01_map_parser.py,sha256=y4Qlgiwre3bn5_UpL6R-ytjg8kQqwkbvhIYFOtpAM3s,14814
104
104
  roborock/map/b01_q10_map_parser.py,sha256=Pt-goedXV60hg-mwHOgOF0f4TQBQmQXe6otpWaa99ps,29996
105
105
  roborock/map/b01_q10_overlays.py,sha256=JmriUbT4-oe6NiE94VttMplFc1HHQrAGNQIiZHj5QKk,6640
106
106
  roborock/map/b01_q10_render.py,sha256=b7YUBr53WXxOJhXbfb5IVmgi82iGcC0lJ_j9Ef3kV7M,13502
107
107
  roborock/map/map_parser.py,sha256=EcJcz9yld_wu7d5QrmxR2BTfJ801F6SaEgJkbIIap4w,5111
108
108
  roborock/map/room_colors.py,sha256=5Q85oR_7xsUyzHYGOJPuzsZ6LQSCpJwfxfWql1v6T1E,2152
109
109
  roborock/map/proto/__init__.py,sha256=XcH_s-E67_hcQNwqSkdtY7DgYE0mRBBJwctzsf8zng4,60
110
- roborock/map/proto/b01_scmap.proto,sha256=ux1OnI_-LSDOlTujCCUeOJrTsVCvjLAUKfyddu-rH5U,1929
111
- roborock/map/proto/b01_scmap_pb2.py,sha256=KxHxnxSvEjIAZJY5QO0pH5rY7uYxKlup8hyt30jFAtw,3767
110
+ roborock/map/proto/b01_scmap.proto,sha256=lQtOruroUfrDK9EJ99cnGTi7avEK3CQ1haLIopDrS_A,3725
111
+ roborock/map/proto/b01_scmap_pb2.py,sha256=HI7xxxpvV0cFl80B7T7RN74C3cP8YNqfukL_FW324ss,7493
112
112
  roborock/mqtt/__init__.py,sha256=Lplt5aS3lCJW09KX34tf2r6NHU8penM-R07FI56Z5CE,415
113
113
  roborock/mqtt/health_manager.py,sha256=i_3vbslHMebVd0VNBWalPaEnZi8gcRI3IcKPt2wlQF8,2208
114
114
  roborock/mqtt/roborock_session.py,sha256=ir7HXs4gtoineiwlc6ixyAueBTCSPtNU8zPGgY9hGOE,21027
@@ -125,8 +125,8 @@ roborock/testing/channel.py,sha256=vjulT5MHBe8lAq6XITUqcxJVcCILWx7ZEcw5imTx0Tk,7
125
125
  roborock/testing/cloud.py,sha256=L2L0KlZDYaMuoV19KUQUoq5EAUDeNQ1lJ8Ew5YaOgjo,11946
126
126
  roborock/testing/simulator.py,sha256=g8ZUWVSjgAzuRRxWOCeOq-7deodyEItwUpqEw9RzCmQ,4347
127
127
  roborock/testing/v1_simulator.py,sha256=_LX_vsBMcB2Uu2QDt8QnQymgtVtbnwD5Xa7tmhiPAnY,14439
128
- python_roborock-7.4.3.dist-info/METADATA,sha256=aKz_bLOyquXyaONtqRzSBTwd2qbzww3ozFSdDfPM-_o,5278
129
- python_roborock-7.4.3.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
130
- python_roborock-7.4.3.dist-info/entry_points.txt,sha256=EvC1nMqi9ZXKgZnqlNXA33v_3nzgPNjnM0mzWlrehnY,47
131
- python_roborock-7.4.3.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
132
- python_roborock-7.4.3.dist-info/RECORD,,
128
+ python_roborock-7.6.0.dist-info/METADATA,sha256=K-sGLp5G2PZElinVEK18ggGArG4cdD7GKeYfTJFJsLQ,5278
129
+ python_roborock-7.6.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
130
+ python_roborock-7.6.0.dist-info/entry_points.txt,sha256=EvC1nMqi9ZXKgZnqlNXA33v_3nzgPNjnM0mzWlrehnY,47
131
+ python_roborock-7.6.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
132
+ python_roborock-7.6.0.dist-info/RECORD,,
@@ -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
 
@@ -5,20 +5,36 @@ The inner SCMap blob is parsed with protobuf messages generated from
5
5
  """
6
6
 
7
7
  import io
8
+ import math
9
+ from collections import deque
8
10
  from dataclasses import dataclass
9
11
 
10
12
  from google.protobuf.message import DecodeError
11
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
12
16
  from vacuum_map_parser_base.config.image_config import ImageConfig
13
- from vacuum_map_parser_base.map_data import ImageData, MapData
17
+ from vacuum_map_parser_base.map_data import Area, ImageData, MapData, Path, Point, Room
14
18
 
15
19
  from roborock.exceptions import RoborockException
16
20
  from roborock.map.proto.b01_scmap_pb2 import RobotMap # type: ignore[attr-defined]
17
21
 
18
- from .map_parser import ParsedMapData
22
+ from .map_parser import MapParserConfig, ParsedMapData, _create_image_generator
23
+ from .room_colors import adjacency_aware_room_colors
19
24
 
20
25
  _MAP_FILE_FORMAT = "PNG"
21
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
+
22
38
 
23
39
  @dataclass
24
40
  class B01MapParserConfig:
@@ -40,7 +56,11 @@ class B01MapParser:
40
56
  size_x, size_y, grid = _extract_grid(parsed)
41
57
  room_names = _extract_room_names(parsed)
42
58
 
43
- image = _render_occupancy_image(grid, size_x=size_x, size_y=size_y, scale=self._config.map_scale)
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
+ )
44
64
 
45
65
  map_data = MapData()
46
66
  map_data.image = ImageData(
@@ -51,11 +71,30 @@ class B01MapParser:
51
71
  width=size_x,
52
72
  image_config=ImageConfig(scale=self._config.map_scale),
53
73
  data=image,
54
- img_transformation=lambda p: p,
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),
55
78
  )
56
79
  if room_names:
57
80
  map_data.additional_parameters["room_names"] = room_names
58
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
+
59
98
  image_bytes = io.BytesIO()
60
99
  image.save(image_bytes, format=_MAP_FILE_FORMAT)
61
100
 
@@ -101,6 +140,100 @@ def _extract_grid(parsed: RobotMap) -> tuple[int, int, bytes]:
101
140
  return size_x, size_y, map_data[:expected_len]
102
141
 
103
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
+
104
237
  def _extract_room_names(parsed: RobotMap) -> dict[int, str]:
105
238
  # Expose room id/name mapping without inventing room geometry/polygons.
106
239
  room_names: dict[int, str] = {}
@@ -111,21 +244,138 @@ def _extract_room_names(parsed: RobotMap) -> dict[int, str]:
111
244
  return room_names
112
245
 
113
246
 
114
- def _render_occupancy_image(grid: bytes, *, size_x: int, size_y: int, scale: int) -> Image.Image:
115
- """Render the B01 occupancy grid into a simple image."""
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
+ }
116
350
 
117
351
  # The observed occupancy grid contains only:
118
352
  # - 0: outside/unknown
119
- # - 127: wall/obstacle
120
- # - 128: floor/free
121
- table = bytearray(range(256))
122
- table[0] = 0
123
- table[127] = 180
124
- table[128] = 255
125
-
126
- mapped = grid.translate(bytes(table))
127
- img = Image.frombytes("L", (size_x, size_y), mapped)
128
- img = img.transpose(Image.Transpose.FLIP_TOP_BOTTOM).convert("RGB")
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)
129
379
 
130
380
  if scale > 1:
131
381
  img = img.resize((size_x * scale, size_y * scale), resample=Image.Resampling.NEAREST)
@@ -1,6 +1,6 @@
1
1
  // Checked-in B01/Q7 SCMap schema for the generated runtime protobuf module.
2
2
  // Regenerate the checked-in Python module after edits with:
3
- // python -m grpc_tools.protoc -I./roborock/map/proto --python_out=./roborock/map/proto roborock/map/proto/b01_scmap.proto
3
+ // python -m grpc_tools.protoc -I. --python_out=. roborock/map/proto/b01_scmap.proto
4
4
  // The generated file `b01_scmap_pb2.py` is checked in for runtime use and should
5
5
  // not be edited by hand.
6
6
  syntax = "proto2";
@@ -47,6 +47,79 @@ message MapDataInfo {
47
47
  optional bytes mapData = 1;
48
48
  }
49
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
+
50
123
  message RoomDataInfo {
51
124
  optional uint32 roomId = 1;
52
125
  optional string roomName = 2;
@@ -66,5 +139,13 @@ message RobotMap {
66
139
  optional MapExtInfo mapExtInfo = 2;
67
140
  optional MapHeadInfo mapHead = 3;
68
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;
69
147
  repeated RoomDataInfo roomDataInfo = 12;
148
+ optional RoomMatrixInfo roomMatrix = 13;
149
+ repeated RoomOutlineInfo roomOutline = 14;
150
+ repeated CarpetDataInfo carpetInfo = 20;
70
151
  }
@@ -24,7 +24,7 @@ _sym_db = _symbol_database.Default()
24
24
 
25
25
 
26
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\"\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\"\xc7\x01\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\x0croomDataInfo\x18\x0c \x03(\x0b\x32\x17.b01.scmap.RoomDataInfo')
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
28
 
29
29
  _globals = globals()
30
30
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -41,8 +41,32 @@ if not _descriptor._USE_C_DESCRIPTORS:
41
41
  _globals['_MAPHEADINFO']._serialized_end=544
42
42
  _globals['_MAPDATAINFO']._serialized_start=546
43
43
  _globals['_MAPDATAINFO']._serialized_end=576
44
- _globals['_ROOMDATAINFO']._serialized_start=579
45
- _globals['_ROOMDATAINFO']._serialized_end=842
46
- _globals['_ROBOTMAP']._serialized_start=845
47
- _globals['_ROBOTMAP']._serialized_end=1044
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
48
72
  # @@protoc_insertion_point(module_scope)