valetudo-map-parser 0.1.9a6__tar.gz → 0.1.9a8__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.
Files changed (27) hide show
  1. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/PKG-INFO +1 -1
  2. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/auto_crop.py +4 -9
  3. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/hypfer_draw.py +64 -38
  4. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/hypfer_handler.py +3 -1
  5. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/rand25_handler.py +2 -13
  6. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/pyproject.toml +1 -1
  7. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/LICENSE +0 -0
  8. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/NOTICE.txt +0 -0
  9. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/README.md +0 -0
  10. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/__init__.py +0 -0
  11. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/__init__.py +0 -0
  12. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/color_utils.py +0 -0
  13. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/colors.py +0 -0
  14. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/drawable.py +0 -0
  15. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/drawable_elements.py +0 -0
  16. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/enhanced_drawable.py +0 -0
  17. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/optimized_element_map.py +0 -0
  18. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/rand25_parser.py +0 -0
  19. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/room_outline.py +0 -0
  20. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/shared.py +0 -0
  21. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/types.py +0 -0
  22. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/utils.py +0 -0
  23. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/hypfer_rooms_handler.py +0 -0
  24. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/map_data.py +0 -0
  25. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/py.typed +0 -0
  26. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/reimg_draw.py +0 -0
  27. {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/rooms_handler.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: valetudo-map-parser
3
- Version: 0.1.9a6
3
+ Version: 0.1.9a8
4
4
  Summary: A Python library to parse Valetudo map data returning a PIL Image object.
5
5
  License: Apache-2.0
6
6
  Author: Sandro Cantarella
@@ -7,6 +7,7 @@ import logging
7
7
 
8
8
  import numpy as np
9
9
  from numpy import rot90
10
+ from scipy import ndimage
10
11
 
11
12
  from .types import Color, NumpyArray, TrimCropData, TrimsData
12
13
  from .utils import BaseHandler
@@ -89,7 +90,7 @@ class AutoCrop:
89
90
 
90
91
  async def _async_auto_crop_data(self, tdata: TrimsData): # , tdata=None
91
92
  """Load the auto crop data from the Camera config."""
92
- _LOGGER.debug("Auto Crop data: %s, %s", str(tdata), str(self.auto_crop))
93
+ _LOGGER.debug("Auto Crop init data: %s, %s", str(tdata), str(self.auto_crop))
93
94
  if not self.auto_crop:
94
95
  trims_data = TrimCropData.from_dict(dict(tdata.to_dict())).to_list()
95
96
  (
@@ -139,7 +140,7 @@ class AutoCrop:
139
140
  ) -> tuple[int, int, int, int]:
140
141
  """Crop the image based on the auto crop area using scipy.ndimage for better performance."""
141
142
  # Import scipy.ndimage here to avoid import at module level
142
- from scipy import ndimage
143
+
143
144
 
144
145
  # Create a binary mask where True = non-background pixels
145
146
  # This is much more memory efficient than storing coordinates
@@ -269,7 +270,7 @@ class AutoCrop:
269
270
 
270
271
  # Get the current room name from robot_pos (not robot_in_room)
271
272
  current_room = self.handler.robot_pos.get("in_room") if self.handler.robot_pos else None
272
-
273
+ _LOGGER.info(f"Current room: {current_room}")
273
274
 
274
275
  if not current_room:
275
276
  # For Rand256 handler, try to zoom based on robot position even without room data
@@ -303,12 +304,9 @@ class AutoCrop:
303
304
  self.auto_crop[0] : self.auto_crop[2],
304
305
  ]
305
306
 
306
-
307
-
308
307
  # Calculate bounding box from room outline
309
308
  bounding_box = await self.async_get_room_bounding_box(current_room, rand256)
310
309
 
311
-
312
310
  if not bounding_box:
