valetudo-map-parser 0.1.9b41__py3-none-any.whl → 0.1.9b42__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.
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  import logging
10
10
 
11
+ from .config.drawable_elements import DrawableElement
11
12
  from .config.types import Color, JsonType, NumpyArray, RobotPosition
12
13
 
13
14
 
@@ -44,8 +45,22 @@ class ImageDraw:
44
45
  color_wall,
45
46
  color_zone_clean,
46
47
  pixel_size,
48
+ disabled_rooms=None,
47
49
  ):
48
- """Draw the base layer of the map."""
50
+ """Draw the base layer of the map.
51
+
52
+ Args:
53
+ img_np_array: The image array to draw on
54
+ compressed_pixels_list: The list of compressed pixels to draw
55
+ layer_type: The type of layer to draw (segment, floor, wall)
56
+ color_wall: The color to use for walls
57
+ color_zone_clean: The color to use for clean zones
58
+ pixel_size: The size of each pixel
59
+ disabled_rooms: A set of room IDs that are disabled
60
+
61
+ Returns:
62
+ A tuple of (room_id, img_np_array)
63
+ """
49
64
  room_id = 0
50
65
 
51
66
  for compressed_pixels in compressed_pixels_list:
@@ -62,7 +77,7 @@ class ImageDraw:
62
77
  )
63
78
  elif layer_type == "wall":
64
79
  img_np_array = await self._process_wall_layer(
65
- img_np_array, pixels, pixel_size, color_wall
80
+ img_np_array, pixels, pixel_size, color_wall, disabled_rooms
66
81
  )
67
82
 
68
83
  return room_id, img_np_array
@@ -71,6 +86,25 @@ class ImageDraw:
71
86
  self, img_np_array, pixels, layer_type, room_id, pixel_size, color_zone_clean
72
87
  ):
73
88
  """Process a room layer (segment or floor)."""
89
+ # Check if this room should be drawn
90
+ draw_room = True
91
+ if layer_type == "segment" and hasattr(self.img_h, "drawing_config"):
92
+ # The room_id is 0-based, but DrawableElement.ROOM_x is 1-based
93
+ current_room_id = room_id + 1
94
+ if 1 <= current_room_id <= 15:
95
+ # Use the DrawableElement imported at the top of the file
96
+
97
+ room_element = getattr(DrawableElement, f"ROOM_{current_room_id}", None)
98
+ if room_element and hasattr(self.img_h.drawing_config, "is_enabled"):
99
+ draw_room = self.img_h.drawing_config.is_enabled(room_element)
100
+ _LOGGER.debug(
101
+ "%s: Room %d is %s",
102
+ self.file_name,
103
+ current_room_id,
104
+ "enabled" if draw_room else "disabled",
105
+ )
106
+
107
+ # Get the room color
74
108
  room_color = self.img_h.shared.rooms_colors[room_id]
75
109
 
76
110
  try:
@@ -79,13 +113,18 @@ class ImageDraw:
79
113
  room_id, room_color, color_zone_clean
80
114
  )
81
115
 
82
- img_np_array = await self.img_h.draw.from_json_to_image(
83
- img_np_array, pixels, pixel_size, room_color
84
- )
116
+ # Only draw the room if it's enabled
117
+ if draw_room:
118
+ img_np_array = await self.img_h.draw.from_json_to_image(
119
+ img_np_array, pixels, pixel_size, room_color
120
+ )
121
+
122
+ # Always increment the room_id, even if the room is not drawn
85
123
  room_id = (room_id + 1) % 16 # Cycle room_id back to 0 after 15
86
124
 
87
125
  except IndexError as e:
88
126
  _LOGGER.warning("%s: Image Draw Error: %s", self.file_name, str(e))
127
+
89
128
  _LOGGER.debug(
90
129
  "%s Active Zones: %s and Room ID: %s",
91
130
  self.file_name,
@@ -104,12 +143,106 @@ class ImageDraw:
104
143
  )
105
144
  return room_color
106
145
 
