valetudo-map-parser 0.1.9b4__py3-none-any.whl → 0.1.9b6__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.
- valetudo_map_parser/config/utils.py +448 -0
- valetudo_map_parser/hypfer_draw.py +0 -21
- valetudo_map_parser/hypfer_handler.py +25 -128
- valetudo_map_parser/rand25_handler.py +12 -101
- valetudo_map_parser/reimg_draw.py +0 -21
- {valetudo_map_parser-0.1.9b4.dist-info → valetudo_map_parser-0.1.9b6.dist-info}/METADATA +1 -1
- {valetudo_map_parser-0.1.9b4.dist-info → valetudo_map_parser-0.1.9b6.dist-info}/RECORD +10 -10
- valetudo_map_parser/images_utils.py +0 -398
- {valetudo_map_parser-0.1.9b4.dist-info → valetudo_map_parser-0.1.9b6.dist-info}/LICENSE +0 -0
- {valetudo_map_parser-0.1.9b4.dist-info → valetudo_map_parser-0.1.9b6.dist-info}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.9b4.dist-info → valetudo_map_parser-0.1.9b6.dist-info}/WHEEL +0 -0
@@ -0,0 +1,448 @@
|
|
1
|
+
"""Utility code for the valetudo map parser."""
|
2
|
+
|
3
|
+
import hashlib
|
4
|
+
import json
|
5
|
+
from logging import getLogger
|
6
|
+
|
7
|
+
from PIL import ImageOps
|
8
|
+
|
9
|
+
from .types import ChargerPosition, ImageSize, NumpyArray, RobotPosition
|
10
|
+
|
11
|
+
_LOGGER = getLogger(__name__)
|
12
|
+
|
13
|
+
|
14
|
+
class BaseHandler:
|
15
|
+
"""Avoid Code duplication"""
|
16
|
+
|
17
|
+
def __init__(self):
|
18
|
+
self.file_name = None
|
19
|
+
self.img_size = None
|
20
|
+
self.json_data = None
|
21
|
+
self.json_id = None
|
22
|
+
self.path_pixels = None
|
23
|
+
self.robot_in_room = None
|
24
|
+
self.robot_pos = None
|
25
|
+
self.room_propriety = None
|
26
|
+
self.rooms_pos = None
|
27
|
+
self.charger_pos = None
|
28
|
+
self.frame_number = 0
|
29
|
+
self.max_frames = 1024
|
30
|
+
self.crop_img_size = [0, 0]
|
31
|
+
self.offset_x = 0
|
32
|
+
self.offset_y = 0
|
33
|
+
self.shared = None
|
34
|
+
|
35
|
+
def get_frame_number(self) -> int:
|
36
|
+
"""Return the frame number of the image."""
|
37
|
+
return self.frame_number
|
38
|
+
|
39
|
+
def get_robot_position(self) -> RobotPosition | None:
|
40
|
+
"""Return the robot position."""
|
41
|
+
return self.robot_pos
|
42
|
+
|
43
|
+
def get_charger_position(self) -> ChargerPosition | None:
|
44
|
+
"""Return the charger position."""
|
45
|
+
return self.charger_pos
|
46
|
+
|
47
|
+
def get_img_size(self) -> ImageSize | None:
|
48
|
+
"""Return the size of the image."""
|
49
|
+
return self.img_size
|
50
|
+
|
51
|
+
def get_json_id(self) -> str | None:
|
52
|
+
"""Return the JSON ID from the image."""
|
53
|
+
return self.json_id
|
54
|
+
|
55
|
+
async def async_resize_image(
|
56
|
+
self, pil_img, width, height, aspect_ratio=None, is_rand=False
|
57
|
+
):
|
58
|
+
"""Resize the image to the given dimensions and aspect ratio."""
|
59
|
+
if aspect_ratio:
|
60
|
+
wsf, hsf = [int(x) for x in aspect_ratio.split(",")]
|
61
|
+
if wsf == 0 or hsf == 0:
|
62
|
+
return pil_img
|
63
|
+
new_aspect_ratio = wsf / hsf
|
64
|
+
if width / height > new_aspect_ratio:
|
65
|
+
new_width = int(pil_img.height * new_aspect_ratio)
|
66
|
+
new_height = pil_img.height
|
67
|
+
else:
|
68
|
+
new_width = pil_img.width
|
69
|
+
new_height = int(pil_img.width / new_aspect_ratio)
|
70
|
+
_LOGGER.debug(
|
71
|
+
"%s: Image Aspect Ratio: %s, %s",
|
72
|
+
self.file_name,
|
73
|
+
str(wsf),
|
74
|
+
str(hsf),
|
75
|
+
)
|
76
|
+
(
|
77
|
+
self.crop_img_size[0],
|
78
|
+
self.crop_img_size[1],
|
79
|
+
) = await self.async_map_coordinates_offset(
|
80
|
+
wsf, hsf, new_width, new_height, is_rand
|
81
|
+
)
|
82
|
+
return ImageOps.pad(pil_img, (new_width, new_height))
|
83
|
+
return ImageOps.pad(pil_img, (width, height))
|
84
|
+
|
85
|
+
async def async_map_coordinates_offset(
|
86
|
+
self, wsf: int, hsf: int, width: int, height: int, rand256: bool = False
|
87
|
+
) -> tuple[int, int]:
|
88
|
+
"""
|
89
|
+
Offset the coordinates to the map.
|
90
|
+
"""
|
91
|
+
|
92
|
+
if wsf == 1 and hsf == 1:
|
93
|
+
self.set_image_offset_ratio_1_1(width, height, rand256)
|
94
|
+
elif wsf == 2 and hsf == 1:
|
95
|
+
self.set_image_offset_ratio_2_1(width, height, rand256)
|
96
|
+
elif wsf == 3 and hsf == 2:
|
97
|
+
self.set_image_offset_ratio_3_2(width, height, rand256)
|
98
|
+
elif wsf == 5 and hsf == 4:
|
99
|
+
self.set_image_offset_ratio_5_4(width, height, rand256)
|
100
|
+
elif wsf == 9 and hsf == 16:
|
101
|
+
self.set_image_offset_ratio_9_16(width, height, rand256)
|
102
|
+
elif wsf == 16 and hsf == 9:
|
103
|
+
self.set_image_offset_ratio_16_9(width, height, rand256)
|
104
|
+
return width, height
|
105
|
+
|
106
|
+
@staticmethod
|
107
|
+
async def calculate_array_hash(layers: dict, active: list[int] = None) -> str:
|
108
|
+
"""Calculate the hash of the image based on layers and active zones."""
|
109
|
+
if layers and active:
|
110
|
+
data_to_hash = {
|
111
|
+
"layers": len(layers["wall"][0]),
|
112
|
+
"active_segments": tuple(active),
|
113
|
+
}
|
114
|
+
data_json = json.dumps(data_to_hash, sort_keys=True)
|
115
|
+
return hashlib.sha256(data_json.encode()).hexdigest()
|
116
|
+
return None
|
117
|
+
|
118
|
+
@staticmethod
|
119
|
+
async def async_copy_array(original_array: NumpyArray) -> NumpyArray:
|
120
|
+
"""Copy the array."""
|
121
|
+
return NumpyArray.copy(original_array)
|
122
|
+
|
123
|
+
def get_map_points(self) -> dict:
|
124
|
+
"""Return the map points."""
|
125
|
+
return [
|
126
|
+
{"x": 0, "y": 0}, # Top-left corner 0
|
127
|
+
{"x": self.crop_img_size[0], "y": 0}, # Top-right corner 1
|
128
|
+
{
|
129
|
+
"x": self.crop_img_size[0],
|
130
|
+
"y": self.crop_img_size[1],
|
131
|
+
}, # Bottom-right corner 2
|
132
|
+
{"x": 0, "y": self.crop_img_size[1]}, # Bottom-left corner (optional) 3
|
133
|
+
]
|
134
|
+
|
135
|
+
def set_image_offset_ratio_1_1(
|
136
|
+
self, width: int, height: int, rand256: bool = False
|
137
|
+
) -> None:
|
138
|
+
"""Set the image offset ratio to 1:1."""
|
139
|
+
|
140
|
+
rotation = self.shared.image_rotate
|
141
|
+
if not rand256:
|
142
|
+
if rotation in [0, 180]:
|
143
|
+
self.offset_y = self.crop_img_size[0] - width
|
144
|
+
self.offset_x = (height - self.crop_img_size[1]) // 2
|
145
|
+
elif rotation in [90, 270]:
|
146
|
+
self.offset_y = width - self.crop_img_size[0]
|
147
|
+
self.offset_x = (self.crop_img_size[1] - height) // 2
|
148
|
+
else:
|
149
|
+
if rotation in [0, 180]:
|
150
|
+
self.offset_x = (width - self.crop_img_size[0]) // 2
|
151
|
+
self.offset_y = height - self.crop_img_size[1]
|
152
|
+
elif rotation in [90, 270]:
|
153
|
+
self.offset_y = (self.crop_img_size[0] - width) // 2
|
154
|
+
self.offset_x = self.crop_img_size[1] - height
|
155
|
+
_LOGGER.debug(
|
156
|
+
"%s Image Coordinates Offsets (x,y): %s. %s",
|
157
|
+
self.file_name,
|
158
|
+
self.offset_x,
|
159
|
+
self.offset_y,
|
160
|
+
)
|
161
|
+
|
162
|
+
def set_image_offset_ratio_2_1(
|
163
|
+
self, width: int, height: int, rand256: bool = False
|
164
|
+
) -> None:
|
165
|
+
"""Set the image offset ratio to 2:1."""
|
166
|
+
|
167
|
+
rotation = self.shared.image_rotate
|
168
|
+
if not rand256:
|
169
|
+
if rotation in [0, 180]:
|
170
|
+
self.offset_y = width - self.crop_img_size[0]
|
171
|
+
self.offset_x = height - self.crop_img_size[1]
|
172
|
+
elif rotation in [90, 270]:
|
173
|
+
self.offset_x = width - self.crop_img_size[0]
|
174
|
+
self.offset_y = height - self.crop_img_size[1]
|
175
|
+
else:
|
176
|
+
if rotation in [0, 180]:
|
177
|
+
self.offset_y = width - self.crop_img_size[0]
|
178
|
+
self.offset_x = height - self.crop_img_size[1]
|
179
|
+
elif rotation in [90, 270]:
|
180
|
+
self.offset_x = width - self.crop_img_size[0]
|
181
|
+
self.offset_y = height - self.crop_img_size[1]
|
182
|
+
|
183
|
+
_LOGGER.debug(
|
184
|
+
"%s Image Coordinates Offsets (x,y): %s. %s",
|
185
|
+
self.file_name,
|
186
|
+
self.offset_x,
|
187
|
+
self.offset_y,
|
188
|
+
)
|
189
|
+
|
190
|
+
def set_image_offset_ratio_3_2(
|
191
|
+
self, width: int, height: int, rand256: bool = False
|
192
|
+
) -> None:
|
193
|
+
"""Set the image offset ratio to 3:2."""
|
194
|
+
|
195
|
+
rotation = self.shared.image_rotate
|
196
|
+
|
197
|
+
if not rand256:
|
198
|
+
if rotation in [0, 180]:
|
199
|
+
self.offset_y = width - self.crop_img_size[0]
|
200
|
+
self.offset_x = ((height - self.crop_img_size[1]) // 2) - (
|
201
|
+
self.crop_img_size[1] // 10
|
202
|
+
)
|
203
|
+
elif rotation in [90, 270]:
|
204
|
+
self.offset_y = (self.crop_img_size[0] - width) // 2
|
205
|
+
self.offset_x = (self.crop_img_size[1] - height) + (
|
206
|
+
(height // 10) // 2
|
207
|
+
)
|
208
|
+
else:
|
209
|
+
if rotation in [0, 180]:
|
210
|
+
self.offset_x = (width - self.crop_img_size[0]) // 2
|
211
|
+
self.offset_y = height - self.crop_img_size[1]
|
212
|
+
elif rotation in [90, 270]:
|
213
|
+
self.offset_y = (self.crop_img_size[0] - width) // 2
|
214
|
+
self.offset_x = self.crop_img_size[1] - height
|
215
|
+
|
216
|
+
_LOGGER.debug(
|
217
|
+
"%s Image Coordinates Offsets (x,y): %s. %s",
|
218
|
+
self.file_name,
|
219
|
+
self.offset_x,
|
220
|
+
self.offset_y,
|
221
|
+
)
|
222
|
+
|
223
|
+
def set_image_offset_ratio_5_4(
|
224
|
+
self, width: int, height: int, rand256: bool = False
|
225
|
+
) -> None:
|
226
|
+
"""Set the image offset ratio to 5:4."""
|
227
|
+
|
228
|
+
rotation = self.shared.image_rotate
|
229
|
+
if not rand256:
|
230
|
+
if rotation in [0, 180]:
|
231
|
+
self.offset_x = ((width - self.crop_img_size[0]) // 2) - (
|
232
|
+
self.crop_img_size[0] // 2
|
233
|
+
)
|
234
|
+
self.offset_y = (self.crop_img_size[1] - height) - (
|
235
|
+
self.crop_img_size[1] // 2
|
236
|
+
)
|
237
|
+
elif rotation in [90, 270]:
|
238
|
+
self.offset_y = ((self.crop_img_size[0] - width) // 2) - 10
|
239
|
+
self.offset_x = (self.crop_img_size[1] - height) + (
|
240
|
+
height // 10
|
241
|
+
)
|
242
|
+
else:
|
243
|
+
if rotation in [0, 180]:
|
244
|
+
self.offset_y = (width - self.crop_img_size[0]) // 2
|
245
|
+
self.offset_x = self.crop_img_size[1] - height
|
246
|
+
elif rotation in [90, 270]:
|
247
|
+
self.offset_y = (self.crop_img_size[0] - width) // 2
|
248
|
+
self.offset_x = self.crop_img_size[1] - height
|
249
|
+
|
250
|
+
_LOGGER.debug(
|
251
|
+
"%s Image Coordinates Offsets (x,y): %s. %s",
|
252
|
+
self.file_name,
|
253
|
+
self.offset_x,
|
254
|
+
self.offset_y,
|
255
|
+
)
|
256
|
+
|
257
|
+
def set_image_offset_ratio_9_16(
|
258
|
+
self, width: int, height: int, rand256: bool = False
|
259
|
+
) -> None:
|
260
|
+
"""Set the image offset ratio to 9:16."""
|
261
|
+
|
262
|
+
rotation = self.shared.image_rotate
|
263
|
+
if not rand256:
|
264
|
+
if rotation in [0, 180]:
|
265
|
+
self.offset_y = width - self.crop_img_size[0]
|
266
|
+
self.offset_x = height - self.crop_img_size[1]
|
267
|
+
elif rotation in [90, 270]:
|
268
|
+
self.offset_x = (width - self.crop_img_size[0]) + (height // 10)
|
269
|
+
self.offset_y = height - self.crop_img_size[1]
|
270
|
+
else:
|
271
|
+
if rotation in [0, 180]:
|
272
|
+
self.offset_y = width - self.crop_img_size[0]
|
273
|
+
self.offset_x = height - self.crop_img_size[1]
|
274
|
+
elif rotation in [90, 270]:
|
275
|
+
self.offset_x = width - self.crop_img_size[0]
|
276
|
+
self.offset_y = height - self.crop_img_size[1]
|
277
|
+
|
278
|
+
_LOGGER.debug(
|
279
|
+
"%s Image Coordinates Offsets (x,y): %s. %s",
|
280
|
+
self.file_name,
|
281
|
+
self.offset_x,
|
282
|
+
self.offset_y,
|
283
|
+
)
|
284
|
+
|
285
|
+
def set_image_offset_ratio_16_9(
|
286
|
+
self, width: int, height: int, rand256: bool = False
|
287
|
+
) -> None:
|
288
|
+
"""Set the image offset ratio to 16:9."""
|
289
|
+
|
290
|
+
rotation = self.shared.image_rotate
|
291
|
+
if not rand256:
|
292
|
+
if rotation in [0, 180]:
|
293
|
+
self.offset_y = width - self.crop_img_size[0]
|
294
|
+
self.offset_x = height - self.crop_img_size[1]
|
295
|
+
elif rotation in [90, 270]:
|
296
|
+
self.offset_x = width - self.crop_img_size[0]
|
297
|
+
self.offset_y = height - self.crop_img_size[1]
|
298
|
+
else:
|
299
|
+
if rotation in [0, 180]:
|
300
|
+
self.offset_y = width - self.crop_img_size[0]
|
301
|
+
self.offset_x = height - self.crop_img_size[1]
|
302
|
+
elif rotation in [90, 270]:
|
303
|
+
self.offset_x = width - self.crop_img_size[0]
|
304
|
+
self.offset_y = height - self.crop_img_size[1]
|
305
|
+
|
306
|
+
_LOGGER.debug(
|
307
|
+
"%s Image Coordinates Offsets (x,y): %s. %s",
|
308
|
+
self.file_name,
|
309
|
+
self.offset_x,
|
310
|
+
self.offset_y,
|
311
|
+
)
|
312
|
+
|
313
|
+
def get_vacuum_points(self, rotation_angle: int) -> list[dict[str, int]]:
|
314
|
+
"""Calculate the calibration points based on the rotation angle."""
|
315
|
+
|
316
|
+
# get_calibration_data
|
317
|
+
vacuum_points = [
|
318
|
+
{
|
319
|
+
"x": self.img.crop_area[0] + self.img.offset_x,
|
320
|
+
"y": self.img.crop_area[1] + self.img.offset_y,
|
321
|
+
}, # Top-left corner 0
|
322
|
+
{
|
323
|
+
"x": self.img.crop_area[2] - self.img.offset_x,
|
324
|
+
"y": self.img.crop_area[1] + self.img.offset_y,
|
325
|
+
}, # Top-right corner 1
|
326
|
+
{
|
327
|
+
"x": self.img.crop_area[2] - self.img.offset_x,
|
328
|
+
"y": self.img.crop_area[3] - self.img.offset_y,
|
329
|
+
}, # Bottom-right corner 2
|
330
|
+
{
|
331
|
+
"x": self.img.crop_area[0] + self.img.offset_x,
|
332
|
+
"y": self.img.crop_area[3] - self.img.offset_y,
|
333
|
+
}, # Bottom-left corner (optional)3
|
334
|
+
]
|
335
|
+
|
336
|
+
# Rotate the vacuum points based on the rotation angle
|
337
|
+
if rotation_angle == 90:
|
338
|
+
vacuum_points = [
|
339
|
+
vacuum_points[1],
|
340
|
+
vacuum_points[2],
|
341
|
+
vacuum_points[3],
|
342
|
+
vacuum_points[0],
|
343
|
+
]
|
344
|
+
elif rotation_angle == 180:
|
345
|
+
vacuum_points = [
|
346
|
+
vacuum_points[2],
|
347
|
+
vacuum_points[3],
|
348
|
+
vacuum_points[0],
|
349
|
+
vacuum_points[1],
|
350
|
+
]
|
351
|
+
elif rotation_angle == 270:
|
352
|
+
vacuum_points = [
|
353
|
+
vacuum_points[3],
|
354
|
+
vacuum_points[0],
|
355
|
+
vacuum_points[1],
|
356
|
+
vacuum_points[2],
|
357
|
+
]
|
358
|
+
|
359
|
+
return vacuum_points
|
360
|
+
|
361
|
+
def re_get_vacuum_points(self, rotation_angle: int) -> list[dict[str, int]]:
|
362
|
+
"""Recalculate the calibration points based on the rotation angle.
|
363
|
+
RAND256 Vacuums Calibration Points are in 10th of a mm."""
|
364
|
+
vacuum_points = [
|
365
|
+
{
|
366
|
+
"x": ((self.img.crop_area[0] + self.img.offset_x) * 10),
|
367
|
+
"y": ((self.img.crop_area[1] + self.img.offset_y) * 10),
|
368
|
+
}, # Top-left corner 0
|
369
|
+
{
|
370
|
+
"x": ((self.img.crop_area[2] - self.img.offset_x) * 10),
|
371
|
+
"y": ((self.img.crop_area[1] + self.img.offset_y) * 10),
|
372
|
+
}, # Top-right corner 1
|
373
|
+
{
|
374
|
+
"x": ((self.img.crop_area[2] - self.img.offset_x) * 10),
|
375
|
+
"y": ((self.img.crop_area[3] - self.img.offset_y) * 10),
|
376
|
+
}, # Bottom-right corner 2
|
377
|
+
{
|
378
|
+
"x": ((self.img.crop_area[0] + self.img.offset_x) * 10),
|
379
|
+
"y": ((self.img.crop_area[3] - self.img.offset_y) * 10),
|
380
|
+
}, # Bottom-left corner (optional)3
|
381
|
+
]
|
382
|
+
|
383
|
+
# Rotate the vacuum points based on the rotation angle
|
384
|
+
if rotation_angle == 90:
|
385
|
+
vacuum_points = [
|
386
|
+
vacuum_points[1],
|
387
|
+
vacuum_points[2],
|
388
|
+
vacuum_points[3],
|
389
|
+
vacuum_points[0],
|
390
|
+
]
|
391
|
+
elif rotation_angle == 180:
|
392
|
+
vacuum_points = [
|
393
|
+
vacuum_points[2],
|
394
|
+
vacuum_points[3],
|
395
|
+
vacuum_points[0],
|
396
|
+
vacuum_points[1],
|
397
|
+
]
|
398
|
+
elif rotation_angle == 270:
|
399
|
+
vacuum_points = [
|
400
|
+
vacuum_points[3],
|
401
|
+
vacuum_points[0],
|
402
|
+
vacuum_points[1],
|
403
|
+
vacuum_points[2],
|
404
|
+
]
|
405
|
+
|
406
|
+
return vacuum_points
|
407
|
+
|
408
|
+
async def async_zone_propriety(self, zones_data) -> dict:
|
409
|
+
"""Get the zone propriety"""
|
410
|
+
zone_properties = {}
|
411
|
+
id_count = 1
|
412
|
+
for zone in zones_data:
|
413
|
+
zone_name = zone.get("name")
|
414
|
+
coordinates = zone.get("coordinates")
|
415
|
+
if coordinates and len(coordinates) > 0:
|
416
|
+
coordinates[0].pop()
|
417
|
+
x1, y1, x2, y2 = coordinates[0]
|
418
|
+
zone_properties[zone_name] = {
|
419
|
+
"zones": coordinates,
|
420
|
+
"name": zone_name,
|
421
|
+
"x": ((x1 + x2) // 2),
|
422
|
+
"y": ((y1 + y2) // 2),
|
423
|
+
}
|
424
|
+
id_count += 1
|
425
|
+
if id_count > 1:
|
426
|
+
_LOGGER.debug("%s: Zones Properties updated.", self.file_name)
|
427
|
+
return zone_properties
|
428
|
+
|
429
|
+
async def async_points_propriety(self, points_data) -> dict:
|
430
|
+
"""Get the point propriety"""
|
431
|
+
point_properties = {}
|
432
|
+
id_count = 1
|
433
|
+
for point in points_data:
|
434
|
+
point_name = point.get("name")
|
435
|
+
coordinates = point.get("coordinates")
|
436
|
+
if coordinates and len(coordinates) > 0:
|
437
|
+
coordinates = point.get("coordinates")
|
438
|
+
x1, y1 = coordinates
|
439
|
+
point_properties[id_count] = {
|
440
|
+
"position": coordinates,
|
441
|
+
"name": point_name,
|
442
|
+
"x": x1,
|
443
|
+
"y": y1,
|
444
|
+
}
|
445
|
+
id_count += 1
|
446
|
+
if id_count > 1:
|
447
|
+
_LOGGER.debug("%s: Point Properties updated.", self.file_name)
|
448
|
+
return point_properties
|
@@ -6,8 +6,6 @@ Version: 2024.07.2
|
|
6
6
|
|
7
7
|
from __future__ import annotations
|
8
8
|
|
9
|
-
import hashlib
|
10
|
-
import json
|
11
9
|
import logging
|
12
10
|
|
13
11
|
from .config.types import Color, JsonType, NumpyArray, RobotPosition
|
@@ -283,25 +281,6 @@ class ImageDraw:
|
|
283
281
|
_LOGGER.info("%s: Got the points in the json.", self.file_name)
|
284
282
|
return entity_dict
|
285
283
|
|
286
|
-
@staticmethod
|
287
|
-
async def async_copy_array(original_array: NumpyArray) -> NumpyArray:
|
288
|
-
"""Copy the array."""
|
289
|
-
return NumpyArray.copy(original_array)
|
290
|
-
|
291
|
-
async def calculate_array_hash(self, layers: dict, active: list[int] = None) -> str:
|
292
|
-
"""Calculate the hash of the image based on the layers and active segments walls."""
|
293
|
-
self.img_h.active_zones = active
|
294
|
-
if layers and active:
|
295
|
-
data_to_hash = {
|
296
|
-
"layers": len(layers["wall"][0]),
|
297
|
-
"active_segments": tuple(active),
|
298
|
-
}
|
299
|
-
data_json = json.dumps(data_to_hash, sort_keys=True)
|
300
|
-
hash_value = hashlib.sha256(data_json.encode()).hexdigest()
|
301
|
-
else:
|
302
|
-
hash_value = None
|
303
|
-
return hash_value
|
304
|
-
|
305
284
|
async def async_get_robot_in_room(
|
306
285
|
self, robot_y: int = 0, robot_x: int = 0, angle: float = 0.0
|
307
286
|
) -> RobotPosition:
|