valetudo-map-parser 0.1.9b100__py3-none-any.whl → 0.1.10__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 (33) hide show
  1. valetudo_map_parser/__init__.py +24 -8
  2. valetudo_map_parser/config/auto_crop.py +2 -27
  3. valetudo_map_parser/config/color_utils.py +3 -4
  4. valetudo_map_parser/config/colors.py +2 -2
  5. valetudo_map_parser/config/drawable.py +102 -153
  6. valetudo_map_parser/config/drawable_elements.py +0 -2
  7. valetudo_map_parser/config/fonts/FiraSans.ttf +0 -0
  8. valetudo_map_parser/config/fonts/Inter-VF.ttf +0 -0
  9. valetudo_map_parser/config/fonts/Lato-Regular.ttf +0 -0
  10. valetudo_map_parser/config/fonts/MPLUSRegular.ttf +0 -0
  11. valetudo_map_parser/config/fonts/NotoKufiArabic-VF.ttf +0 -0
  12. valetudo_map_parser/config/fonts/NotoSansCJKhk-VF.ttf +0 -0
  13. valetudo_map_parser/config/fonts/NotoSansKhojki.ttf +0 -0
  14. valetudo_map_parser/config/rand256_parser.py +169 -44
  15. valetudo_map_parser/config/shared.py +103 -101
  16. valetudo_map_parser/config/status_text/status_text.py +96 -0
  17. valetudo_map_parser/config/status_text/translations.py +280 -0
  18. valetudo_map_parser/config/types.py +42 -13
  19. valetudo_map_parser/config/utils.py +221 -181
  20. valetudo_map_parser/hypfer_draw.py +6 -169
  21. valetudo_map_parser/hypfer_handler.py +40 -130
  22. valetudo_map_parser/map_data.py +403 -84
  23. valetudo_map_parser/rand256_handler.py +53 -197
  24. valetudo_map_parser/reimg_draw.py +14 -24
  25. valetudo_map_parser/rooms_handler.py +3 -18
  26. {valetudo_map_parser-0.1.9b100.dist-info → valetudo_map_parser-0.1.10.dist-info}/METADATA +7 -4
  27. valetudo_map_parser-0.1.10.dist-info/RECORD +34 -0
  28. {valetudo_map_parser-0.1.9b100.dist-info → valetudo_map_parser-0.1.10.dist-info}/WHEEL +1 -1
  29. valetudo_map_parser/config/enhanced_drawable.py +0 -324
  30. valetudo_map_parser/hypfer_rooms_handler.py +0 -599
  31. valetudo_map_parser-0.1.9b100.dist-info/RECORD +0 -27
  32. {valetudo_map_parser-0.1.9b100.dist-info → valetudo_map_parser-0.1.10.dist-info/licenses}/LICENSE +0 -0
  33. {valetudo_map_parser-0.1.9b100.dist-info → valetudo_map_parser-0.1.10.dist-info/licenses}/NOTICE.txt +0 -0
@@ -2,19 +2,18 @@
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.a6
5
+ Version: 0.1.10
6
6
  """
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
- import logging
11
10
  import uuid
12
11
  from typing import Any
13
12
 
14
13
  import numpy as np
14
+ from mvcrender.autocrop import AutoCrop
15
15
 
16
- from .config.async_utils import AsyncNumPy, AsyncPIL
17
- from .config.auto_crop import AutoCrop
16
+ from .config.async_utils import AsyncPIL
18
17
  from .config.drawable_elements import DrawableElement
19
18
  from .config.types import (
20
19
  COLORS,
@@ -26,23 +25,18 @@ from .config.types import (
26
25
  RobotPosition,
27
26
  RoomsProperties,
28
27
  RoomStore,
29
- WebPBytes,
28
+ LOGGER,
30
29
  )
31
30
  from .config.utils import (
32
31
  BaseHandler,
33
32
  initialize_drawing_config,
34
- manage_drawable_elements,
35
- numpy_to_webp_bytes,
36
- prepare_resize_params,
33
+ point_in_polygon,
37
34
  )
38
35
  from .map_data import RandImageData
39
36
  from .reimg_draw import ImageDraw
40
37
  from .rooms_handler import RandRoomsHandler
41
38
 
42
39
 
43
- _LOGGER = logging.getLogger(__name__)
44
-
45
-
46
40
  # noinspection PyTypeChecker
47
41
  class ReImageHandler(BaseHandler, AutoCrop):
48
42
  """
