valetudo-map-parser 0.1.8__py3-none-any.whl → 0.1.9a2__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.
Files changed (28) hide show
  1. valetudo_map_parser/__init__.py +19 -12
  2. valetudo_map_parser/config/auto_crop.py +174 -116
  3. valetudo_map_parser/config/color_utils.py +105 -0
  4. valetudo_map_parser/config/colors.py +662 -13
  5. valetudo_map_parser/config/drawable.py +624 -279
  6. valetudo_map_parser/config/drawable_elements.py +292 -0
  7. valetudo_map_parser/config/enhanced_drawable.py +324 -0
  8. valetudo_map_parser/config/optimized_element_map.py +406 -0
  9. valetudo_map_parser/config/rand25_parser.py +42 -28
  10. valetudo_map_parser/config/room_outline.py +148 -0
  11. valetudo_map_parser/config/shared.py +73 -6
  12. valetudo_map_parser/config/types.py +102 -51
  13. valetudo_map_parser/config/utils.py +841 -0
  14. valetudo_map_parser/hypfer_draw.py +398 -132
  15. valetudo_map_parser/hypfer_handler.py +259 -241
  16. valetudo_map_parser/hypfer_rooms_handler.py +599 -0
  17. valetudo_map_parser/map_data.py +45 -64
  18. valetudo_map_parser/rand25_handler.py +429 -310
  19. valetudo_map_parser/reimg_draw.py +55 -74
  20. valetudo_map_parser/rooms_handler.py +470 -0
  21. valetudo_map_parser-0.1.9a2.dist-info/METADATA +93 -0
  22. valetudo_map_parser-0.1.9a2.dist-info/RECORD +27 -0
  23. {valetudo_map_parser-0.1.8.dist-info → valetudo_map_parser-0.1.9a2.dist-info}/WHEEL +1 -1
  24. valetudo_map_parser/images_utils.py +0 -398
  25. valetudo_map_parser-0.1.8.dist-info/METADATA +0 -23
  26. valetudo_map_parser-0.1.8.dist-info/RECORD +0 -20
  27. {valetudo_map_parser-0.1.8.dist-info → valetudo_map_parser-0.1.9a2.dist-info}/LICENSE +0 -0
  28. {valetudo_map_parser-0.1.8.dist-info → valetudo_map_parser-0.1.9a2.dist-info}/NOTICE.txt +0 -0
