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.
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/PKG-INFO +1 -1
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/auto_crop.py +4 -9
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/hypfer_draw.py +64 -38
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/hypfer_handler.py +3 -1
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/rand25_handler.py +2 -13
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/pyproject.toml +1 -1
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/LICENSE +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/README.md +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/__init__.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/__init__.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/color_utils.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/colors.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/drawable.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/drawable_elements.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/enhanced_drawable.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/optimized_element_map.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/rand25_parser.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/room_outline.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/shared.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/types.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/utils.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/hypfer_rooms_handler.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/map_data.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/py.typed +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/reimg_draw.py +0 -0
- {valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/rooms_handler.py +0 -0
@@ -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
|
-
|
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])
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/hypfer_draw.py
RENAMED
@@ -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
|
-
|
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
|
-
|
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 -
|
594
|
+
# Handle active zones - Map segment ID to active_zones position
|
578
595
|
if self.img_h.active_zones:
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
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
|
624
|
-
|
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.
|
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
|
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))
|
File without changes
|
File without changes
|
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/colors.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/shared.py
RENAMED
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/types.py
RENAMED
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/config/utils.py
RENAMED
File without changes
|
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/map_data.py
RENAMED
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/py.typed
RENAMED
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/reimg_draw.py
RENAMED
File without changes
|
{valetudo_map_parser-0.1.9a6 → valetudo_map_parser-0.1.9a8}/SCR/valetudo_map_parser/rooms_handler.py
RENAMED
File without changes
|