@@ -60,9 +54,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
60
54
  self.data = RandImageData # Image Data
61
55
 
62
56
  # Initialize drawing configuration using the shared utility function
63
- self.drawing_config, self.draw, self.enhanced_draw = initialize_drawing_config(
64
- self
65
- )
57
+ self.drawing_config, self.draw = initialize_drawing_config(self)
66
58
  self.go_to = None # Go to position data
67
59
  self.img_base_layer = None # Base image layer
68
60
  self.img_rotate = shared_data.image_rotate # Image rotation
@@ -101,56 +93,40 @@ class ReImageHandler(BaseHandler, AutoCrop):
101
93
 
102
94
  # Update self.rooms_pos from room_properties for compatibility with other methods
103
95
  self.rooms_pos = []
104
- room_ids = [] # Collect room IDs for shared.map_rooms
105
96
  for room_id, room_data in room_properties.items():
106
97
  self.rooms_pos.append(
107
98
  {"name": room_data["name"], "outline": room_data["outline"]}
108
99
  )
109
- # Store the room number (segment ID) for MQTT active zone mapping
110
- room_ids.append(room_data["number"])
111
-
112
- # Update shared.map_rooms with the room IDs for MQTT active zone mapping
113
- self.shared.map_rooms = room_ids
114
- _LOGGER.debug("Updated shared.map_rooms with room IDs: %s", room_ids)
115
100
 
101
+ # Update shared.map_rooms with the full room properties (consistent with Hypfer)
102
+ self.shared.map_rooms = room_properties
116
103
  # get the zones and points data
117
- zone_properties = await self.async_zone_propriety(zones_data)
104
+ self.shared.map_pred_zones = await self.async_zone_propriety(zones_data)
118
105
  # get the points data
119
- point_properties = await self.async_points_propriety(points_data)
120
-
121
- if room_properties or zone_properties:
122
- extracted_data = [
123
- f"{len(room_properties)} Rooms" if room_properties else None,
124
- f"{len(zone_properties)} Zones" if zone_properties else None,
125
- ]
126
- extracted_data = ", ".join(filter(None, extracted_data))
127
- _LOGGER.debug("Extracted data: %s", extracted_data)
128
- else:
106
+ self.shared.map_pred_points = await self.async_points_propriety(points_data)
107
+
108
+ if not (room_properties or self.shared.map_pred_zones):
129
109
  self.rooms_pos = None
130
- _LOGGER.debug("%s: Rooms and Zones data not available!", self.file_name)
131
110
 
132
- rooms = RoomStore(self.file_name, room_properties)
133
- _LOGGER.debug("Rooms Data: %s", rooms.get_rooms())
134
- return room_properties, zone_properties, point_properties
111
+ _ = RoomStore(self.file_name, room_properties)
112
+ return room_properties
135
113
  except (RuntimeError, ValueError) as e:
136
- _LOGGER.debug(
114
+ LOGGER.warning(
137
115
  "No rooms Data or Error in extract_room_properties: %s",
138
116
  e,
139
117
  exc_info=True,
140
118
  )
141
- return None, None, None
119
+ return None
142
120
 
143
121
  async def get_image_from_rrm(
144
122
  self,
145
123
  m_json: JsonType, # json data
146
124
  destinations: None = None, # MQTT destinations for labels
147
- return_webp: bool = False,
148
- ) -> WebPBytes | PilPNG | None:
125
+ ) -> PilPNG | None:
149
126
  """Generate Images from the json data.
150
127
  @param m_json: The JSON data to use to draw the image.
151
128
  @param destinations: MQTT destinations for labels (unused).
152
- @param return_webp: If True, return WebP bytes; if False, return PIL Image (default).
153
- @return WebPBytes | Image.Image: WebP bytes or PIL Image depending on return_webp parameter.
129
+ @return Image.Image: PIL Image.
154
130
  """
