valetudo-map-parser 0.1.7__py3-none-any.whl → 0.1.9a0__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 (30) hide show
  1. valetudo_map_parser/__init__.py +28 -13
  2. valetudo_map_parser/config/async_utils.py +93 -0
  3. valetudo_map_parser/config/auto_crop.py +312 -123
  4. valetudo_map_parser/config/color_utils.py +105 -0
  5. valetudo_map_parser/config/colors.py +662 -13
  6. valetudo_map_parser/config/drawable.py +613 -268
  7. valetudo_map_parser/config/drawable_elements.py +292 -0
  8. valetudo_map_parser/config/enhanced_drawable.py +324 -0
  9. valetudo_map_parser/config/optimized_element_map.py +406 -0
  10. valetudo_map_parser/config/rand256_parser.py +395 -0
  11. valetudo_map_parser/config/shared.py +94 -11
  12. valetudo_map_parser/config/types.py +105 -52
  13. valetudo_map_parser/config/utils.py +1025 -0
  14. valetudo_map_parser/hypfer_draw.py +464 -148
  15. valetudo_map_parser/hypfer_handler.py +366 -259
  16. valetudo_map_parser/hypfer_rooms_handler.py +599 -0
  17. valetudo_map_parser/map_data.py +56 -66
  18. valetudo_map_parser/rand256_handler.py +674 -0
  19. valetudo_map_parser/reimg_draw.py +68 -84
  20. valetudo_map_parser/rooms_handler.py +474 -0
  21. valetudo_map_parser-0.1.9a0.dist-info/METADATA +93 -0
  22. valetudo_map_parser-0.1.9a0.dist-info/RECORD +27 -0
  23. {valetudo_map_parser-0.1.7.dist-info → valetudo_map_parser-0.1.9a0.dist-info}/WHEEL +1 -1
  24. valetudo_map_parser/config/rand25_parser.py +0 -398
  25. valetudo_map_parser/images_utils.py +0 -398
  26. valetudo_map_parser/rand25_handler.py +0 -455
  27. valetudo_map_parser-0.1.7.dist-info/METADATA +0 -23
  28. valetudo_map_parser-0.1.7.dist-info/RECORD +0 -20
  29. {valetudo_map_parser-0.1.7.dist-info → valetudo_map_parser-0.1.9a0.dist-info}/LICENSE +0 -0
  30. {valetudo_map_parser-0.1.7.dist-info → valetudo_map_parser-0.1.9a0.dist-info}/NOTICE.txt +0 -0