@@ -0,0 +1,470 @@
1
+ """
2
+ Hipfer Rooms Handler Module.
3
+ Handles room data extraction and processing for Valetudo Hipfer vacuum maps.
4
+ Provides async methods for room outline extraction and properties management.
5
+ Version: 0.1.9
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import time
11
+ from typing import Any, Dict, List, Optional, Tuple
12
+
13
+ import numpy as np
14
+ from scipy.ndimage import binary_dilation, binary_erosion
15
+ from scipy.spatial import ConvexHull
16
+
17
+ from .config.drawable_elements import DrawableElement, DrawingConfig
18
+ from .config.types import LOGGER, RoomsProperties
19
+
20
+ from .map_data import RandImageData, ImageData
21
+
22
+ class RoomsHandler:
23
+ """
24
+ Handler for extracting and managing room data from Hipfer vacuum maps.
25
+
26
+ This class provides methods to:
27
+ - Extract room outlines using the Ramer-Douglas-Peucker algorithm
28
+ - Process room properties from JSON data
29
+ - Generate room masks and extract contours
30
+
31
+ All methods are async for better integration with the rest of the codebase.
32
+ """
33
+
34
+ def __init__(self, vacuum_id: str, drawing_config: Optional[DrawingConfig] = None):
35
+ """
36
+ Initialize the HipferRoomsHandler.
37
+
38
+ Args:
39
+ vacuum_id: Identifier for the vacuum
40
+ drawing_config: Configuration for which elements to draw (optional)
41
+ """
42
+ self.vacuum_id = vacuum_id
43
+ self.drawing_config = drawing_config
44
+ self.current_json_data = (
45
+ None # Will store the current JSON data being processed
46
+ )
47
+
48
+ @staticmethod
49
+ def sublist(data: list, chunk_size: int) -> list:
50
+ return [data[i : i + chunk_size] for i in range(0, len(data), chunk_size)]
51
+
52
+ @staticmethod
53
+ def convex_hull_outline(mask: np.ndarray) -> list[tuple[int, int]]:
54
+ y_indices, x_indices = np.where(mask > 0)
55
+ if len(x_indices) == 0 or len(y_indices) == 0:
56
+ return []
57
+
58
+ points = np.column_stack((x_indices, y_indices))
59
+ if len(points) < 3:
60
+ return [(int(x), int(y)) for x, y in points]
61
+
62
+ hull = ConvexHull(points)
63
+ # Convert numpy.int64 values to regular Python integers
64
+ hull_points = [
65
+ (int(points[vertex][0]), int(points[vertex][1])) for vertex in hull.vertices
66
+ ]
67
+ if hull_points[0] != hull_points[-1]:
68
+ hull_points.append(hull_points[0])
69
+ return hull_points
70
+
71
+ async def _process_room_layer(
72
+ self, layer: Dict[str, Any], width: int, height: int, pixel_size: int
73
+ ) -> Tuple[Optional[str], Optional[Dict[str, Any]]]:
74
+ """Process a single room layer and extract its outline.
75
+
76
+ Args:
77
+ layer: The layer data from the JSON
78
+ width: The width of the map
79
+ height: The height of the map
80
+ pixel_size: The size of each pixel
81
+
82
+ Returns:
83
+ Tuple of (room_id, room_data) or (None, None) if processing failed
84
+ """
85
+ meta_data = layer.get("metaData", {})
86
+ segment_id = meta_data.get("segmentId")
87
+ name = meta_data.get("name", "Room {}".format(segment_id))
88
+ compressed_pixels = layer.get("compressedPixels", [])
89
+ pixels = self.sublist(compressed_pixels, 3)
90
+
91
+ # Check if this room is enabled in the drawing configuration
92
+ if self.drawing_config is not None:
93
+ # Convert segment_id to room element (ROOM_1 to ROOM_15)
94
+ try:
95
+ # Segment IDs might not be sequential, so we need to map them to room elements
96
+ # We'll use a simple approach: if segment_id is an integer, use it directly
97
+ room_element_id = int(segment_id)
98
+ if 1 <= room_element_id <= 15:
99
+ room_element = getattr(
100
+ DrawableElement, f"ROOM_{room_element_id}", None
101
+ )
102
+ if room_element:
103
+ is_enabled = self.drawing_config.is_enabled(room_element)
104
+ if not is_enabled:
105
+ # Skip this room if it's disabled
106
+ LOGGER.debug("Skipping disabled room %s", segment_id)
107
+ return None, None
108
+ except (ValueError, TypeError):
109
+ # If segment_id is not a valid integer, we can't map it to a room element
110
+ # In this case, we'll include the room (fail open)
111
+ LOGGER.debug(
112
+ "Could not convert segment_id %s to room element", segment_id
113
+ )
114
+
115
+ # Optimization: Create a smaller mask for just the room area
116
+ if not pixels:
117
+ # Skip if no pixels
118
+ return None, None
119
+
120
+ # Convert to numpy arrays for vectorized operations
121
+ pixel_data = np.array(pixels)
122
+
123
+ if pixel_data.size == 0:
124
+ return None, None
125
+
126
+ # Find the actual bounds of the room to create a smaller mask
127
+ # Add padding to ensure we don't lose edge details
128
+ padding = 10 # Add padding pixels around the room
129
+ min_x = max(0, int(np.min(pixel_data[:, 0])) - padding)
130
+ max_x = min(
131
+ width, int(np.max(pixel_data[:, 0]) + np.max(pixel_data[:, 2])) + padding
132
+ )
133
+ min_y = max(0, int(np.min(pixel_data[:, 1])) - padding)
134
+ max_y = min(height, int(np.max(pixel_data[:, 1]) + 1) + padding)
135
+
136
+ # Create a smaller mask for just the room area (much faster)
137
+ local_width = max_x - min_x
138
+ local_height = max_y - min_y
139
+
140
+ # Skip if dimensions are invalid
141
+ if local_width <= 0 or local_height <= 0:
142
+ return None, None
143
+
144
+ # Create a smaller mask
145
+ local_mask = np.zeros((local_height, local_width), dtype=np.uint8)
146
+
147
+ # Fill the mask efficiently
148
+ for x, y, length in pixel_data:
149
+ x, y, length = int(x), int(y), int(length)
150
+ # Adjust coordinates to local mask
151
+ local_x = x - min_x
152
+ local_y = y - min_y
153
+
154
+ # Ensure we're within bounds
155
+ if 0 <= local_y < local_height and 0 <= local_x < local_width:
156
+ # Calculate the end point, clamping to mask width
157
+ end_x = min(local_x + length, local_width)
158
+ if end_x > local_x: # Only process if there's a valid segment
159
+ local_mask[local_y, local_x:end_x] = 1
160
+
161
+ # Apply morphological operations
162
+ struct_elem = np.ones((3, 3), dtype=np.uint8)
163
+ eroded = binary_erosion(local_mask, structure=struct_elem, iterations=1)
164
+ mask = binary_dilation(eroded, structure=struct_elem, iterations=1).astype(
165
+ np.uint8
166
+ )
167
+
168
+ # Extract contour from the mask
169
+ outline = self.convex_hull_outline(mask)
170
+ if not outline:
171
+ return None, None
172
+
173
+ # Adjust coordinates back to global space
174
+ outline = [(x + min_x, y + min_y) for (x, y) in outline]
175
+
176
+ # Use coordinates as-is without flipping Y coordinates
177
+ xs, ys = zip(*outline)
178
+ x_min, x_max = min(xs), max(xs)
179
+ y_min, y_max = min(ys), max(ys)
180
+
181
+ room_id = str(segment_id)
182
+
183
+ # Scale coordinates by pixel_size and convert to regular Python integers
184
+ scaled_outline = [
185
+ (int(x * pixel_size), int(y * pixel_size)) for x, y in outline
186
+ ]
187
+ room_data = {
188
+ "number": segment_id,
189
+ "outline": scaled_outline,
190
+ "name": name,
191
+ "x": int(((x_min + x_max) * pixel_size) // 2),
192
+ "y": int(((y_min + y_max) * pixel_size) // 2),
193
+ }
194
+
195
+ return room_id, room_data
196
+
197
+ async def async_extract_room_properties(self, json_data) -> RoomsProperties:
198
+ """Extract room properties from the JSON data.
199
+
200
+ This method processes all room layers in the JSON data and extracts their outlines.
201
+ It respects the drawing configuration, skipping rooms that are disabled.
202
+
203
+ Args:
204
+ json_data: The JSON data from the vacuum
205
+
206
+ Returns:
207
+ Dictionary of room properties
208
+ """
209
+ start_total = time.time()
210
+ room_properties = {}
211
+ pixel_size = json_data.get("pixelSize", 5)
212
+ height = json_data["size"]["y"]
213
+ width = json_data["size"]["x"]
214
+
215
+ for layer in json_data.get("layers", []):
216
+ if layer.get("__class") == "MapLayer" and layer.get("type") == "segment":
217
+ room_id, room_data = await self._process_room_layer(
218
+ layer, width, height, pixel_size
219
+ )
220
+ if room_id is not None and room_data is not None:
221
+ room_properties[room_id] = room_data
222
+
223
+ # Log timing information
224
+ total_time = time.time() - start_total
225
+ LOGGER.debug("Room extraction Total time: %.3fs", total_time)
226
+ return room_properties
227
+
228
+ class RandRoomsHandler:
229
+ """
230
+ Handler for extracting and managing room data from Rand25 vacuum maps.
231
+
232
+ This class provides methods to:
233
+ - Extract room outlines using the Convex Hull algorithm
234
+ - Process room properties from JSON data and destinations JSON
235
+ - Generate room masks and extract contours
236
+
237
+ All methods are async for better integration with the rest of the codebase.
238
+ """
239
+
240
+ def __init__(self, vacuum_id: str, drawing_config: Optional[DrawingConfig] = None):
241
+ """
242
+ Initialize the RandRoomsHandler.
243
+
244
+ Args:
245
+ vacuum_id: Identifier for the vacuum
246
+ drawing_config: Configuration for which elements to draw (optional)
247
+ """
248
+ self.vacuum_id = vacuum_id
249
+ self.drawing_config = drawing_config
250
+ self.current_json_data = None # Will store the current JSON data being processed
251
+ self.segment_data = None # Segment data
252
+ self.outlines = None # Outlines data
253
+
254
+ @staticmethod
255
+ def sublist(data: list, chunk_size: int) -> list:
256
+ """Split a list into chunks of specified size."""
257
+ return [data[i : i + chunk_size] for i in range(0, len(data), chunk_size)]
258
+
259
+ @staticmethod
260
+ def convex_hull_outline(points: List[Tuple[int, int]]) -> List[Tuple[int, int]]:
261
+ """
262
+ Generate a convex hull outline from a set of points.
263
+
264
+ Args:
265
+ points: List of (x, y) coordinate tuples
266
+
267
+ Returns:
268
+ List of (x, y) tuples forming the convex hull outline
269
+ """
270
+ if len(points) == 0:
271
+ return []
272
+
273
+ # Convert to numpy array for processing
274
+ points_array = np.array(points)
275
+
276
+ if len(points) < 3:
277
+ # Not enough points for a convex hull, return the points as is
278
+ return [(int(x), int(y)) for x, y in points_array]
279
+
280
+ try:
281
+ # Calculate the convex hull
282
+ hull = ConvexHull(points_array)
283
+
284
+ # Extract the vertices in order
285
+ hull_points = [
286
+ (int(points_array[vertex][0]), int(points_array[vertex][1]))
287
+ for vertex in hull.vertices
288
+ ]
289
+
290
+ # Close the polygon by adding the first point at the end
291
+ if hull_points[0] != hull_points[-1]:
292
+ hull_points.append(hull_points[0])
293
+
294
+ return hull_points
295
+
296
+ except Exception as e:
297
+ LOGGER.warning(f"Error calculating convex hull: {e}")
298
+
299
+ # Fallback to bounding box if convex hull fails
300
+ x_min, y_min = np.min(points_array, axis=0)
301
+ x_max, y_max = np.max(points_array, axis=0)
302
+
303
+ return [
304
+ (int(x_min), int(y_min)), # Top-left
305
+ (int(x_max), int(y_min)), # Top-right
306
+ (int(x_max), int(y_max)), # Bottom-right
307
+ (int(x_min), int(y_max)), # Bottom-left
308
+ (int(x_min), int(y_min)), # Back to top-left to close the polygon
309
+ ]
310
+
311
+ async def _process_segment_data(
312
+ self, segment_data: List, segment_id: int, pixel_size: int
313
+ ) -> Tuple[Optional[str], Optional[Dict[str, Any]]]:
314
+ """
315
+ Process a single segment and extract its outline.
316
+
317
+ Args:
318
+ segment_data: The segment pixel data
319
+ segment_id: The ID of the segment
320
+ pixel_size: The size of each pixel
321
+
322
+ Returns:
323
+ Tuple of (room_id, room_data) or (None, None) if processing failed
324
+ """
325
+ # Check if this room is enabled in the drawing configuration
326
+ if self.drawing_config is not None:
327
+ try:
328
+ # Convert segment_id to room element (ROOM_1 to ROOM_15)
329
+ room_element_id = int(segment_id)
330
+ if 1 <= room_element_id <= 15:
331
+ room_element = getattr(
332
+ DrawableElement, f"ROOM_{room_element_id}", None
333
+ )
334
+ if room_element:
335
+ is_enabled = self.drawing_config.is_enabled(room_element)
336
+ if not is_enabled:
337
+ # Skip this room if it's disabled
338
+ LOGGER.debug("Skipping disabled room %s", segment_id)
339
+ return None, None
340
+ except (ValueError, TypeError):
341
+ # If segment_id is not a valid integer, we can't map it to a room element
342
+ # In this case, we'll include the room (fail open)
343
+ LOGGER.debug(
344
+ "Could not convert segment_id %s to room element", segment_id
345
+ )
346
+
347
+ # Skip if no pixels
348
+ if not segment_data:
349
+ return None, None
350
+
351
+ # Extract points from segment data
352
+ points = []
353
+ for x, y, _ in segment_data:
354
+ points.append((int(x), int(y)))
355
+
356
+ if not points:
357
+ return None, None
358
+
359
+ # Use convex hull to get the outline
360
+ outline = self.convex_hull_outline(points)
361
+ if not outline:
362
+ return None, None
363
+
364
+ # Calculate bounding box for the room
365
+ xs, ys = zip(*outline)
366
+ x_min, x_max = min(xs), max(xs)
367
+ y_min, y_max = min(ys), max(ys)
368
+
369
+ # Scale coordinates by pixel_size
370
+ scaled_outline = [
371
+ (int(x * pixel_size), int(y * pixel_size)) for x, y in outline
372
+ ]
373
+
374
+ room_id = str(segment_id)
375
+ room_data = {
376
+ "number": segment_id,
377
+ "outline": scaled_outline,
378
+ "name": f"Room {segment_id}", # Default name, will be updated from destinations
379
+ "x": int(((x_min + x_max) * pixel_size) // 2),
380
+ "y": int(((y_min + y_max) * pixel_size) // 2),
381
+ }
382
+
383
+ return room_id, room_data
384
+
385
+ async def async_extract_room_properties(
386
+ self, json_data: Dict[str, Any], destinations: Dict[str, Any]
387
+ ) -> RoomsProperties:
388
+ """
389
+ Extract room properties from the JSON data and destinations.
390
+
391
+ Args:
392
+ json_data: The JSON data from the vacuum
393
+ destinations: The destinations JSON containing room names and IDs
394
+
395
+ Returns:
396
+ Dictionary of room properties
397
+ """
398
+ start_total = time.time()
399
+ room_properties = {}
400
+
401
+ # Get basic map information
402
+ unsorted_id = RandImageData.get_rrm_segments_ids(json_data)
403
+ size_x, size_y = RandImageData.get_rrm_image_size(json_data)
404
+ top, left = RandImageData.get_rrm_image_position(json_data)
405
+ pixel_size = 50 # Rand25 vacuums use a larger pixel size to match the original implementation
406
+
407
+ # Get segment data and outlines if not already available
408
+ if not self.segment_data or not self.outlines:
409
+ (
410
+ self.segment_data,
411
+ self.outlines,
412
+ ) = await RandImageData.async_get_rrm_segments(
413
+ json_data, size_x, size_y, top, left, True
414
+ )
415
+
416
+ # Process destinations JSON to get room names
417
+ dest_json = destinations
418
+ room_data = dest_json.get("rooms", [])
419
+ room_id_to_data = {room["id"]: room for room in room_data}
420
+
421
+ # Process each segment
422
+ if unsorted_id and self.segment_data and self.outlines:
423
+ for idx, segment_id in enumerate(unsorted_id):
424
+ # Extract points from segment data
425
+ points = []
426
+ for x, y, _ in self.segment_data[idx]:
427
+ points.append((int(x), int(y)))
428
+
429
+ if not points:
430
+ continue
431
+
432
+ # Use convex hull to get the outline
433
+ outline = self.convex_hull_outline(points)
434
+ if not outline:
435
+ continue
436
+
437
+ # Scale coordinates by pixel_size
438
+ scaled_outline = [
439
+ (int(x * pixel_size), int(y * pixel_size)) for x, y in outline
440
+ ]
441
+
442
+ # Calculate center point
443
+ xs, ys = zip(*outline)
444
+ x_min, x_max = min(xs), max(xs)
445
+ y_min, y_max = min(ys), max(ys)
446
+ center_x = int(((x_min + x_max) * pixel_size) // 2)
447
+ center_y = int(((y_min + y_max) * pixel_size) // 2)
448
+
449
+ # Create room data
450
+ room_id = str(segment_id)
451
+ room_data = {
452
+ "number": segment_id,
453
+ "outline": scaled_outline,
454
+ "name": f"Room {segment_id}", # Default name, will be updated from destinations
455
+ "x": center_x,
456
+ "y": center_y,
457
+ }
458
+
459
+ # Update room name from destinations if available
460
+ if segment_id in room_id_to_data:
461
+ room_info = room_id_to_data[segment_id]
462
+ room_data["name"] = room_info.get("name", room_data["name"])
463
+
464
+ room_properties[room_id] = room_data
465
+
466
+ # Log timing information
467
+ total_time = time.time() - start_total
468
+ LOGGER.debug("Room extraction Total time: %.3fs", total_time)
469
+
470
+ return room_properties
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.3
2
+ Name: valetudo-map-parser
3
+ Version: 0.1.9a2
4
+ Summary: A Python library to parse Valetudo map data returning a PIL Image object.
5
+ License: Apache-2.0
6
+ Author: Sandro Cantarella
7
+ Author-email: gsca075@gmail.com
8
+ Requires-Python: >=3.12
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: Pillow (>=10.3.0)
14
+ Requires-Dist: numpy (>=1.26.4)
15
+ Requires-Dist: scipy (>=1.12.0)
16
+ Project-URL: Bug Tracker, https://github.com/sca075/Python-package-valetudo-map-parser/issues
17
+ Project-URL: Changelog, https://github.com/sca075/Python-package-valetudo-map-parser/releases
18
+ Project-URL: Homepage, https://github.com/sca075/Python-package-valetudo-map-parser
19
+ Project-URL: Repository, https://github.com/sca075/Python-package-valetudo-map-parser
20
+ Description-Content-Type: text/markdown
21
+
22
+ # Python-package-valetudo-map-parser
23
+
24
+ ---
25
+ ### What is it:
26
+ ❗This is an _unofficial_ project and is not created, maintained, or in any sense linked to [valetudo.cloud](https://valetudo.cloud)
27
+
28
+ A Python library that converts Valetudo vacuum JSON map data into PIL (Python Imaging Library) images. This package is primarily developed for and used in the [MQTT Vacuum Camera](https://github.com/sca075/mqtt_vacuum_camera) project.
29
+
30
+ ---
31
+
32
+ ### Features:
33
+ - Processes map data from Valetudo-compatible robot vacuums
34
+ - Supports both Hypfer and Rand256 vacuum data formats
35
+ - Renders comprehensive map visualizations including:
36
+ - Walls and obstacles
37
+ - Robot position and cleaning path
38
+ - Room segments and boundaries
39
+ - Cleaning zones
40
+ - Virtual restrictions
41
+ - LiDAR data
42
+ - Provides auto-cropping and dynamic zooming
43
+ - Supports image rotation and aspect ratio management
44
+ - Enables custom color schemes
45
+ - Handles multilingual labels
46
+ - Implements thread-safe data sharing
47
+
48
+ ### Installation:
49
+ ```bash
50
+ pip install valetudo_map_parser
51
+ ```
52
+
53
+ ### Requirements:
54
+ - Python 3.12 or higher
55
+ - Dependencies:
56
+ - Pillow (PIL) for image processing
57
+ - NumPy for array operations
58
+
59
+ ### Usage:
60
+ The library is configured using a dictionary format. See our [sample code](https://github.com/sca075/Python-package-valetudo-map-parser/blob/main/tests/test.py) for implementation examples.
61
+
62
+ Key functionalities:
63
+ - Decodes raw data from Rand256 format
64
+ - Processes JSON data from compatible vacuums
65
+ - Returns Pillow PNG images
66
+ - Provides calibration and room property extraction
67
+ - Supports asynchronous operations
68
+
69
+ ### Development Status:
70
+ Current version: 0.1.9.b41
71
+ - Full functionality available in versions >= 0.1.9
72
+ - Actively maintained and enhanced
73
+ - Uses Poetry for dependency management
74
+ - Implements comprehensive testing
75
+ - Enforces code quality through ruff, isort, and pylint
76
+
77
+ ### Contributing:
78
+ Contributions are welcome! You can help by:
79
+ - Submitting code improvements
80
+ - Enhancing documentation
81
+ - Reporting issues
82
+ - Suggesting new features
83
+
84
+ ### Disclaimer:
85
+ This project is provided "as is" without warranty of any kind. Users assume all risks associated with its use.
86
+
87
+ ### License:
88
+ Apache-2.0
89
+
90
+ ---
91
+ For more information about Valetudo, visit [valetudo.cloud](https://valetudo.cloud)
92
+ Integration with Home Assistant: [MQTT Vacuum Camera](https://github.com/sca075/mqtt_vacuum_camera)
93
+
@@ -0,0 +1,27 @@
1
+ valetudo_map_parser/__init__.py,sha256=Fz-gtKf_OlZcDQqVfGlBwIWi5DJAiRucMbBMdQ2tX_U,1060
2
+ valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
3
+ valetudo_map_parser/config/auto_crop.py,sha256=6xt_wJQqphddWhlrr7MNUkodCi8ZYdRk42qvAaxlYCM,13546
4
+ valetudo_map_parser/config/color_utils.py,sha256=nXD6WeNmdFdoMxPDW-JFpjnxJSaZR1jX-ouNfrx6zvE,4502
5
+ valetudo_map_parser/config/colors.py,sha256=DG-oPQoN5gsnwDbEsuFr8a0hRCxmbFHObWa4_5pr-70,29910
6
+ valetudo_map_parser/config/drawable.py,sha256=2MeVHXqZuVuJk3eerMJYGwo25rVetHx3xB_vxecEFOQ,34168
7
+ valetudo_map_parser/config/drawable_elements.py,sha256=o-5oiXmfqPwNQLzKIhkEcZD_A47rIU9E0CqKgWipxgc,11516
8
+ valetudo_map_parser/config/enhanced_drawable.py,sha256=QlGxlUMVgECUXPtFwIslyjubWxQuhIixsRymWV3lEvk,12586
9
+ valetudo_map_parser/config/optimized_element_map.py,sha256=52BCnkvVv9bre52LeVIfT8nhnEIpc0TuWTv1xcNu0Rk,15744
10
+ valetudo_map_parser/config/rand25_parser.py,sha256=kIayyqVZBfQfAMkiArzqrrj9vqZB3pkgT0Y5ufrQmGA,16448
11
+ valetudo_map_parser/config/room_outline.py,sha256=D20D-yeyKnlmVbW9lI7bsPtQGn2XkcWow6YNOEPnWVg,4800
12
+ valetudo_map_parser/config/shared.py,sha256=Yd0MlAH6DaAfqxrUw1NW2uHxYoLe9IwKxyFowQ6VJWg,12133
13
+ valetudo_map_parser/config/types.py,sha256=TaRKoo7G7WIUw7ljOz2Vn5oYzKaLyQH-7Eb8ZYql8Ls,17464
14
+ valetudo_map_parser/config/utils.py,sha256=CFuuiS5IufEu9aeaZwi7xa1jEF1z6yDZB0mcyVX79Xo,29261
15
+ valetudo_map_parser/hypfer_draw.py,sha256=L1eM8dDLNsi4SOUt9499v9jLbQa1MwDKPfMYHcUEsXQ,26722
16
+ valetudo_map_parser/hypfer_handler.py,sha256=f7y5It8tr__FCadojQsk_FPuMgsnjyUST1scXLZ1tws,20108
17
+ valetudo_map_parser/hypfer_rooms_handler.py,sha256=NkpOA6Gdq-2D3lLAxvtNuuWMvPXHxeMY2TO5RZLSHlU,22652
18
+ valetudo_map_parser/map_data.py,sha256=3CG3l_fWeEwWCT5j9nfnqPuClU01m7exwuYWV3K9jIk,18618
19
+ valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ valetudo_map_parser/rand25_handler.py,sha256=EKf7dhBtLKt_lEFi3hiJwSL0wgX0ZmvWlNMPxS8TDQE,22875
21
+ valetudo_map_parser/reimg_draw.py,sha256=1q8LkNTPHEA9Tsapc_JnVw51kpPYNhaBU-KmHkefCQY,12507
22
+ valetudo_map_parser/rooms_handler.py,sha256=YP8OLotBH-RXluv398l7TTT2zIBHJp91b8THWxl3NdI,17794
23
+ valetudo_map_parser-0.1.9a2.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
24
+ valetudo_map_parser-0.1.9a2.dist-info/METADATA,sha256=DZkyXziGLLJ2QK6P29Unz2P8tBWHVbJNUYe072gg5yU,3320
25
+ valetudo_map_parser-0.1.9a2.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
26
+ valetudo_map_parser-0.1.9a2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
+ valetudo_map_parser-0.1.9a2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.0.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any