155
131
  colors: Colors = {
156
132
  name: self.shared.user_colors[idx] for idx, name in enumerate(COLORS)
@@ -159,12 +135,12 @@ class ReImageHandler(BaseHandler, AutoCrop):
159
135
 
160
136
  try:
161
137
  if (m_json is not None) and (not isinstance(m_json, tuple)):
162
- _LOGGER.info("%s: Composing the image for the camera.", self.file_name)
138
+ LOGGER.info("%s: Composing the image for the camera.", self.file_name)
163
139
  self.json_data = m_json
164
140
  size_x, size_y = self.data.get_rrm_image_size(m_json)
165
141
  self.img_size = DEFAULT_IMAGE_SIZE
166
142
  self.json_id = str(uuid.uuid4()) # image id
167
- _LOGGER.info("Vacuum Data ID: %s", self.json_id)
143
+ LOGGER.info("Vacuum Data ID: %s", self.json_id)
168
144
 
169
145
  (
170
146
  img_np_array,
@@ -177,9 +153,6 @@ class ReImageHandler(BaseHandler, AutoCrop):
177
153
  # Increment frame number
178
154
  self.frame_number += 1
179
155
  img_np_array = await self.async_copy_array(self.img_base_layer)
180
- _LOGGER.debug(
181
- "%s: Frame number %s", self.file_name, str(self.frame_number)
182
- )
183
156
  if self.frame_number > 5:
184
157
  self.frame_number = 0
185
158
 
@@ -188,20 +161,13 @@ class ReImageHandler(BaseHandler, AutoCrop):
188
161
  img_np_array, m_json, colors, robot_position, robot_position_angle
189
162
  )
190
163
 
191
- # Return WebP bytes or PIL Image based on parameter
192
- if return_webp:
193
- # Convert directly to WebP bytes for better performance
194
- webp_bytes = await numpy_to_webp_bytes(img_np_array)
195
- del img_np_array # free memory
196
- return webp_bytes
197
- else:
198
- # Convert to PIL Image using async utilities
199
- pil_img = await AsyncPIL.async_fromarray(img_np_array, mode="RGBA")
200
- del img_np_array # free memory
201
- return await self._finalize_image(pil_img)
164
+ # Return PIL Image using async utilities
165
+ pil_img = await AsyncPIL.async_fromarray(img_np_array, mode="RGBA")
166
+ del img_np_array # free memory
167
+ return await self._finalize_image(pil_img)
202
168
 
203
169
  except (RuntimeError, RuntimeWarning) as e:
204
- _LOGGER.warning(
170
+ LOGGER.warning(
205
171
  "%s: Runtime Error %s during image creation.",
206
172
  self.file_name,
207
173
  str(e),
@@ -215,6 +181,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
215
181
  async def _setup_robot_and_image(
216
182
  self, m_json, size_x, size_y, colors, destinations
217
183
  ):
184
+ """Set up the elements of the map and the image."""
218
185
  (
219
186
  _,
220
187
  robot_position,
@@ -237,13 +204,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
237
204
  colors["background"],
238
205
  DEFAULT_PIXEL_SIZE,
239
206
  )
240
- _LOGGER.info("%s: Completed base Layers", self.file_name)
241
-
242
- # Update element map for rooms
243
- if 0 < room_id <= 15:
244
- # This is a simplification - in a real implementation we would
245
- # need to identify the exact pixels that belong to each room
246
- pass
207
+ LOGGER.info("%s: Completed base Layers", self.file_name)
247
208
 
248
209
  if room_id > 0 and not self.room_propriety:
249
210
  self.room_propriety = await self.get_rooms_attributes(destinations)
@@ -252,8 +213,10 @@ class ReImageHandler(BaseHandler, AutoCrop):
252
213
  if not self.rooms_pos and not self.room_propriety:
253
214
  self.room_propriety = await self.get_rooms_attributes(destinations)
254
215
 
255
- # Always check robot position for zooming (fallback)
256
- if self.rooms_pos and robot_position and not hasattr(self, "robot_pos"):
216
+ # Always check robot position for zooming (update if room info is missing)
217
+ if self.rooms_pos and robot_position and (
218
+ self.robot_pos is None or "in_room" not in self.robot_pos
219
+ ):
257
220
  self.robot_pos = await self.async_get_robot_in_room(
258
221
  (robot_position[0] * 10),
259
222
  (robot_position[1] * 10),
@@ -300,12 +263,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
300
263
  # Restore original rooms_pos
301
264
  self.rooms_pos = original_rooms_pos
302
265
 
303
- except Exception as e:
304
- _LOGGER.debug(
305
- "%s: Early room extraction failed: %s, falling back to robot-position zoom",
306
- self.file_name,
307
- e,
308
- )
266
+ except (ValueError, KeyError, TypeError):
309
267
  # Fallback to robot-position-based zoom if room extraction fails
310
268
  if (
311
269
  self.shared.image_auto_zoom
@@ -313,16 +271,13 @@ class ReImageHandler(BaseHandler, AutoCrop):
313
271
  and robot_position
314
272
  ):
315
273
  self.zooming = True
316
- _LOGGER.debug(
317
- "%s: Enabling fallback robot-position-based zoom",
318
- self.file_name,
319
- )
320
274
 
321
275
  return self.img_base_layer, robot_position, robot_position_angle
322
276
 
323
277
  async def _draw_map_elements(
324
278
  self, img_np_array, m_json, colors, robot_position, robot_position_angle
325
279
  ):
280
+ """Draw map elements on the image."""
326
281
  # Draw charger if enabled
327
282
  if self.drawing_config.is_enabled(DrawableElement.CHARGER):
328
283
  img_np_array, self.charger_pos = await self.imd.async_draw_charger(
@@ -379,19 +334,10 @@ class ReImageHandler(BaseHandler, AutoCrop):
379
334
  active_zones = self.shared.rand256_active_zone
380
335
  if active_zones and any(zone for zone in active_zones):
381
336
  self.zooming = True
382
- _LOGGER.debug(
383
- "%s: Enabling zoom for Rand256 - active zones detected: %s",
384
- self.file_name,
385
- active_zones,
386
- )
387
337
  else:
388
338
  self.zooming = False
389
- _LOGGER.debug(
390
- "%s: Zoom disabled for Rand256 - no active zones set",
391
- self.file_name,
392
- )
393
339
 
394
- img_np_array = await self.async_auto_trim_and_zoom_image(
340
+ img_np_array = self.auto_trim_and_zoom_image(
395
341
  img_np_array,
396
342
  detect_colour=colors["background"],
397
343
  margin_size=int(self.shared.margins),
@@ -402,77 +348,30 @@ class ReImageHandler(BaseHandler, AutoCrop):
402
348
  return img_np_array
403
349
 
404
350
  async def _finalize_image(self, pil_img):
405
- if not self.shared.image_ref_width or not self.shared.image_ref_height:
406
- _LOGGER.warning(
407
- "Image finalization failed: Invalid image dimensions. Returning original image."
408
- )
409
- return pil_img
351
+ """Finalize the image by resizing if needed."""
352
+ if pil_img is None:
353
+ LOGGER.warning("%s: Image is None. Returning None.", self.file_name)
354
+ return None
410
355
  if self.check_zoom_and_aspect_ratio():
411
- resize_params = prepare_resize_params(self, pil_img, True)
356
+ resize_params = self.prepare_resize_params(pil_img, True)
412
357
  pil_img = await self.async_resize_images(resize_params)
413
- _LOGGER.debug("%s: Frame Completed.", self.file_name)
358
+ else:
359
+ LOGGER.warning(
360
+ "%s: Invalid image dimensions. Returning original image.",
361
+ self.file_name,
362
+ )
414
363
  return pil_img
415
364
 
416
365
  async def get_rooms_attributes(
417
366
  self, destinations: JsonType = None
418
367
  ) -> tuple[RoomsProperties, Any, Any]:
419
368
  """Return the rooms attributes."""
420
- if self.room_propriety:
421
- return self.room_propriety
422
369
  if self.json_data and destinations:
423
- _LOGGER.debug("Checking for rooms data..")
424
370
  self.room_propriety = await self.extract_room_properties(
425
371
  self.json_data, destinations
426
372
  )
427
- if self.room_propriety:
428
- _LOGGER.debug("Got Rooms Attributes.")
429
373
  return self.room_propriety
430
374
 
431
- @staticmethod
432
- def point_in_polygon(x: int, y: int, polygon: list) -> bool:
433
- """
434
- Check if a point is inside a polygon using ray casting algorithm.
435
- Enhanced version with better handling of edge cases.
436
-
437
- Args:
438
- x: X coordinate of the point
439
- y: Y coordinate of the point
440
- polygon: List of (x, y) tuples forming the polygon
441
-
442
- Returns:
443
- True if the point is inside the polygon, False otherwise
444
- """
445
- # Ensure we have a valid polygon with at least 3 points
446
- if len(polygon) < 3:
447
- return False
448
-
449
- # Make sure the polygon is closed (last point equals first point)
450
- if polygon[0] != polygon[-1]:
451
- polygon = polygon + [polygon[0]]
452
-
453
- # Use winding number algorithm for better accuracy
454
- wn = 0 # Winding number counter
455
-
456
- # Loop through all edges of the polygon
457
- for i in range(len(polygon) - 1): # Last vertex is first vertex
458
- p1x, p1y = polygon[i]
459
- p2x, p2y = polygon[i + 1]
460
-
461
- # Test if a point is left/right/on the edge defined by two vertices
462
- if p1y <= y: # Start y <= P.y
463
- if p2y > y: # End y > P.y (upward crossing)
464
- # Point left of edge
465
- if ((p2x - p1x) * (y - p1y) - (x - p1x) * (p2y - p1y)) > 0:
466
- wn += 1 # Valid up intersect
467
- else: # Start y > P.y
468
- if p2y <= y: # End y <= P.y (downward crossing)
469
- # Point right of edge
470
- if ((p2x - p1x) * (y - p1y) - (x - p1x) * (p2y - p1y)) < 0:
471
- wn -= 1 # Valid down intersect
472
-
473
- # If winding number is not 0, the point is inside the polygon
474
- return wn != 0
475
-
476
375
  async def async_get_robot_in_room(
477
376
  self, robot_x: int, robot_y: int, angle: float
478
377
  ) -> RobotPosition:
@@ -482,7 +381,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
482
381
  # If we have outline data, use point_in_polygon for accurate detection
483
382
  if "outline" in self.robot_in_room:
484
383
  outline = self.robot_in_room["outline"]
485
- if self.point_in_polygon(int(robot_x), int(robot_y), outline):
384
+ if point_in_polygon(int(robot_x), int(robot_y), outline):
486
385
  temp = {
487
386
  "x": robot_x,
488
387
  "y": robot_y,
@@ -491,6 +390,12 @@ class ReImageHandler(BaseHandler, AutoCrop):
491
390
  }
492
391
  # Handle active zones
493
392
  self.active_zones = self.shared.rand256_active_zone
393
+ LOGGER.debug(
394
+ "%s: Robot is in %s room (polygon detection). %s",
395
+ self.file_name,
396
+ self.robot_in_room["room"],
397
+ self.active_zones,
398
+ )
494
399
  self.zooming = False
495
400
  if self.active_zones and (
496
401
  self.robot_in_room["id"] in range(len(self.active_zones))
@@ -537,12 +442,6 @@ class ReImageHandler(BaseHandler, AutoCrop):
537
442
  # This helps prevent false positives for points very far from any room
538
443
  map_boundary = 50000 # Typical map size is around 25000-30000 units for Rand25
539
444
  if abs(robot_x) > map_boundary or abs(robot_y) > map_boundary:
540
- _LOGGER.debug(
541
- "%s robot position (%s, %s) is far outside map boundaries.",
542
- self.file_name,
543
- robot_x,
544
- robot_y,
545
- )
546
445
  self.robot_in_room = last_room
547
446
  self.zooming = False
548
447
  temp = {
@@ -555,10 +454,6 @@ class ReImageHandler(BaseHandler, AutoCrop):
555
454
 
556
455
  # Search through all rooms to find which one contains the robot
557
456
  if not self.rooms_pos:
558
- _LOGGER.debug(
559
- "%s: No rooms data available for robot position detection.",
560
- self.file_name,
561
- )
562
457
  self.robot_in_room = last_room
563
458
  self.zooming = False
564
459
  temp = {
@@ -569,13 +464,12 @@ class ReImageHandler(BaseHandler, AutoCrop):
569
464
  }
570
465
  return temp
571
466
 
572
- _LOGGER.debug("%s: Searching for robot in rooms...", self.file_name)
573
467
  for room in self.rooms_pos:
574
468
  # Check if the room has an outline (polygon points)
575
469
  if "outline" in room:
576
470
  outline = room["outline"]
577
471
  # Use point_in_polygon for accurate detection with complex shapes
578
- if self.point_in_polygon(int(robot_x), int(robot_y), outline):
472
+ if point_in_polygon(int(robot_x), int(robot_y), outline):
579
473
  # Robot is in this room
580
474
  self.robot_in_room = {
581
475
  "id": room_count,
@@ -598,19 +492,10 @@ class ReImageHandler(BaseHandler, AutoCrop):
598
492
  else:
599
493
  self.zooming = False
600
494
 
601
- _LOGGER.debug(
602
- "%s is in %s room (polygon detection).",
603
- self.file_name,
604
- self.robot_in_room["room"],
605
- )
606
495
  return temp
607
496
  room_count += 1
608
497
 
609
498
  # Robot not found in any room
610
- _LOGGER.debug(
611
- "%s not located within any room coordinates.",
612
- self.file_name,
613
- )
614
499
  self.robot_in_room = last_room
615
500
  self.zooming = False
616
501
  temp = {
@@ -625,7 +510,7 @@ class ReImageHandler(BaseHandler, AutoCrop):
625
510
  """Return the map calibration data."""
626
511
  if not self.calibration_data and self.crop_img_size:
627
512
  self.calibration_data = []
628
- _LOGGER.info(
513
+ LOGGER.info(
629
514
  "%s: Getting Calibrations points %s",
630
515
  self.file_name,
631
516
  str(self.crop_area),
@@ -643,32 +528,3 @@ class ReImageHandler(BaseHandler, AutoCrop):
643
528
  self.calibration_data.append(calibration_point)
644
529
 
645
530
  return self.calibration_data
646
-
647
- # Element selection methods
648
- def enable_element(self, element_code: DrawableElement) -> None:
649
- """Enable drawing of a specific element."""
650
- self.drawing_config.enable_element(element_code)
651
-
652
- def disable_element(self, element_code: DrawableElement) -> None:
653
- """Disable drawing of a specific element."""
654
- manage_drawable_elements(self, "disable", element_code=element_code)
655
-
656
- def set_elements(self, element_codes: list[DrawableElement]) -> None:
657
- """Enable only the specified elements, disable all others."""
658
- manage_drawable_elements(self, "set_elements", element_codes=element_codes)
659
-
660
- def set_element_property(
661
- self, element_code: DrawableElement, property_name: str, value
662
- ) -> None:
663
- """Set a drawing property for an element."""
664
- manage_drawable_elements(
665
- self,
666
- "set_property",
667
- element_code=element_code,
668
- property_name=property_name,
669
- value=value,
670
- )
671
-
672
- async def async_copy_array(self, original_array):
673
- """Copy the array using async utilities."""
674
- return await AsyncNumPy.async_copy(original_array)
@@ -6,17 +6,12 @@ Version: 0.1.9.b42
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- import logging
10
-
11
9
  from .config.drawable import Drawable
12
10
  from .config.drawable_elements import DrawableElement
13
- from .config.types import Color, JsonType, NumpyArray
11
+ from .config.types import LOGGER, Color, JsonType, NumpyArray
14
12
  from .map_data import ImageData, RandImageData
15
13
 
16
14
 
17
- _LOGGER = logging.getLogger(__name__)
18
-
19
-
20
15
  class ImageDraw:
21
16
  """Class to handle the image creation."""
22
17
 
@@ -48,7 +43,7 @@ class ImageDraw:
48
43
  )
49
44
  return np_array
50
45
  except KeyError as e:
51
- _LOGGER.warning(
46
+ LOGGER.warning(
52
47
  "%s: Error in extraction of go-to target: %s",
53
48
  self.file_name,
54
49
  e,
@@ -70,7 +65,7 @@ class ImageDraw:
70
65
  )
71
66
  except ValueError as e:
72
67
  self.img_h.segment_data = None
73
- _LOGGER.info("%s: No segments data found: %s", self.file_name, e)
68
+ LOGGER.info("%s: No segments data found: %s", self.file_name, e)
74
69
 
75
70
  async def async_draw_base_layer(
76
71
  self,
@@ -87,13 +82,13 @@ class ImageDraw:
87
82
  walls_data = self.data.get_rrm_walls(m_json)
88
83
  floor_data = self.data.get_rrm_floor(m_json)
89
84
 
90
- _LOGGER.info("%s: Empty image with background color", self.file_name)
85
+ LOGGER.info("%s: Empty image with background color", self.file_name)
91
86
  img_np_array = await self.draw.create_empty_image(
92
87
  self.img_h.img_size["x"], self.img_h.img_size["y"], color_background
93
88
  )
94
89
  room_id = 0
95
90
  if self.img_h.frame_number == 0:
96
- _LOGGER.info("%s: Overlapping Layers", self.file_name)
91
+ LOGGER.info("%s: Overlapping Layers", self.file_name)
97
92
 
98
93
  # checking if there are segments too (sorted pixels in the raw data).
99
94
  await self.async_segment_data(m_json, size_x, size_y, pos_top, pos_left)
@@ -148,10 +143,10 @@ class ImageDraw:
148
143
  room_id = 0
149
144
  rooms_list = [color_wall]
150
145
  if not segment_data:
151
- _LOGGER.info("%s: No segments data found.", self.file_name)
146
+ LOGGER.info("%s: No segments data found.", self.file_name)
152
147
  return room_id, img_np_array
153
148
 
154
- _LOGGER.info("%s: Drawing segments.", self.file_name)
149
+ LOGGER.info("%s: Drawing segments.", self.file_name)
155
150
  for pixels in segment_data:
156
151
  room_color = self.img_h.shared.rooms_colors[room_id]
157
152
  rooms_list.append(room_color)
@@ -211,9 +206,8 @@ class ImageDraw:
211
206
  self.data.get_rrm_charger_position(m_json)
212
207
  )
213
208
  except KeyError as e:
214
- _LOGGER.warning("%s: No charger position found: %s", self.file_name, e)
209
+ LOGGER.warning("%s: No charger position found: %s", self.file_name, e)
215
210
  else:
216
- _LOGGER.debug("Charger position: %s", charger_pos)
217
211
  if charger_pos:
218
212
  charger_pos_dictionary = {
219
213
  "x": (charger_pos[0] * 10),
@@ -239,7 +233,7 @@ class ImageDraw:
239
233
  zone_clean = None
240
234
 
241
235
  if zone_clean:
242
- _LOGGER.info("%s: Got zones.", self.file_name)
236
+ LOGGER.info("%s: Got zones.", self.file_name)
243
237
  return await self.draw.zones(np_array, zone_clean, color_zone_clean)
244
238
  return np_array
245
239
 
@@ -253,7 +247,7 @@ class ImageDraw:
253
247
  virtual_walls = None
254
248
 
255
249
  if virtual_walls:
256
- _LOGGER.info("%s: Got virtual walls.", self.file_name)
250
+ LOGGER.info("%s: Got virtual walls.", self.file_name)
257
251
  np_array = await self.draw.draw_virtual_walls(
258
252
  np_array, virtual_walls, color_no_go
259
253
  )
@@ -281,7 +275,7 @@ class ImageDraw:
281
275
  self.data.rrm_valetudo_path_array(path_pixel["points"]), 2
282
276
  )
283
277
  except KeyError as e:
284
- _LOGGER.warning(
278
+ LOGGER.warning(
285
279
  "%s: Error extracting paths data: %s", self.file_name, str(e)
286
280
  )
287
281
  finally:
@@ -298,7 +292,7 @@ class ImageDraw:
298
292
  except (ValueError, KeyError):
299
293
  entity_dict = None
300
294
  else:
301
- _LOGGER.info("%s: Got the points in the json.", self.file_name)
295
+ LOGGER.info("%s: Got the points in the json.", self.file_name)
302
296
  return entity_dict
303
297
 
304
298
  async def async_get_robot_position(self, m_json: JsonType) -> tuple | None:
@@ -311,17 +305,12 @@ class ImageDraw:
311
305
  robot_pos = self.data.rrm_coordinates_to_valetudo(robot_pos_data)
312
306
  angle = self.data.get_rrm_robot_angle(m_json)
313
307
  except (ValueError, KeyError):
314
- _LOGGER.warning("%s No robot position found.", self.file_name)
308
+ LOGGER.warning("%s No robot position found.", self.file_name)
315
309
  return None, None, None
316
310
  finally:
317
311
  robot_position_angle = round(angle[0], 0)
318
312
  if robot_pos and robot_position_angle:
319
313
  robot_position = robot_pos
320
- _LOGGER.debug(
321
- "robot position: %s, robot angle: %s",
322
- str(robot_pos),
323
- str(robot_position_angle),
324
- )
325
314
  if self.img_h.rooms_pos is None:
326
315
  self.img_h.robot_pos = {
327
316
  "x": robot_position[0] * 10,
@@ -351,6 +340,7 @@ class ImageDraw:
351
340
  y=robot_pos[1],
352
341
  angle=robot_angle,
353
342
  fill=color_robot,
343
+ radius=self.img_h.shared.robot_size,
354
344
  robot_state=self.img_h.shared.vacuum_state,
355
345
  )
356
346
  return np_array