107
- async def _process_wall_layer(self, img_np_array, pixels, pixel_size, color_wall):
108
- """Process a wall layer."""
109
- return await self.img_h.draw.from_json_to_image(
110
- img_np_array, pixels, pixel_size, color_wall
146
+ async def _process_wall_layer(
147
+ self, img_np_array, pixels, pixel_size, color_wall, disabled_rooms=None
148
+ ):
149
+ """Process a wall layer.
150
+
151
+ Args:
152
+ img_np_array: The image array to draw on
153
+ pixels: The pixels to draw
154
+ pixel_size: The size of each pixel
155
+ color_wall: The color to use for the walls
156
+ disabled_rooms: A set of room IDs that are disabled
157
+
158
+ Returns:
159
+ The updated image array
160
+ """
161
+ # Log the wall color to verify alpha is being passed correctly
162
+ _LOGGER.debug("%s: Drawing walls with color %s", self.file_name, color_wall)
163
+
164
+ # If there are no disabled rooms, draw all walls
165
+ if not disabled_rooms:
166
+ return await self.img_h.draw.from_json_to_image(
167
+ img_np_array, pixels, pixel_size, color_wall
168
+ )
169
+
170
+ # If there are disabled rooms, we need to check each wall pixel
171
+ # to see if it belongs to a disabled room
172
+ _LOGGER.debug(
173
+ "%s: Filtering walls for disabled rooms: %s", self.file_name, disabled_rooms
111
174
  )
112
175
 
176
+ # Get the element map if available
177
+ element_map = getattr(self.img_h, "element_map", None)
178
+ if element_map is None:
179
+ _LOGGER.warning(
180
+ "%s: Element map not available, drawing all walls", self.file_name
181
+ )
182
+ return await self.img_h.draw.from_json_to_image(
183
+ img_np_array, pixels, pixel_size, color_wall
184
+ )
185
+
186
+ # Filter out walls that belong to disabled rooms
187
+ filtered_pixels = []
188
+ for x, y, z in pixels:
189
+ # Check if this wall pixel is adjacent to a disabled room
190
+ # by checking the surrounding pixels in the element map
191
+ is_disabled_room_wall = False
192
+
193
+ # Check the element map at this position and surrounding positions
194
+ # to see if this wall is adjacent to a disabled room
195
+ for dx in range(-1, 2):
196
+ for dy in range(-1, 2):
197
+ # Skip the center pixel
198
+ if dx == 0 and dy == 0:
199
+ continue
200
+
201
+ # Calculate the position to check
202
+ check_x = x + dx
203
+ check_y = y + dy
204
+
205
+ # Make sure the position is within bounds
206
+ if (
207
+ check_x < 0
208
+ or check_y < 0
209
+ or check_x >= element_map.shape[1]
210
+ or check_y >= element_map.shape[0]
211
+ ):
212
+ continue
213
+
214
+ # Get the element at this position
215
+ element = element_map[check_y, check_x]
216
+
217
+ # Check if this element is a disabled room
218
+ # Room elements are in the range 101-115 (ROOM_1 to ROOM_15)
219
+ if 101 <= element <= 115:
220
+ room_id = element - 101 # Convert to 0-based index
221
+ if room_id in disabled_rooms:
222
+ is_disabled_room_wall = True
223
+ break
224
+
225
+ if is_disabled_room_wall:
226
+ break
227
+
228
+ # If this wall is not adjacent to a disabled room, add it to the filtered pixels
229
+ if not is_disabled_room_wall:
230
+ filtered_pixels.append((x, y, z))
231
+
232
+ # Draw the filtered walls
233
+ _LOGGER.debug(
234
+ "%s: Drawing %d of %d wall pixels after filtering",
235
+ self.file_name,
236
+ len(filtered_pixels),
237
+ len(pixels),
238
+ )
239
+ if filtered_pixels:
240
+ return await self.img_h.draw.from_json_to_image(
241
+ img_np_array, filtered_pixels, pixel_size, color_wall
242
+ )
243
+
244
+ return img_np_array
245
+
113
246
  async def async_draw_obstacle(
114
247
  self, np_array: NumpyArray, entity_dict: dict, color_no_go: Color
115
248
  ) -> NumpyArray:
@@ -118,6 +251,7 @@ class ImageDraw:
118
251
  obstacle_data = entity_dict.get("obstacle")
119
252
  except KeyError:
120
253
  _LOGGER.info("%s No obstacle found.", self.file_name)
254
+ return np_array
121
255
  else:
122
256
  obstacle_positions = []
123
257
  if obstacle_data:
@@ -151,6 +285,7 @@ class ImageDraw:
151
285
  charger_pos = entity_dict.get("charger_location")
152
286
  except KeyError:
153
287
  _LOGGER.warning("%s: No charger position found.", self.file_name)
288
+ return np_array
154
289
  else:
155
290
  if charger_pos:
156
291
  charger_pos = charger_pos[0]["points"]
@@ -311,58 +446,57 @@ class ImageDraw:
311
446
  self.img_h.zooming = False
312
447
  return temp
313
448
  # else we need to search and use the async method.
314
- if self.img_h.rooms_pos:
315
- last_room = None
316
- room_count = 0
317
- if self.img_h.robot_in_room:
318
- last_room = self.img_h.robot_in_room
319
- for room in self.img_h.rooms_pos:
320
- corners = room["corners"]
321
- self.img_h.robot_in_room = {
322
- "id": room_count,
323
- "left": int(corners[0][0]),
324
- "right": int(corners[2][0]),
325
- "up": int(corners[0][1]),
326
- "down": int(corners[2][1]),
327
- "room": str(room["name"]),
328
- }
329
- room_count += 1
330
- # Check if the robot coordinates are inside the room's corners
331
- if (
332
- (self.img_h.robot_in_room["right"] >= int(robot_x))
333
- and (self.img_h.robot_in_room["left"] <= int(robot_x))
334
- ) and (
335
- (self.img_h.robot_in_room["down"] >= int(robot_y))
336
- and (self.img_h.robot_in_room["up"] <= int(robot_y))
337
- ):
338
- temp = {
339
- "x": robot_x,
340
- "y": robot_y,
341
- "angle": angle,
342
- "in_room": self.img_h.robot_in_room["room"],
343
- }
344
- _LOGGER.debug(
345
- "%s is in %s room.",
346
- self.file_name,
347
- self.img_h.robot_in_room["room"],
348
- )
349
- del room, corners, robot_x, robot_y # free memory.
350
- return temp
351
- del room, corners # free memory.
352
- _LOGGER.debug(
353
- "%s not located within Camera Rooms coordinates.",
354
- self.file_name,
355
- )
356
- self.img_h.robot_in_room = last_room
357
- self.img_h.zooming = False
358
- temp = {
359
- "x": robot_x,
360
- "y": robot_y,
361
- "angle": angle,
362
- "in_room": last_room["room"] if last_room else None,
449
+ last_room = None
450
+ room_count = 0
451
+ if self.img_h.robot_in_room:
452
+ last_room = self.img_h.robot_in_room
453
+ for room in self.img_h.rooms_pos:
454
+ corners = room["corners"]
455
+ self.img_h.robot_in_room = {
456
+ "id": room_count,
457
+ "left": int(corners[0][0]),
458
+ "right": int(corners[2][0]),
459
+ "up": int(corners[0][1]),
460
+ "down": int(corners[2][1]),
461
+ "room": str(room["name"]),
363
462
  }
364
- # If the robot is not inside any room, return a default value
365
- return temp
463
+ room_count += 1
464
+ # Check if the robot coordinates are inside the room's corners
465
+ if (
466
+ (self.img_h.robot_in_room["right"] >= int(robot_x))
467
+ and (self.img_h.robot_in_room["left"] <= int(robot_x))
468
+ ) and (
469
+ (self.img_h.robot_in_room["down"] >= int(robot_y))
470
+ and (self.img_h.robot_in_room["up"] <= int(robot_y))
471
+ ):
472
+ temp = {
473
+ "x": robot_x,
474
+ "y": robot_y,
475
+ "angle": angle,
476
+ "in_room": self.img_h.robot_in_room["room"],
477
+ }
478
+ _LOGGER.debug(
479
+ "%s is in %s room.",
480
+ self.file_name,
481
+ self.img_h.robot_in_room["room"],
482
+ )
483
+ del room, corners, robot_x, robot_y # free memory.
484
+ return temp
485
+ del room, corners # free memory.
486
+ _LOGGER.debug(
487
+ "%s not located within Camera Rooms coordinates.",
488
+ self.file_name,
489
+ )
490
+ self.img_h.robot_in_room = last_room
491
+ self.img_h.zooming = False
492
+ temp = {
493
+ "x": robot_x,
494
+ "y": robot_y,
495
+ "angle": angle,
496
+ "in_room": last_room["room"] if last_room else None,
497
+ }
498
+ # If the robot is not inside any room, return a default value
499
+ return temp
366
500
 
367
501
  async def async_get_robot_position(self, entity_dict: dict) -> tuple | None:
368
502
  """Get the robot position from the entity data."""