valetudo-map-parser 0.1.4__py3-none-any.whl → 0.1.6__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/__init__.py +4 -2
- valetudo_map_parser/config/auto_crop.py +12 -12
- valetudo_map_parser/config/rand25_parser.py +398 -0
- valetudo_map_parser/hypfer_handler.py +4 -4
- valetudo_map_parser/map_data.py +3 -4
- valetudo_map_parser/rand25_handler.py +455 -0
- valetudo_map_parser/reimg_draw.py +372 -0
- {valetudo_map_parser-0.1.4.dist-info → valetudo_map_parser-0.1.6.dist-info}/METADATA +1 -1
- valetudo_map_parser-0.1.6.dist-info/RECORD +20 -0
- valetudo_map_parser-0.1.4.dist-info/RECORD +0 -17
- {valetudo_map_parser-0.1.4.dist-info → valetudo_map_parser-0.1.6.dist-info}/LICENSE +0 -0
- {valetudo_map_parser-0.1.4.dist-info → valetudo_map_parser-0.1.6.dist-info}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.4.dist-info → valetudo_map_parser-0.1.6.dist-info}/WHEEL +0 -0
@@ -0,0 +1,372 @@
|
|
1
|
+
"""
|
2
|
+
Image Draw Class for Valetudo Rand256 Image Handling.
|
3
|
+
This class is used to simplify the ImageHandler class.
|
4
|
+
Version: 2024.12.0
|
5
|
+
"""
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
|
9
|
+
import hashlib
|
10
|
+
import json
|
11
|
+
import logging
|
12
|
+
|
13
|
+
from .config.types import Color, JsonType, NumpyArray
|
14
|
+
from .config.drawable import Drawable
|
15
|
+
from map_data import ImageData
|
16
|
+
|
17
|
+
_LOGGER = logging.getLogger(__name__)
|
18
|
+
|
19
|
+
|
20
|
+
class ImageDraw:
|
21
|
+
"""Class to handle the image creation."""
|
22
|
+
|
23
|
+
"""It Draws each elements of the images, like the walls, zones, paths, etc."""
|
24
|
+
|
25
|
+
def __init__(self, image_handler):
|
26
|
+
self.img_h = image_handler
|
27
|
+
self.file_name = self.img_h.shared.file_name
|
28
|
+
self.data = ImageData
|
29
|
+
self.draw = Drawable
|
30
|
+
self.color_grey = (128, 128, 128, 255)
|
31
|
+
|
32
|
+
async def async_draw_go_to_flag(
|
33
|
+
self, np_array: NumpyArray, m_json: JsonType, color_go_to: Color
|
34
|
+
) -> NumpyArray:
|
35
|
+
"""Draw the goto target flag on the map."""
|
36
|
+
try:
|
37
|
+
go_to = self.data.get_rrm_goto_target(m_json)
|
38
|
+
if go_to:
|
39
|
+
np_array = await self.draw.go_to_flag(
|
40
|
+
np_array,
|
41
|
+
(go_to[0], go_to[1]),
|
42
|
+
self.img_h.img_rotate,
|
43
|
+
color_go_to,
|
44
|
+
)
|
45
|
+
predicted_path = self.data.get_rrm_goto_predicted_path(m_json)
|
46
|
+
if predicted_path:
|
47
|
+
np_array = await self.draw.lines(
|
48
|
+
np_array, predicted_path, 3, self.color_grey
|
49
|
+
)
|
50
|
+
return np_array
|
51
|
+
else:
|
52
|
+
return np_array
|
53
|
+
except Exception as e:
|
54
|
+
_LOGGER.warning(
|
55
|
+
f"{self.file_name}: Error in extraction of go to. {e}", exc_info=True
|
56
|
+
)
|
57
|
+
return np_array
|
58
|
+
|
59
|
+
async def async_segment_data(
|
60
|
+
self, m_json, size_x, size_y, pos_top, pos_left
|
61
|
+
) -> None:
|
62
|
+
"""Get the segments data from the JSON data."""
|
63
|
+
try:
|
64
|
+
if not self.img_h.segment_data:
|
65
|
+
(
|
66
|
+
self.img_h.segment_data,
|
67
|
+
self.img_h.outlines,
|
68
|
+
) = await self.data.async_get_rrm_segments(
|
69
|
+
m_json, size_x, size_y, pos_top, pos_left, True
|
70
|
+
)
|
71
|
+
except ValueError as e:
|
72
|
+
self.img_h.segment_data = None
|
73
|
+
_LOGGER.info(f"{self.file_name}: No segments data found. {e}")
|
74
|
+
|
75
|
+
async def async_draw_base_layer(
|
76
|
+
self,
|
77
|
+
m_json,
|
78
|
+
size_x,
|
79
|
+
size_y,
|
80
|
+
color_wall,
|
81
|
+
color_zone_clean,
|
82
|
+
color_background,
|
83
|
+
pixel_size,
|
84
|
+
):
|
85
|
+
"""Draw the base layer of the map."""
|
86
|
+
pos_top, pos_left = self.data.get_rrm_image_position(m_json)
|
87
|
+
walls_data = self.data.get_rrm_walls(m_json)
|
88
|
+
floor_data = self.data.get_rrm_floor(m_json)
|
89
|
+
|
90
|
+
_LOGGER.info(self.file_name + ": Empty image with background color")
|
91
|
+
img_np_array = await self.draw.create_empty_image(
|
92
|
+
self.img_h.img_size["x"], self.img_h.img_size["y"], color_background
|
93
|
+
)
|
94
|
+
room_id = 0
|
95
|
+
if self.img_h.frame_number == 0:
|
96
|
+
_LOGGER.info(self.file_name + ": Overlapping Layers")
|
97
|
+
|
98
|
+
# checking if there are segments too (sorted pixels in the raw data).
|
99
|
+
await self.async_segment_data(m_json, size_x, size_y, pos_top, pos_left)
|
100
|
+
|
101
|
+
img_np_array = await self._draw_floor(
|
102
|
+
img_np_array, floor_data, size_x, size_y, pos_top, pos_left, pixel_size
|
103
|
+
)
|
104
|
+
room_id, img_np_array = await self._draw_segments(
|
105
|
+
img_np_array,
|
106
|
+
pixel_size,
|
107
|
+
self.img_h.segment_data,
|
108
|
+
color_wall,
|
109
|
+
color_zone_clean,
|
110
|
+
)
|
111
|
+
img_np_array = await self._draw_walls(
|
112
|
+
img_np_array,
|
113
|
+
walls_data,
|
114
|
+
size_x,
|
115
|
+
size_y,
|
116
|
+
pos_top,
|
117
|
+
pos_left,
|
118
|
+
pixel_size,
|
119
|
+
color_wall,
|
120
|
+
)
|
121
|
+
return room_id, img_np_array
|
122
|
+
|
123
|
+
async def _draw_floor(
|
124
|
+
self, img_np_array, floor_data, size_x, size_y, pos_top, pos_left, pixel_size
|
125
|
+
):
|
126
|
+
"""Draw the floor data onto the image."""
|
127
|
+
pixels = self.data.from_rrm_to_compressed_pixels(
|
128
|
+
floor_data,
|
129
|
+
image_width=size_x,
|
130
|
+
image_height=size_y,
|
131
|
+
image_top=pos_top,
|
132
|
+
image_left=pos_left,
|
133
|
+
)
|
134
|
+
if pixels:
|
135
|
+
room_color = self.img_h.shared.rooms_colors[0] # Using initial room_id = 0
|
136
|
+
img_np_array = await self.draw.from_json_to_image(
|
137
|
+
img_np_array, pixels, pixel_size, room_color
|
138
|
+
)
|
139
|
+
return img_np_array
|
140
|
+
|
141
|
+
async def _draw_segments(
|
142
|
+
self, img_np_array, pixel_size, segment_data, color_wall, color_zone_clean
|
143
|
+
):
|
144
|
+
"""Draw the segments onto the image and update room_id."""
|
145
|
+
|
146
|
+
room_id = 0
|
147
|
+
rooms_list = [color_wall]
|
148
|
+
if not segment_data:
|
149
|
+
_LOGGER.info(f"{self.file_name}: No segments data found.")
|
150
|
+
return room_id, img_np_array
|
151
|
+
|
152
|
+
if segment_data:
|
153
|
+
_LOGGER.info(f"{self.file_name}: Drawing segments.")
|
154
|
+
for pixels in segment_data:
|
155
|
+
room_color = self.img_h.shared.rooms_colors[room_id]
|
156
|
+
rooms_list.append(room_color)
|
157
|
+
if (
|
158
|
+
self.img_h.active_zones
|
159
|
+
and len(self.img_h.active_zones) > room_id
|
160
|
+
and self.img_h.active_zones[room_id] == 1
|
161
|
+
):
|
162
|
+
room_color = (
|
163
|
+
((2 * room_color[0]) + color_zone_clean[0]) // 3,
|
164
|
+
((2 * room_color[1]) + color_zone_clean[1]) // 3,
|
165
|
+
((2 * room_color[2]) + color_zone_clean[2]) // 3,
|
166
|
+
((2 * room_color[3]) + color_zone_clean[3]) // 3,
|
167
|
+
)
|
168
|
+
img_np_array = await self.draw.from_json_to_image(
|
169
|
+
img_np_array, pixels, pixel_size, room_color
|
170
|
+
)
|
171
|
+
room_id += 1
|
172
|
+
if room_id > 15:
|
173
|
+
room_id = 0
|
174
|
+
return room_id, img_np_array
|
175
|
+
|
176
|
+
async def _draw_walls(
|
177
|
+
self,
|
178
|
+
img_np_array,
|
179
|
+
walls_data,
|
180
|
+
size_x,
|
181
|
+
size_y,
|
182
|
+
pos_top,
|
183
|
+
pos_left,
|
184
|
+
pixel_size,
|
185
|
+
color_wall,
|
186
|
+
):
|
187
|
+
"""Draw the walls onto the image."""
|
188
|
+
walls = self.data.from_rrm_to_compressed_pixels(
|
189
|
+
walls_data,
|
190
|
+
image_width=size_x,
|
191
|
+
image_height=size_y,
|
192
|
+
image_left=pos_left,
|
193
|
+
image_top=pos_top,
|
194
|
+
)
|
195
|
+
if walls:
|
196
|
+
img_np_array = await self.draw.from_json_to_image(
|
197
|
+
img_np_array, walls, pixel_size, color_wall
|
198
|
+
)
|
199
|
+
return img_np_array
|
200
|
+
|
201
|
+
async def async_draw_charger(
|
202
|
+
self,
|
203
|
+
np_array: NumpyArray,
|
204
|
+
m_json: JsonType,
|
205
|
+
color_charger: Color,
|
206
|
+
) -> (NumpyArray, dict):
|
207
|
+
"""Get the charger position from the entity data."""
|
208
|
+
try:
|
209
|
+
charger_pos = self.data.rrm_coordinates_to_valetudo(
|
210
|
+
self.data.get_rrm_charger_position(m_json)
|
211
|
+
)
|
212
|
+
except Exception as e:
|
213
|
+
_LOGGER.warning(f"{self.file_name}: No charger position found. {e}")
|
214
|
+
else:
|
215
|
+
_LOGGER.debug("charger position: %s", charger_pos)
|
216
|
+
if charger_pos:
|
217
|
+
charger_pos_dictionary = {
|
218
|
+
"x": (charger_pos[0] * 10),
|
219
|
+
"y": (charger_pos[1] * 10),
|
220
|
+
}
|
221
|
+
|
222
|
+
np_array = await self.draw.battery_charger(
|
223
|
+
np_array, charger_pos[0], charger_pos[1], color_charger
|
224
|
+
)
|
225
|
+
return np_array, charger_pos_dictionary
|
226
|
+
else:
|
227
|
+
return np_array, {}
|
228
|
+
|
229
|
+
async def async_draw_zones(
|
230
|
+
self,
|
231
|
+
m_json: JsonType,
|
232
|
+
np_array: NumpyArray,
|
233
|
+
color_zone_clean: Color,
|
234
|
+
) -> NumpyArray:
|
235
|
+
"""Get the zone clean from the JSON data."""
|
236
|
+
try:
|
237
|
+
zone_clean = self.data.get_rrm_currently_cleaned_zones(m_json)
|
238
|
+
except (ValueError, KeyError):
|
239
|
+
zone_clean = None
|
240
|
+
else:
|
241
|
+
_LOGGER.info(f"{self.file_name}: Got zones.")
|
242
|
+
if zone_clean:
|
243
|
+
return await self.draw.zones(np_array, zone_clean, color_zone_clean)
|
244
|
+
else:
|
245
|
+
return np_array
|
246
|
+
|
247
|
+
async def async_draw_virtual_restrictions(
|
248
|
+
self, m_json: JsonType, np_array: NumpyArray, color_no_go: Color
|
249
|
+
) -> NumpyArray:
|
250
|
+
"""Get the virtual walls from the JSON data."""
|
251
|
+
try:
|
252
|
+
virtual_walls = self.data.get_rrm_virtual_walls(m_json)
|
253
|
+
except (ValueError, KeyError):
|
254
|
+
virtual_walls = None
|
255
|
+
else:
|
256
|
+
_LOGGER.info(f"{self.file_name}: Got virtual walls.")
|
257
|
+
if virtual_walls:
|
258
|
+
np_array = await self.draw.draw_virtual_walls(
|
259
|
+
np_array, virtual_walls, color_no_go
|
260
|
+
)
|
261
|
+
try:
|
262
|
+
no_go_area = self.data.get_rrm_forbidden_zones(m_json)
|
263
|
+
except KeyError:
|
264
|
+
no_go_area = None
|
265
|
+
if no_go_area:
|
266
|
+
np_array = await self.draw.zones(np_array, no_go_area, color_no_go)
|
267
|
+
return np_array
|
268
|
+
|
269
|
+
async def async_draw_path(
|
270
|
+
self,
|
271
|
+
np_array: NumpyArray,
|
272
|
+
m_json: JsonType,
|
273
|
+
color_move: Color,
|
274
|
+
) -> NumpyArray:
|
275
|
+
"""Get the paths from the JSON data."""
|
276
|
+
# Initialize the variables
|
277
|
+
path_pixel_formatted = None
|
278
|
+
# Extract the paths data from the JSON data.
|
279
|
+
try:
|
280
|
+
path_pixel = self.data.get_rrm_path(m_json)
|
281
|
+
path_pixel_formatted = self.data.sublist_join(
|
282
|
+
self.data.rrm_valetudo_path_array(path_pixel["points"]), 2
|
283
|
+
)
|
284
|
+
except KeyError as e:
|
285
|
+
_LOGGER.warning(f"{self.file_name}: Error extracting paths data: {str(e)}")
|
286
|
+
finally:
|
287
|
+
if path_pixel_formatted:
|
288
|
+
np_array = await self.draw.lines(
|
289
|
+
np_array, path_pixel_formatted, 5, color_move
|
290
|
+
)
|
291
|
+
return np_array
|
292
|
+
|
293
|
+
async def async_get_entity_data(self, m_json: JsonType) -> dict or None:
|
294
|
+
"""Get the entity data from the JSON data."""
|
295
|
+
try:
|
296
|
+
entity_dict = self.data.find_points_entities(m_json)
|
297
|
+
except (ValueError, KeyError):
|
298
|
+
entity_dict = None
|
299
|
+
else:
|
300
|
+
_LOGGER.info(f"{self.file_name}: Got the points in the json.")
|
301
|
+
return entity_dict
|
302
|
+
|
303
|
+
@staticmethod
|
304
|
+
async def async_copy_array(original_array: NumpyArray) -> NumpyArray:
|
305
|
+
"""Copy the array."""
|
306
|
+
return NumpyArray.copy(original_array)
|
307
|
+
|
308
|
+
async def calculate_array_hash(self, layers: dict, active: list[int] = None) -> str:
|
309
|
+
"""Calculate the hash of the image based on the layers and active segments walls."""
|
310
|
+
self.img_h.active_zones = active
|
311
|
+
if layers and active:
|
312
|
+
data_to_hash = {
|
313
|
+
"layers": len(layers["wall"][0]),
|
314
|
+
"active_segments": tuple(active),
|
315
|
+
}
|
316
|
+
data_json = json.dumps(data_to_hash, sort_keys=True)
|
317
|
+
hash_value = hashlib.sha256(data_json.encode()).hexdigest()
|
318
|
+
else:
|
319
|
+
hash_value = None
|
320
|
+
return hash_value
|
321
|
+
|
322
|
+
async def async_get_robot_position(self, m_json: JsonType) -> tuple | None:
|
323
|
+
"""Get the robot position from the entity data."""
|
324
|
+
robot_pos = None
|
325
|
+
robot_position = None
|
326
|
+
angle = [0, 0]
|
327
|
+
try:
|
328
|
+
robot_pos_data = self.data.get_rrm_robot_position(m_json)
|
329
|
+
robot_pos = self.data.rrm_coordinates_to_valetudo(robot_pos_data)
|
330
|
+
angle = self.data.get_rrm_robot_angle(m_json)
|
331
|
+
except (ValueError, KeyError):
|
332
|
+
_LOGGER.warning(f"{self.file_name} No robot position found.")
|
333
|
+
return None, None, None
|
334
|
+
finally:
|
335
|
+
robot_position_angle = round(angle[0], 0)
|
336
|
+
if robot_pos and robot_position_angle:
|
337
|
+
robot_position = robot_pos
|
338
|
+
_LOGGER.debug(
|
339
|
+
f"robot position: {robot_pos}, robot angle: {robot_position_angle}"
|
340
|
+
)
|
341
|
+
if self.img_h.rooms_pos is None:
|
342
|
+
self.img_h.robot_pos = {
|
343
|
+
"x": robot_position[0] * 10,
|
344
|
+
"y": robot_position[1] * 10,
|
345
|
+
"angle": robot_position_angle,
|
346
|
+
}
|
347
|
+
else:
|
348
|
+
self.img_h.robot_pos = await self.img_h.async_get_robot_in_room(
|
349
|
+
(robot_position[0] * 10),
|
350
|
+
(robot_position[1] * 10),
|
351
|
+
robot_position_angle,
|
352
|
+
)
|
353
|
+
return robot_pos, robot_position, robot_position_angle
|
354
|
+
|
355
|
+
async def async_draw_robot_on_map(
|
356
|
+
self,
|
357
|
+
np_array: NumpyArray,
|
358
|
+
robot_pos: tuple,
|
359
|
+
robot_angle: float,
|
360
|
+
color_robot: Color,
|
361
|
+
) -> NumpyArray:
|
362
|
+
"""Draw the robot on the map."""
|
363
|
+
if robot_pos and robot_angle:
|
364
|
+
np_array = await self.draw.robot(
|
365
|
+
layers=np_array,
|
366
|
+
x=robot_pos[0],
|
367
|
+
y=robot_pos[1],
|
368
|
+
angle=robot_angle,
|
369
|
+
fill=color_robot,
|
370
|
+
robot_state=self.img_h.shared.vacuum_state,
|
371
|
+
)
|
372
|
+
return np_array
|
@@ -0,0 +1,20 @@
|
|
1
|
+
valetudo_map_parser/__init__.py,sha256=9eWCgcSvmRe_MWEInCAjXkF9LspOuCWesjr4eUtsdA8,790
|
2
|
+
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
3
|
+
valetudo_map_parser/config/auto_crop.py,sha256=vaDAVVn86agrlEjX-rjYZxDtAZ7P92rWqF1nSyT2kJA,11014
|
4
|
+
valetudo_map_parser/config/colors.py,sha256=HlgROKagpV7FP9LTU1IvhTKTYjnlBw1ZDMKHVJSct8M,6514
|
5
|
+
valetudo_map_parser/config/drawable.py,sha256=8Fp4yqyFbsGvNyCEynYCTpiohRZk_plUSSOyHpECvj8,20356
|
6
|
+
valetudo_map_parser/config/rand25_parser.py,sha256=vkghj60Bdq22P3UnLCkKc77mqyJP524z2O9k8NvEi6M,15806
|
7
|
+
valetudo_map_parser/config/shared.py,sha256=8xYBUfKY-tiPhXaT5ttIasnCWL3_RLawIZeTValQC64,9462
|
8
|
+
valetudo_map_parser/config/types.py,sha256=bVSEDE0ihrc01jG4fZ1_hUVtoj6hdkbqShytZ6wJwJY,16163
|
9
|
+
valetudo_map_parser/hypfer_draw.py,sha256=R8JVrqPPavhj8exCDJKk1QsXgsB12cjy4AIgFffyQec,15773
|
10
|
+
valetudo_map_parser/hypfer_handler.py,sha256=MoCO4zVflFd0HSB4IRz1EOjJtlMfaagJS7A-OqJUNIU,18457
|
11
|
+
valetudo_map_parser/images_utils.py,sha256=Ls5OnXXcojBTuUagj3_N4tY3nOe9aot7gl5hrPCXKss,15262
|
12
|
+
valetudo_map_parser/map_data.py,sha256=yt_osaewoYjcQPV1u6R_N801XmAH8EgR7mKrsbOcph0,19449
|
13
|
+
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
valetudo_map_parser/rand25_handler.py,sha256=pwbMEa4ZLtS3hsja2lC2D0zpa76mKWQz4mQ5yBJ-sa0,19872
|
15
|
+
valetudo_map_parser/reimg_draw.py,sha256=zs-HHncsFxV5kozMqZ4XCYRJx8anQ3K0I440RPt7ADI,13404
|
16
|
+
valetudo_map_parser-0.1.6.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
17
|
+
valetudo_map_parser-0.1.6.dist-info/METADATA,sha256=ABBsZ58Yz7Pp0ZnlOU9oX9EexC23iBS-dHV7QTnXmpw,1026
|
18
|
+
valetudo_map_parser-0.1.6.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
19
|
+
valetudo_map_parser-0.1.6.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
20
|
+
valetudo_map_parser-0.1.6.dist-info/RECORD,,
|
@@ -1,17 +0,0 @@
|
|
1
|
-
valetudo_map_parser/__init__.py,sha256=SYv1w4Zf6ADLJ6yC6W8vhzQ96DicDRSP3yuf6ijmlxc,683
|
2
|
-
valetudo_map_parser/config/__init__.py,sha256=DQ9plV3ZF_K25Dp5ZQHPDoG-40dQoJNdNi-dfNeR3Zc,48
|
3
|
-
valetudo_map_parser/config/auto_crop.py,sha256=eTzMVhaeP7SP2-65jefE4toAigkZM6XUoARsSB5JwH8,10927
|
4
|
-
valetudo_map_parser/config/colors.py,sha256=HlgROKagpV7FP9LTU1IvhTKTYjnlBw1ZDMKHVJSct8M,6514
|
5
|
-
valetudo_map_parser/config/drawable.py,sha256=8Fp4yqyFbsGvNyCEynYCTpiohRZk_plUSSOyHpECvj8,20356
|
6
|
-
valetudo_map_parser/config/shared.py,sha256=8xYBUfKY-tiPhXaT5ttIasnCWL3_RLawIZeTValQC64,9462
|
7
|
-
valetudo_map_parser/config/types.py,sha256=bVSEDE0ihrc01jG4fZ1_hUVtoj6hdkbqShytZ6wJwJY,16163
|
8
|
-
valetudo_map_parser/hypfer_draw.py,sha256=R8JVrqPPavhj8exCDJKk1QsXgsB12cjy4AIgFffyQec,15773
|
9
|
-
valetudo_map_parser/hypfer_handler.py,sha256=PCdfzLpGZD0zXvVufFWadPc-xDqbtsnArfPW0PWViU4,18469
|
10
|
-
valetudo_map_parser/images_utils.py,sha256=Ls5OnXXcojBTuUagj3_N4tY3nOe9aot7gl5hrPCXKss,15262
|
11
|
-
valetudo_map_parser/map_data.py,sha256=-6etLFZXZikFEUeR2YhPLgXu7dv3YRY2e-u5Mx9ogqw,19498
|
12
|
-
valetudo_map_parser/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
valetudo_map_parser-0.1.4.dist-info/LICENSE,sha256=Lh-qBbuRV0-jiCIBhfV7NgdwFxQFOXH3BKOzK865hRs,10480
|
14
|
-
valetudo_map_parser-0.1.4.dist-info/METADATA,sha256=qsrU3YyxUwjsKvqo6IReZAneO_6KIAVHVvdVDLYlTMA,1026
|
15
|
-
valetudo_map_parser-0.1.4.dist-info/NOTICE.txt,sha256=5lTOuWiU9aiEnJ2go8sc7lTJ7ntMBx0g0GFnNrswCY4,2533
|
16
|
-
valetudo_map_parser-0.1.4.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
17
|
-
valetudo_map_parser-0.1.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|