313
311
  _LOGGER.warning(
314
312
  "%s: Could not calculate bounding box for room '%s'. Using full image.",
@@ -328,9 +326,6 @@ class AutoCrop:
328
326
  trim_right = right + margin_size
329
327
  trim_up = up - margin_size
330
328
  trim_down = down + margin_size
331
-
332
-
333
-
334
329
  # Ensure valid trim values
335
330
  trim_left, trim_right = sorted([trim_left, trim_right])
336
331
  trim_up, trim_down = sorted([trim_up, trim_down])
@@ -426,6 +426,39 @@ class ImageDraw:
426
426
  _LOGGER.info("%s: Got the points in the json.", self.file_name)
427
427
  return entity_dict
428
428
 
429
+ def _check_active_zone_and_set_zooming(self) -> None:
430
+ """Helper function to check active zones and set zooming state."""
431
+ if self.img_h.active_zones and self.img_h.robot_in_room:
432
+ from .config.types import RoomStore
433
+ segment_id = str(self.img_h.robot_in_room["id"])
434
+ room_store = RoomStore(self.file_name)
435
+ room_keys = list(room_store.get_rooms().keys())
436
+
437
+ _LOGGER.debug(
438
+ "%s: Active zones debug - segment_id: %s, room_keys: %s, active_zones: %s",
439
+ self.file_name, segment_id, room_keys, self.img_h.active_zones
440
+ )
441
+
442
+ if segment_id in room_keys:
443
+ position = room_keys.index(segment_id)
444
+ _LOGGER.debug(
445
+ "%s: Segment ID %s found at position %s, active_zones[%s] = %s",
446
+ self.file_name, segment_id, position, position,
447
+ self.img_h.active_zones[position] if position < len(self.img_h.active_zones) else "OUT_OF_BOUNDS"
448
+ )
449
+ if position < len(self.img_h.active_zones):
450
+ self.img_h.zooming = bool(self.img_h.active_zones[position])
451
+ else:
452
+ self.img_h.zooming = False
453
+ else:
454
+ _LOGGER.warning(
455
+ "%s: Segment ID %s not found in room_keys %s",
456
+ self.file_name, segment_id, room_keys
457
+ )
458
+ self.img_h.zooming = False
459
+ else:
460
+ self.img_h.zooming = False
461
+
429
462
  @staticmethod
430
463
  def point_in_polygon(x: int, y: int, polygon: list) -> bool:
431
464
  """
@@ -474,15 +507,7 @@ class ImageDraw:
474
507
  "in_room": self.img_h.robot_in_room["room"],
475
508
  }
476
509
  # Handle active zones
477
- if self.img_h.active_zones and (
478
- self.img_h.robot_in_room["id"]
479
- in range(len(self.img_h.active_zones))
480
- ):
481
- self.img_h.zooming = bool(
482
- self.img_h.active_zones[self.img_h.robot_in_room["id"]]
483
- )
484
- else:
485
- self.img_h.zooming = False
510
+ self._check_active_zone_and_set_zooming()
486
511
  return temp
487
512
  # Fallback to bounding box check if no outline data
488
513
  elif all(
@@ -502,15 +527,7 @@ class ImageDraw:
502
527
  "in_room": self.img_h.robot_in_room["room"],
503
528
  }
504
529
  # Handle active zones
505
- if self.img_h.active_zones and (
506
- self.img_h.robot_in_room["id"]
507
- in range(len(self.img_h.active_zones))
508
- ):
509
- self.img_h.zooming = bool(
510
- self.img_h.active_zones[self.img_h.robot_in_room["id"]]
511
- )
512
- else:
513
- self.img_h.zooming = False
530
+ self._check_active_zone_and_set_zooming()
514
531
  return temp
515
532
 
516
533
  # If we don't have a cached room or the robot is not in it, search all rooms
@@ -563,7 +580,7 @@ class ImageDraw:
563
580
  if self.point_in_polygon(int(robot_x), int(robot_y), outline):
564
581
  # Robot is in this room
565
582
  self.img_h.robot_in_room = {
566
- "id": room_count,
583
+ "id": room.get("id", room_count), # Use actual segment ID if available
567
584
  "room": str(room["name"]),
568
585
  "outline": outline,
569
586
  }
@@ -574,15 +591,34 @@ class ImageDraw:
574
591
  "in_room": self.img_h.robot_in_room["room"],
575
592
  }
576
593
 
577
- # Handle active zones - Set zooming based on active zones
594
+ # Handle active zones - Map segment ID to active_zones position
578
595
  if self.img_h.active_zones:
579
- # Convert room ID to integer index
580
- room_id = int(self.img_h.robot_in_room["id"])
581
- if room_id < len(self.img_h.active_zones):
582
- self.img_h.zooming = bool(
583
- self.img_h.active_zones[room_id]
596
+ from .config.types import RoomStore
597
+ segment_id = str(self.img_h.robot_in_room["id"])
598
+ room_store = RoomStore(self.file_name)
599
+ room_keys = list(room_store.get_rooms().keys())
600
+
601
+ _LOGGER.debug(
602
+ "%s: Active zones debug - segment_id: %s, room_keys: %s, active_zones: %s",
603
+ self.file_name, segment_id, room_keys, self.img_h.active_zones
604
+ )
605
+
606
+ if segment_id in room_keys:
607
+ position = room_keys.index(segment_id)
608
+ _LOGGER.debug(
609
+ "%s: Segment ID %s found at position %s, active_zones[%s] = %s",
610
+ self.file_name, segment_id, position, position,
611
+ self.img_h.active_zones[position] if position < len(self.img_h.active_zones) else "OUT_OF_BOUNDS"
584
612
  )
613
+ if position < len(self.img_h.active_zones):
614
+ self.img_h.zooming = bool(self.img_h.active_zones[position])
615
+ else:
616
+ self.img_h.zooming = False
585
617
  else:
618
+ _LOGGER.warning(
619
+ "%s: Segment ID %s not found in room_keys %s",
620
+ self.file_name, segment_id, room_keys
621
+ )
586
622
  self.img_h.zooming = False
587
623
  else:
588
624
  self.img_h.zooming = False
@@ -598,7 +634,7 @@ class ImageDraw:
598
634
  corners = room["corners"]
599
635
  # Create a bounding box from the corners
600
636
  self.img_h.robot_in_room = {
601
- "id": room_count,
637
+ "id": room.get("id", room_count), # Use actual segment ID if available
602
638
  "left": int(corners[0][0]),
603
639
  "right": int(corners[2][0]),
604
640
  "up": int(corners[0][1]),
@@ -620,18 +656,8 @@ class ImageDraw:
620
656
  "in_room": self.img_h.robot_in_room["room"],
621
657
  }
622
658
 
623
- # Handle active zones - Set zooming based on active zones
624
- if self.img_h.active_zones:
625
- # Convert room ID to integer index
626
- room_id = int(self.img_h.robot_in_room["id"])
627
- if room_id < len(self.img_h.active_zones):
628
- self.img_h.zooming = bool(
629
- self.img_h.active_zones[room_id]
630
- )
631
- else:
632
- self.img_h.zooming = False
633
- else:
634
- self.img_h.zooming = False
659
+ # Handle active zones
660
+ self._check_active_zone_and_set_zooming()
635
661
 
636
662
  _LOGGER.debug(
637
663
  "%s is in %s room (bounding box detection).",
@@ -81,7 +81,7 @@ class HypferMapImageHandler(BaseHandler, AutoCrop):
81
81
  self.rooms_pos = []
82
82
  for room_id, room_data in room_properties.items():
83
83
  self.rooms_pos.append(
84
- {"name": room_data["name"], "outline": room_data["outline"]}
84
+ {"id": room_id, "name": room_data["name"], "outline": room_data["outline"]}
85
85
  )
86
86
  else:
87
87
  LOGGER.debug("%s: Rooms data not available!", self.file_name)
@@ -131,6 +131,8 @@ class HypferMapImageHandler(BaseHandler, AutoCrop):
131
131
  # Get the pixels size and layers from the JSON data
132
132
  pixel_size = int(m_json["pixelSize"])
133
133
  layers, active = self.data.find_layers(m_json["layers"], {}, [])
134
+ # Populate active_zones from the JSON data
135
+ self.active_zones = active
134
136
  new_frame_hash = await self.calculate_array_hash(layers, active)
135
137
  if self.frame_number == 0:
136
138
  self.img_hash = new_frame_hash
@@ -2,7 +2,7 @@
2
2
  Image Handler Module for Valetudo Re Vacuums.
3
3
  It returns the PIL PNG image frame relative to the Map Data extrapolated from the vacuum json.
4
4
  It also returns calibration, rooms data to the card and other images information to the camera.
5
- Version: 0.1.9.b42
5
+ Version: 0.1.9.a6
6
6
  """
7
7
 
8
8
  from __future__ import annotations
@@ -264,10 +264,6 @@ class ReImageHandler(BaseHandler, AutoCrop):
264
264
  and robot_position
265
265
  and destinations # Check if we have destinations data for room extraction
266
266
  ):