@@ -0,0 +1,474 @@
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
+
23
+ class RoomsHandler:
24
+ """
25
+ Handler for extracting and managing room data from Hipfer vacuum maps.
26
+
27
+ This class provides methods to:
28
+ - Extract room outlines using the Ramer-Douglas-Peucker algorithm
29
+ - Process room properties from JSON data
30
+ - Generate room masks and extract contours
31
+
32
+ All methods are async for better integration with the rest of the codebase.
33
+ """
34
+
35
+ def __init__(self, vacuum_id: str, drawing_config: Optional[DrawingConfig] = None):
36
+ """
37
+ Initialize the HipferRoomsHandler.
38
+
39
+ Args:
40
+ vacuum_id: Identifier for the vacuum
41
+ drawing_config: Configuration for which elements to draw (optional)
42
+ """
43
+ self.vacuum_id = vacuum_id
44
+ self.drawing_config = drawing_config
45
+ self.current_json_data = (
46
+ None # Will store the current JSON data being processed
47
+ )
48
+
49
+ @staticmethod
50
+ def sublist(data: list, chunk_size: int) -> list:
51
+ return [data[i : i + chunk_size] for i in range(0, len(data), chunk_size)]
52
+
53
+ @staticmethod
54
+ def convex_hull_outline(mask: np.ndarray) -> list[tuple[int, int]]:
55
+ y_indices, x_indices = np.where(mask > 0)
56
+ if len(x_indices) == 0 or len(y_indices) == 0:
57
+ return []
58
+
59
+ points = np.column_stack((x_indices, y_indices))
60
+ if len(points) < 3:
61
+ return [(int(x), int(y)) for x, y in points]
62
+
63
+ hull = ConvexHull(points)
64
+ # Convert numpy.int64 values to regular Python integers
65
+ hull_points = [
66
+ (int(points[vertex][0]), int(points[vertex][1])) for vertex in hull.vertices
67
+ ]
68
+ if hull_points[0] != hull_points[-1]:
69
+ hull_points.append(hull_points[0])
70
+ return hull_points
71
+
72
+ async def _process_room_layer(
73
+ self, layer: Dict[str, Any], width: int, height: int, pixel_size: int
74
+ ) -> Tuple[Optional[str], Optional[Dict[str, Any]]]:
75
+ """Process a single room layer and extract its outline.
76
+
77
+ Args:
78
+ layer: The layer data from the JSON
79
+ width: The width of the map
80
+ height: The height of the map
81
+ pixel_size: The size of each pixel
82
+
83
+ Returns:
84
+ Tuple of (room_id, room_data) or (None, None) if processing failed
85
+ """
86
+ meta_data = layer.get("metaData", {})
87
+ segment_id = meta_data.get("segmentId")
88
+ name = meta_data.get("name", "Room {}".format(segment_id))
89
+ compressed_pixels = layer.get("compressedPixels", [])
90
+ pixels = self.sublist(compressed_pixels, 3)
91
+
92
+ # Check if this room is enabled in the drawing configuration
93
+ if self.drawing_config is not None:
94
+ # Convert segment_id to room element (ROOM_1 to ROOM_15)
95
+ try:
96
+ # Segment IDs might not be sequential, so we need to map them to room elements
97
+ # We'll use a simple approach: if segment_id is an integer, use it directly
98
+ room_element_id = int(segment_id)
99
+ if 1 <= room_element_id <= 15:
100
+ room_element = getattr(
101
+ DrawableElement, f"ROOM_{room_element_id}", None
102
+ )
103
+ if room_element:
104
+ is_enabled = self.drawing_config.is_enabled(room_element)
105
+ if not is_enabled:
106
+ # Skip this room if it's disabled
107
+ LOGGER.debug("Skipping disabled room %s", segment_id)
108
+ return None, None
109
+ except (ValueError, TypeError):
110
+ # If segment_id is not a valid integer, we can't map it to a room element
111
+ # In this case, we'll include the room (fail open)
112
+ LOGGER.debug(
113
+ "Could not convert segment_id %s to room element", segment_id
114
+ )
115
+
116
+ # Optimization: Create a smaller mask for just the room area
117
+ if not pixels:
118
+ # Skip if no pixels
119
+ return None, None
120
+
121
+ # Convert to numpy arrays for vectorized operations
122
+ pixel_data = np.array(pixels)
123
+
124
+ if pixel_data.size == 0:
125
+ return None, None
126
+
127
+ # Find the actual bounds of the room to create a smaller mask
128
+ # Add padding to ensure we don't lose edge details
129
+ padding = 10 # Add padding pixels around the room
130
+ min_x = max(0, int(np.min(pixel_data[:, 0])) - padding)
131
+ max_x = min(
132
+ width, int(np.max(pixel_data[:, 0]) + np.max(pixel_data[:, 2])) + padding
133
+ )
134
+ min_y = max(0, int(np.min(pixel_data[:, 1])) - padding)
135
+ max_y = min(height, int(np.max(pixel_data[:, 1]) + 1) + padding)
136
+
137
+ # Create a smaller mask for just the room area (much faster)
138
+ local_width = max_x - min_x
139
+ local_height = max_y - min_y
140
+
141
+ # Skip if dimensions are invalid
142
+ if local_width <= 0 or local_height <= 0:
143
+ return None, None
144
+
145
+ # Create a smaller mask
146
+ local_mask = np.zeros((local_height, local_width), dtype=np.uint8)
147
+
148
+ # Fill the mask efficiently
149
+ for x, y, length in pixel_data:
150
+ x, y, length = int(x), int(y), int(length)
151
+ # Adjust coordinates to local mask
152
+ local_x = x - min_x
153
+ local_y = y - min_y
154
+
155
+ # Ensure we're within bounds
156
+ if 0 <= local_y < local_height and 0 <= local_x < local_width:
157
+ # Calculate the end point, clamping to mask width
158
+ end_x = min(local_x + length, local_width)
159
+ if end_x > local_x: # Only process if there's a valid segment
160
+ local_mask[local_y, local_x:end_x] = 1
161
+
162
+ # Apply morphological operations
163
+ struct_elem = np.ones((3, 3), dtype=np.uint8)
164
+ eroded = binary_erosion(local_mask, structure=struct_elem, iterations=1)
165
+ mask = binary_dilation(eroded, structure=struct_elem, iterations=1).astype(
166
+ np.uint8
167
+ )
168
+
169
+ # Extract contour from the mask
170
+ outline = self.convex_hull_outline(mask)
171
+ if not outline:
172
+ return None, None
173
+
174
+ # Adjust coordinates back to global space
175
+ outline = [(x + min_x, y + min_y) for (x, y) in outline]
176
+
177
+ # Use coordinates as-is without flipping Y coordinates
178
+ xs, ys = zip(*outline)
179
+ x_min, x_max = min(xs), max(xs)
180
+ y_min, y_max = min(ys), max(ys)
181
+
182
+ room_id = str(segment_id)
183
+
184
+ # Scale coordinates by pixel_size and convert to regular Python integers
185
+ scaled_outline = [
186
+ (int(x * pixel_size), int(y * pixel_size)) for x, y in outline
187
+ ]
188
+ room_data = {
189
+ "number": segment_id,
190
+ "outline": scaled_outline,
191
+ "name": name,
192
+ "x": int(((x_min + x_max) * pixel_size) // 2),
193
+ "y": int(((y_min + y_max) * pixel_size) // 2),
194
+ }
195
+
196
+ return room_id, room_data
197
+
198
+ async def async_extract_room_properties(self, json_data) -> RoomsProperties:
199
+ """Extract room properties from the JSON data.
200
+
201
+ This method processes all room layers in the JSON data and extracts their outlines.
202
+ It respects the drawing configuration, skipping rooms that are disabled.
203
+
204
+ Args:
205
+ json_data: The JSON data from the vacuum
206
+
207
+ Returns:
208
+ Dictionary of room properties
209
+ """
210
+ start_total = time.time()
211
+ room_properties = {}
212
+ pixel_size = json_data.get("pixelSize", 5)
213
+ height = json_data["size"]["y"]
214
+ width = json_data["size"]["x"]
215
+
216
+ for layer in json_data.get("layers", []):
217
+ if layer.get("__class") == "MapLayer" and layer.get("type") == "segment":
218
+ room_id, room_data = await self._process_room_layer(
219
+ layer, width, height, pixel_size
220
+ )
221
+ if room_id is not None and room_data is not None:
222
+ room_properties[room_id] = room_data
223
+
224
+ # Log timing information
225
+ total_time = time.time() - start_total
226
+ LOGGER.debug("Room extraction Total time: %.3fs", total_time)
227
+ return room_properties
228
+
229
+
230
+ class RandRoomsHandler:
231
+ """
232
+ Handler for extracting and managing room data from Rand25 vacuum maps.
233
+
234
+ This class provides methods to:
235
+ - Extract room outlines using the Convex Hull algorithm
236
+ - Process room properties from JSON data and destinations JSON
237
+ - Generate room masks and extract contours
238
+
239
+ All methods are async for better integration with the rest of the codebase.
240
+ """
241
+
242
+ def __init__(self, vacuum_id: str, drawing_config: Optional[DrawingConfig] = None):
243
+ """
244
+ Initialize the RandRoomsHandler.
245
+
246
+ Args:
247
+ vacuum_id: Identifier for the vacuum
248
+ drawing_config: Configuration for which elements to draw (optional)
249
+ """
250
+ self.vacuum_id = vacuum_id
251
+ self.drawing_config = drawing_config
252
+ self.current_json_data = (
253
+ None # Will store the current JSON data being processed
254
+ )
255
+ self.segment_data = None # Segment data
256
+ self.outlines = None # Outlines data
257
+
258
+ @staticmethod
259
+ def sublist(data: list, chunk_size: int) -> list:
260
+ """Split a list into chunks of specified size."""
261
+ return [data[i : i + chunk_size] for i in range(0, len(data), chunk_size)]
262
+
263
+ @staticmethod
264
+ def convex_hull_outline(points: List[Tuple[int, int]]) -> List[Tuple[int, int]]:
265
+ """
266
+ Generate a convex hull outline from a set of points.
267
+
268
+ Args:
269
+ points: List of (x, y) coordinate tuples
270
+
271
+ Returns:
272
+ List of (x, y) tuples forming the convex hull outline
273
+ """
274
+ if len(points) == 0:
275
+ return []
276
+
277
+ # Convert to numpy array for processing
278
+ points_array = np.array(points)
279
+
280
+ if len(points) < 3:
281
+ # Not enough points for a convex hull, return the points as is
282
+ return [(int(x), int(y)) for x, y in points_array]
283
+
284
+ try:
285
+ # Calculate the convex hull
286
+ hull = ConvexHull(points_array)
287
+
288
+ # Extract the vertices in order
289
+ hull_points = [
290
+ (int(points_array[vertex][0]), int(points_array[vertex][1]))
291
+ for vertex in hull.vertices
292
+ ]
293
+
294
+ # Close the polygon by adding the first point at the end
295
+ if hull_points[0] != hull_points[-1]:
296
+ hull_points.append(hull_points[0])
297
+
298
+ return hull_points
299
+
300
+ except Exception as e:
301
+ LOGGER.warning(f"Error calculating convex hull: {e}")
302
+
303
+ # Fallback to bounding box if convex hull fails
304
+ x_min, y_min = np.min(points_array, axis=0)
305
+ x_max, y_max = np.max(points_array, axis=0)
306
+
307
+ return [
308
+ (int(x_min), int(y_min)), # Top-left
309
+ (int(x_max), int(y_min)), # Top-right
310
+ (int(x_max), int(y_max)), # Bottom-right
311
+ (int(x_min), int(y_max)), # Bottom-left
312
+ (int(x_min), int(y_min)), # Back to top-left to close the polygon
313
+ ]
314
+
315
+ async def _process_segment_data(
316
+ self, segment_data: List, segment_id: int, pixel_size: int
317
+ ) -> Tuple[Optional[str], Optional[Dict[str, Any]]]:
318
+ """
319
+ Process a single segment and extract its outline.
320
+
321
+ Args:
322
+ segment_data: The segment pixel data
323
+ segment_id: The ID of the segment
324
+ pixel_size: The size of each pixel
325
+
326
+ Returns:
327
+ Tuple of (room_id, room_data) or (None, None) if processing failed
328
+ """
329
+ # Check if this room is enabled in the drawing configuration
330
+ if self.drawing_config is not None:
331
+ try:
332
+ # Convert segment_id to room element (ROOM_1 to ROOM_15)
333
+ room_element_id = int(segment_id)
334
+ if 1 <= room_element_id <= 15:
335
+ room_element = getattr(
336
+ DrawableElement, f"ROOM_{room_element_id}", None
337
+ )
338
+ if room_element:
339
+ is_enabled = self.drawing_config.is_enabled(room_element)
340
+ if not is_enabled:
341
+ # Skip this room if it's disabled
342
+ LOGGER.debug("Skipping disabled room %s", segment_id)
343
+ return None, None
344
+ except (ValueError, TypeError):
345
+ # If segment_id is not a valid integer, we can't map it to a room element
346
+ # In this case, we'll include the room (fail open)
347
+ LOGGER.debug(
348
+ "Could not convert segment_id %s to room element", segment_id
349
+ )
350
+
351
+ # Skip if no pixels
352
+ if not segment_data:
353
+ return None, None
354
+
355
+ # Extract points from segment data
356
+ points = []
357
+ for x, y, _ in segment_data:
358
+ points.append((int(x), int(y)))
359
+
360
+ if not points:
361
+ return None, None
362
+
363
+ # Use convex hull to get the outline
364
+ outline = self.convex_hull_outline(points)
365
+ if not outline:
366
+ return None, None
367
+
368
+ # Calculate bounding box for the room
369
+ xs, ys = zip(*outline)
370
+ x_min, x_max = min(xs), max(xs)
371
+ y_min, y_max = min(ys), max(ys)
372
+
373
+ # Scale coordinates by pixel_size
374
+ scaled_outline = [
375
+ (int(x * pixel_size), int(y * pixel_size)) for x, y in outline
376
+ ]
377
+
378
+ room_id = str(segment_id)
379
+ room_data = {
380
+ "number": segment_id,
381
+ "outline": scaled_outline,
382
+ "name": f"Room {segment_id}", # Default name, will be updated from destinations
383
+ "x": int(((x_min + x_max) * pixel_size) // 2),
384
+ "y": int(((y_min + y_max) * pixel_size) // 2),
385
+ }
386
+
387
+ return room_id, room_data
388
+
389
+ async def async_extract_room_properties(
390
+ self, json_data: Dict[str, Any], destinations: Dict[str, Any]
391
+ ) -> RoomsProperties:
392
+ """
393
+ Extract room properties from the JSON data and destinations.
394
+
395
+ Args:
396
+ json_data: The JSON data from the vacuum
397
+ destinations: The destinations JSON containing room names and IDs
398
+
399
+ Returns:
400
+ Dictionary of room properties
401
+ """
402
+ start_total = time.time()
403
+ room_properties = {}
404
+
405
+ # Get basic map information
406
+ unsorted_id = RandImageData.get_rrm_segments_ids(json_data)
407
+ size_x, size_y = RandImageData.get_rrm_image_size(json_data)
408
+ top, left = RandImageData.get_rrm_image_position(json_data)
409
+ pixel_size = 50 # Rand25 vacuums use a larger pixel size to match the original implementation
410
+
411
+ # Get segment data and outlines if not already available
412
+ if not self.segment_data or not self.outlines:
413
+ (
414
+ self.segment_data,
415
+ self.outlines,
416
+ ) = await RandImageData.async_get_rrm_segments(
417
+ json_data, size_x, size_y, top, left, True
418
+ )
419
+
420
+ # Process destinations JSON to get room names
421
+ dest_json = destinations
422
+ room_data = dest_json.get("rooms", [])
423
+ room_id_to_data = {room["id"]: room for room in room_data}
424
+
425
+ # Process each segment
426
+ if unsorted_id and self.segment_data and self.outlines:
427
+ for idx, segment_id in enumerate(unsorted_id):
428
+ # Extract points from segment data
429
+ points = []
430
+ for x, y, _ in self.segment_data[idx]:
431
+ points.append((int(x), int(y)))
432
+
433
+ if not points:
434
+ continue
435
+
436
+ # Use convex hull to get the outline
437
+ outline = self.convex_hull_outline(points)
438
+ if not outline:
439
+ continue
440
+
441
+ # Scale coordinates by pixel_size
442
+ scaled_outline = [
443
+ (int(x * pixel_size), int(y * pixel_size)) for x, y in outline
444
+ ]
445
+
446
+ # Calculate center point
447
+ xs, ys = zip(*outline)
448
+ x_min, x_max = min(xs), max(xs)
449
+ y_min, y_max = min(ys), max(ys)
450
+ center_x = int(((x_min + x_max) * pixel_size) // 2)
451
+ center_y = int(((y_min + y_max) * pixel_size) // 2)
452
+
453
+ # Create room data
454
+ room_id = str(segment_id)
455
+ room_data = {
456
+ "number": segment_id,
457
+ "outline": scaled_outline,
458
+ "name": f"Room {segment_id}", # Default name, will be updated from destinations
459
+ "x": center_x,
460
+ "y": center_y,
461
+ }
462
+
463
+ # Update room name from destinations if available
464
+ if segment_id in room_id_to_data:
465
+ room_info = room_id_to_data[segment_id]
466
+ room_data["name"] = room_info.get("name", room_data["name"])
467
+
468
+ room_properties[room_id] = room_data
469
+
470
+ # Log timing information
471
+ total_time = time.time() - start_total
472
+ LOGGER.debug("Room extraction Total time: %.3fs", total_time)
473
+
474
+ return room_properties
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.3
2
+ Name: valetudo-map-parser
3
+ Version: 0.1.9a0
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=6RVsd9h44V7VMZLO66QnIsFbAurCKiMeirdYLnTdGXQ,1184
2
+ valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
3
+ valetudo_map_parser/config/async_utils.py,sha256=e1j9uTtg4dhPVWvB2_XgqaH4aeSjRAPz-puRMbGoOs8,3204
4
+ valetudo_map_parser/config/auto_crop.py,sha256=Aes7vfv4z8ihYvGaH5Nryj6Y9mHDerZLIeyvePjf9aQ,19259
5
+ valetudo_map_parser/config/color_utils.py,sha256=nXD6WeNmdFdoMxPDW-JFpjnxJSaZR1jX-ouNfrx6zvE,4502
6
+ valetudo_map_parser/config/colors.py,sha256=DG-oPQoN5gsnwDbEsuFr8a0hRCxmbFHObWa4_5pr-70,29910
7
+ valetudo_map_parser/config/drawable.py,sha256=KpGW4Alm374jeVjsGLhjtiOpsLwxFEDkYD2nNj_G3QU,33139
8
+ valetudo_map_parser/config/drawable_elements.py,sha256=o-5oiXmfqPwNQLzKIhkEcZD_A47rIU9E0CqKgWipxgc,11516
9
+ valetudo_map_parser/config/enhanced_drawable.py,sha256=QlGxlUMVgECUXPtFwIslyjubWxQuhIixsRymWV3lEvk,12586
10
+ valetudo_map_parser/config/optimized_element_map.py,sha256=52BCnkvVv9bre52LeVIfT8nhnEIpc0TuWTv1xcNu0Rk,15744
11
+ valetudo_map_parser/config/rand256_parser.py,sha256=LU3y7XvRRQxVen9iwom0dOaDnJJvhZdg97NqOYRZFas,16279
12
+ valetudo_map_parser/config/shared.py,sha256=98CgGDY0tbc5BSg2TIHbGcDFZZ2acgIYnoPjAwENmBU,12885
13
+ valetudo_map_parser/config/types.py,sha256=saL7pULKAdTRQ_ShR2arT8IV472e9MBC_SohTthlGp8,17567
14
+ valetudo_map_parser/config/utils.py,sha256=p_ez39FPUNXxXSOEJZ16T1eQXzNJwRJN1F30iXx9--w,35095
15
+ valetudo_map_parser/hypfer_draw.py,sha256=mMA0MLmV3Man47VUmj823xwyHprJJmb0nXxmutRNK58,28976
16
+ valetudo_map_parser/hypfer_handler.py,sha256=kXi7f1YGHlC3yPD6knX_8rbJCH8j7uvIOhjdG0C7_as,24061
17
+ valetudo_map_parser/hypfer_rooms_handler.py,sha256=NkpOA6Gdq-2D3lLAxvtNuuWMvPXHxeMY2TO5RZLSHlU,22652
18
+ valetudo_map_parser/map_data.py,sha256=vd4Yjs5FFKrOjA13zyvcZbVrq22EAfUDJp_SDZHwZBU,18924
19
+ valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ valetudo_map_parser/rand256_handler.py,sha256=daaSQ5ktMUYMnYxJkjS75UdBchpXVZ58HIomwHBFivs,27651
21
+ valetudo_map_parser/reimg_draw.py,sha256=LNPEW8jtf7w4R0IM9FMy3YJQzwY21isq9eLhs3ai9o8,12735
22
+ valetudo_map_parser/rooms_handler.py,sha256=ovqQtAjauAqwUNPR0aX27P2zhheQmqfaFhDE3_AwYWk,17821
23
+ valetudo_map_parser-0.1.9a0.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
24
+ valetudo_map_parser-0.1.9a0.dist-info/METADATA,sha256=PahysAy0wwIktTfDWS_qBJRLwMn3ErxP3Q0yCuvqQrk,3320
25
+ valetudo_map_parser-0.1.9a0.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
26
+ valetudo_map_parser-0.1.9a0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
+ valetudo_map_parser-0.1.9a0.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