267
- _LOGGER.debug(
268
- "%s: Attempting early room extraction for active zone checking",
269
- self.file_name
270
- )
271
267
  # Extract room data early if we have destinations
272
268
  try:
273
269
  temp_room_properties = await self.rooms_handler.async_extract_room_properties(
@@ -293,12 +289,6 @@ class ReImageHandler(BaseHandler, AutoCrop):
293
289
  # Restore original rooms_pos
294
290
  self.rooms_pos = original_rooms_pos
295
291
 
296
- _LOGGER.debug(
297
- "%s: Early robot room detection for zoom: robot in %s, zooming=%s",
298
- self.file_name,
299
- robot_room_result.get("in_room", "unknown"),
300
- self.zooming
301
- )
302
292
  except Exception as e:
303
293
  _LOGGER.debug(
304
294
  "%s: Early room extraction failed: %s, falling back to robot-position zoom",
@@ -367,7 +357,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
367
357
  if robot_position:
368
358
  self.robot_position = robot_position
369
359
 
370
- # Check if zoom should be enabled based on active zones
360
+ # Check if Zoom should be enabled based on active zones
371
361
  if (
372
362
  self.shared.image_auto_zoom
373
363
  and self.shared.vacuum_state == "cleaning"
@@ -593,7 +583,6 @@ class ReImageHandler(BaseHandler, AutoCrop):
593
583
 
594
584
  # Handle active zones - Set zooming based on active zones
595
585
  self.active_zones = self.shared.rand256_active_zone
596
- self.zooming = False
597
586
  if self.active_zones and (
598
587
  self.robot_in_room["id"]
599
588
  in range(len(self.active_zones))
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "valetudo-map-parser"
3
- version = "0.1.9a6"
3
+ version = "0.1.9a8"
4
4
  description = "A Python library to parse Valetudo map data returning a PIL Image object."
5
5
  authors = ["Sandro Cantarella <gsca075@gmail.com>"]
6
6
  license = "Apache-2.0"