valetudo-map-parser 0.1.7__py3-none-any.whl → 0.1.9__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 +28 -13
- valetudo_map_parser/config/async_utils.py +93 -0
- valetudo_map_parser/config/auto_crop.py +312 -123
- valetudo_map_parser/config/color_utils.py +105 -0
- valetudo_map_parser/config/colors.py +662 -13
- valetudo_map_parser/config/drawable.py +613 -268
- valetudo_map_parser/config/drawable_elements.py +292 -0
- valetudo_map_parser/config/enhanced_drawable.py +324 -0
- valetudo_map_parser/config/optimized_element_map.py +406 -0
- valetudo_map_parser/config/rand256_parser.py +395 -0
- valetudo_map_parser/config/shared.py +94 -11
- valetudo_map_parser/config/types.py +105 -52
- valetudo_map_parser/config/utils.py +1025 -0
- valetudo_map_parser/hypfer_draw.py +464 -148
- valetudo_map_parser/hypfer_handler.py +366 -259
- valetudo_map_parser/hypfer_rooms_handler.py +599 -0
- valetudo_map_parser/map_data.py +56 -66
- valetudo_map_parser/rand256_handler.py +674 -0
- valetudo_map_parser/reimg_draw.py +68 -84
- valetudo_map_parser/rooms_handler.py +474 -0
- valetudo_map_parser-0.1.9.dist-info/METADATA +93 -0
- valetudo_map_parser-0.1.9.dist-info/RECORD +27 -0
- {valetudo_map_parser-0.1.7.dist-info → valetudo_map_parser-0.1.9.dist-info}/WHEEL +1 -1
- valetudo_map_parser/config/rand25_parser.py +0 -398
- valetudo_map_parser/images_utils.py +0 -398
- valetudo_map_parser/rand25_handler.py +0 -455
- valetudo_map_parser-0.1.7.dist-info/METADATA +0 -23
- valetudo_map_parser-0.1.7.dist-info/RECORD +0 -20
- {valetudo_map_parser-0.1.7.dist-info → valetudo_map_parser-0.1.9.dist-info}/LICENSE +0 -0
- {valetudo_map_parser-0.1.7.dist-info → valetudo_map_parser-0.1.9.dist-info}/NOTICE.txt +0 -0
|
@@ -1,398 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Version: v2024.08.2
|
|
3
|
-
- This parser is the python version of @rand256 valetudo_mapper.
|
|
4
|
-
- This class is extracting the vacuum binary map_data.
|
|
5
|
-
- Additional functions are to get in our image_handler the images datas.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from enum import Enum
|
|
9
|
-
import math
|
|
10
|
-
import struct
|
|
11
|
-
from typing import Dict, List, Optional, Callable, TypeVar, Any
|
|
12
|
-
|
|
13
|
-
_CallableT = TypeVar("_CallableT", bound=Callable[..., Any])
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def callback(func: _CallableT) -> _CallableT:
|
|
17
|
-
"""Annotation to mark method as safe to call from within the event loop."""
|
|
18
|
-
setattr(func, "_hass_callback", True) # Attach a custom attribute to the function
|
|
19
|
-
return func # Return the function without modifying its behavior
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# noinspection PyTypeChecker
|
|
23
|
-
class RRMapParser:
|
|
24
|
-
"""Parse the map data from the Rand256 vacuum."""
|
|
25
|
-
|
|
26
|
-
def __init__(self):
|
|
27
|
-
self.map_data = None
|
|
28
|
-
|
|
29
|
-
class Tools:
|
|
30
|
-
"""Tools for the RRMapParser."""
|
|
31
|
-
|
|
32
|
-
DIMENSION_PIXELS = 1024
|
|
33
|
-
DIMENSION_MM = 50 * 1024
|
|
34
|
-
|
|
35
|
-
class Types(Enum):
|
|
36
|
-
"""Types of blocks in the RRMapParser."""
|
|
37
|
-
|
|
38
|
-
CHARGER_LOCATION = 1
|
|
39
|
-
IMAGE = 2
|
|
40
|
-
PATH = 3
|
|
41
|
-
GOTO_PATH = 4
|
|
42
|
-
GOTO_PREDICTED_PATH = 5
|
|
43
|
-
CURRENTLY_CLEANED_ZONES = 6
|
|
44
|
-
GOTO_TARGET = 7
|
|
45
|
-
ROBOT_POSITION = 8
|
|
46
|
-
FORBIDDEN_ZONES = 9
|
|
47
|
-
VIRTUAL_WALLS = 10
|
|
48
|
-
CURRENTLY_CLEANED_BLOCKS = 11
|
|
49
|
-
FORBIDDEN_MOP_ZONES = 12
|
|
50
|
-
DIGEST = 1024
|
|
51
|
-
|
|
52
|
-
@staticmethod
|
|
53
|
-
def parse_block(
|
|
54
|
-
buf: bytes,
|
|
55
|
-
offset: int,
|
|
56
|
-
result: Optional[Dict[int, Any]] = None,
|
|
57
|
-
pixels: bool = False,
|
|
58
|
-
) -> Dict[int, Any]:
|
|
59
|
-
"""Parse a block of data from the map data."""
|
|
60
|
-
result = result or {}
|
|
61
|
-
if len(buf) <= offset:
|
|
62
|
-
return result
|
|
63
|
-
|
|
64
|
-
type_ = struct.unpack("<H", buf[offset : offset + 2])[0]
|
|
65
|
-
hlength = struct.unpack("<H", buf[offset + 2 : offset + 4])[0]
|
|
66
|
-
length = struct.unpack("<I", buf[offset + 4 : offset + 8])[0]
|
|
67
|
-
|
|
68
|
-
if type_ in (
|
|
69
|
-
RRMapParser.Types.ROBOT_POSITION.value,
|
|
70
|
-
RRMapParser.Types.CHARGER_LOCATION.value,
|
|
71
|
-
):
|
|
72
|
-
result[type_] = {
|
|
73
|
-
"position": [
|
|
74
|
-
int.from_bytes(buf[offset + 8 : offset + 10], byteorder="little"),
|
|
75
|
-
int.from_bytes(buf[offset + 12 : offset + 14], byteorder="little"),
|
|
76
|
-
],
|
|
77
|
-
"angle": (
|
|
78
|
-
struct.unpack("<i", buf[offset + 16 : offset + 20])[0]
|
|
79
|
-
if length >= 12
|
|
80
|
-
else 0
|
|
81
|
-
),
|
|
82
|
-
}
|
|
83
|
-
elif type_ == RRMapParser.Types.IMAGE.value:
|
|
84
|
-
RRMapParser._parse_image_block(buf, offset, length, hlength, result, pixels)
|
|
85
|
-
elif type_ in (
|
|
86
|
-
RRMapParser.Types.PATH.value,
|
|
87
|
-
RRMapParser.Types.GOTO_PATH.value,
|
|
88
|
-
RRMapParser.Types.GOTO_PREDICTED_PATH.value,
|
|
89
|
-
):
|
|
90
|
-
result[type_] = RRMapParser._parse_path_block(buf, offset, length)
|
|
91
|
-
elif type_ == RRMapParser.Types.GOTO_TARGET.value:
|
|
92
|
-
result[type_] = {
|
|
93
|
-
"position": [
|
|
94
|
-
struct.unpack("<H", buf[offset + 8 : offset + 10])[0],
|
|
95
|
-
struct.unpack("<H", buf[offset + 10 : offset + 12])[0],
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
elif type_ == RRMapParser.Types.CURRENTLY_CLEANED_ZONES.value:
|
|
99
|
-
result[type_] = RRMapParser._parse_cleaned_zones(buf, offset, length)
|
|
100
|
-
elif type_ in (
|
|
101
|
-
RRMapParser.Types.FORBIDDEN_ZONES.value,
|
|
102
|
-
RRMapParser.Types.FORBIDDEN_MOP_ZONES.value,
|
|
103
|
-
RRMapParser.Types.VIRTUAL_WALLS.value,
|
|
104
|
-
):
|
|
105
|
-
result[type_] = RRMapParser._parse_forbidden_zones(buf, offset, length)
|
|
106
|
-
return RRMapParser.parse_block(buf, offset + length + hlength, result, pixels)
|
|
107
|
-
|
|
108
|
-
@staticmethod
|
|
109
|
-
def _parse_image_block(
|
|
110
|
-
buf: bytes,
|
|
111
|
-
offset: int,
|
|
112
|
-
length: int,
|
|
113
|
-
hlength: int,
|
|
114
|
-
result: Dict[int, Any],
|
|
115
|
-
pixels: bool,
|
|
116
|
-
) -> None:
|
|
117
|
-
"""Parse the image block of the map data."""
|
|
118
|
-
g3offset = 4 if hlength > 24 else 0
|
|
119
|
-
parameters = {
|
|
120
|
-
"segments": {
|
|
121
|
-
"count": (
|
|
122
|
-
struct.unpack("<i", buf[offset + 8 : offset + 12])[0]
|
|
123
|
-
if g3offset
|
|
124
|
-
else 0
|
|
125
|
-
),
|
|
126
|
-
"id": [],
|
|
127
|
-
},
|
|
128
|
-
"position": {
|
|
129
|
-
"top": struct.unpack(
|
|
130
|
-
"<i", buf[offset + 8 + g3offset : offset + 12 + g3offset]
|
|
131
|
-
)[0],
|
|
132
|
-
"left": struct.unpack(
|
|
133
|
-
"<i", buf[offset + 12 + g3offset : offset + 16 + g3offset]
|
|
134
|
-
)[0],
|
|
135
|
-
},
|
|
136
|
-
"dimensions": {
|
|
137
|
-
"height": struct.unpack(
|
|
138
|
-
"<i", buf[offset + 16 + g3offset : offset + 20 + g3offset]
|
|
139
|
-
)[0],
|
|
140
|
-
"width": struct.unpack(
|
|
141
|
-
"<i", buf[offset + 20 + g3offset : offset + 24 + g3offset]
|
|
142
|
-
)[0],
|
|
143
|
-
},
|
|
144
|
-
"pixels": {"floor": [], "walls": [], "segments": {}},
|
|
145
|
-
}
|
|
146
|
-
parameters["position"]["top"] = (
|
|
147
|
-
RRMapParser.Tools.DIMENSION_PIXELS
|
|
148
|
-
- parameters["position"]["top"]
|
|
149
|
-
- parameters["dimensions"]["height"]
|
|
150
|
-
)
|
|
151
|
-
if (
|
|
152
|
-
parameters["dimensions"]["height"] > 0
|
|
153
|
-
and parameters["dimensions"]["width"] > 0
|
|
154
|
-
):
|
|
155
|
-
for i in range(length):
|
|
156
|
-
segment_type = (
|
|
157
|
-
struct.unpack(
|
|
158
|
-
"<B",
|
|
159
|
-
buf[offset + 24 + g3offset + i : offset + 25 + g3offset + i],
|
|
160
|
-
)[0]
|
|
161
|
-
& 0x07
|
|
162
|
-
)
|
|
163
|
-
if segment_type == 0:
|
|
164
|
-
continue
|
|
165
|
-
elif segment_type == 1 and pixels:
|
|
166
|
-
parameters["pixels"]["walls"].append(i)
|
|
167
|
-
else:
|
|
168
|
-
s = (
|
|
169
|
-
struct.unpack(
|
|
170
|
-
"<B",
|
|
171
|
-
buf[
|
|
172
|
-
offset + 24 + g3offset + i : offset + 25 + g3offset + i
|
|
173
|
-
],
|
|
174
|
-
)[0]
|
|
175
|
-
>> 3
|
|
176
|
-
)
|
|
177
|
-
if s == 0 and pixels:
|
|
178
|
-
parameters["pixels"]["floor"].append(i)
|
|
179
|
-
elif s != 0:
|
|
180
|
-
if s not in parameters["segments"]["id"]:
|
|
181
|
-
parameters["segments"]["id"].append(s)
|
|
182
|
-
parameters["segments"]["pixels_seg_" + str(s)] = []
|
|
183
|
-
if pixels:
|
|
184
|
-
parameters["segments"]["pixels_seg_" + str(s)].append(i)
|
|
185
|
-
result[RRMapParser.Types.IMAGE.value] = parameters
|
|
186
|
-
|
|
187
|
-
@staticmethod
|
|
188
|
-
def _parse_path_block(buf: bytes, offset: int, length: int) -> Dict[str, Any]:
|
|
189
|
-
"""Parse a path block of the map data."""
|
|
190
|
-
points = [
|
|
191
|
-
[
|
|
192
|
-
struct.unpack("<H", buf[offset + 20 + i : offset + 22 + i])[0],
|
|
193
|
-
struct.unpack("<H", buf[offset + 22 + i : offset + 24 + i])[0],
|
|
194
|
-
]
|
|
195
|
-
for i in range(0, length, 4)
|
|
196
|
-
]
|
|
197
|
-
return {
|
|
198
|
-
"current_angle": struct.unpack("<I", buf[offset + 16 : offset + 20])[0],
|
|
199
|
-
"points": points,
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
@staticmethod
|
|
203
|
-
def _parse_cleaned_zones(buf: bytes, offset: int, length: int) -> List[List[int]]:
|
|
204
|
-
"""Parse the cleaned zones block of the map data."""
|
|
205
|
-
zone_count = struct.unpack("<I", buf[offset + 8 : offset + 12])[0]
|
|
206
|
-
return (
|
|
207
|
-
[
|
|
208
|
-
[
|
|
209
|
-
struct.unpack("<H", buf[offset + 12 + i : offset + 14 + i])[0],
|
|
210
|
-
struct.unpack("<H", buf[offset + 14 + i : offset + 16 + i])[0],
|
|
211
|
-
struct.unpack("<H", buf[offset + 16 + i : offset + 18 + i])[0],
|
|
212
|
-
struct.unpack("<H", buf[offset + 18 + i : offset + 20 + i])[0],
|
|
213
|
-
]
|
|
214
|
-
for i in range(0, length, 8)
|
|
215
|
-
]
|
|
216
|
-
if zone_count > 0
|
|
217
|
-
else []
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
@staticmethod
|
|
221
|
-
def _parse_forbidden_zones(buf: bytes, offset: int, length: int) -> List[List[int]]:
|
|
222
|
-
"""Parse the forbidden zones block of the map data."""
|
|
223
|
-
zone_count = struct.unpack("<I", buf[offset + 8 : offset + 12])[0]
|
|
224
|
-
return (
|
|
225
|
-
[
|
|
226
|
-
[
|
|
227
|
-
struct.unpack("<H", buf[offset + 12 + i : offset + 14 + i])[0],
|
|
228
|
-
struct.unpack("<H", buf[offset + 14 + i : offset + 16 + i])[0],
|
|
229
|
-
struct.unpack("<H", buf[offset + 16 + i : offset + 18 + i])[0],
|
|
230
|
-
struct.unpack("<H", buf[offset + 18 + i : offset + 20 + i])[0],
|
|
231
|
-
struct.unpack("<H", buf[offset + 20 + i : offset + 22 + i])[0],
|
|
232
|
-
struct.unpack("<H", buf[offset + 22 + i : offset + 24 + i])[0],
|
|
233
|
-
struct.unpack("<H", buf[offset + 24 + i : offset + 26 + i])[0],
|
|
234
|
-
struct.unpack("<H", buf[offset + 26 + i : offset + 28 + i])[0],
|
|
235
|
-
]
|
|
236
|
-
for i in range(0, length, 16)
|
|
237
|
-
]
|
|
238
|
-
if zone_count > 0
|
|
239
|
-
else []
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
@callback
|
|
243
|
-
def parse(self, map_buf: bytes) -> Dict[str, Any]:
|
|
244
|
-
"""Parse the map data."""
|
|
245
|
-
if map_buf[0:2] == b"rr":
|
|
246
|
-
return {
|
|
247
|
-
"header_length": struct.unpack("<H", map_buf[2:4])[0],
|
|
248
|
-
"data_length": struct.unpack("<H", map_buf[4:6])[0],
|
|
249
|
-
"version": {
|
|
250
|
-
"major": struct.unpack("<H", map_buf[8:10])[0],
|
|
251
|
-
"minor": struct.unpack("<H", map_buf[10:12])[0],
|
|
252
|
-
},
|
|
253
|
-
"map_index": struct.unpack("<H", map_buf[12:14])[0],
|
|
254
|
-
"map_sequence": struct.unpack("<H", map_buf[16:18])[0],
|
|
255
|
-
}
|
|
256
|
-
return {}
|
|
257
|
-
|
|
258
|
-
@callback
|
|
259
|
-
def parse_rrm_data(
|
|
260
|
-
self, map_buf: bytes, pixels: bool = False
|
|
261
|
-
) -> Optional[Dict[str, Any]]:
|
|
262
|
-
"""Parse the complete map data."""
|
|
263
|
-
if not self.parse(map_buf).get("map_index"):
|
|
264
|
-
return None
|
|
265
|
-
|
|
266
|
-
parsed_map_data = {}
|
|
267
|
-
blocks = self.parse_block(map_buf, 0x14, None, pixels)
|
|
268
|
-
|
|
269
|
-
if RRMapParser.Types.IMAGE.value in blocks:
|
|
270
|
-
parsed_map_data["image"] = blocks[RRMapParser.Types.IMAGE.value]
|
|
271
|
-
for item in [
|
|
272
|
-
{"type": RRMapParser.Types.PATH.value, "path": "path"},
|
|
273
|
-
{
|
|
274
|
-
"type": RRMapParser.Types.GOTO_PREDICTED_PATH.value,
|
|
275
|
-
"path": "goto_predicted_path",
|
|
276
|
-
},
|
|
277
|
-
]:
|
|
278
|
-
if item["type"] in blocks:
|
|
279
|
-
parsed_map_data[item["path"]] = blocks[item["type"]]
|
|
280
|
-
parsed_map_data[item["path"]]["points"] = [
|
|
281
|
-
[point[0], RRMapParser.Tools.DIMENSION_MM - point[1]]
|
|
282
|
-
for point in parsed_map_data[item["path"]]["points"]
|
|
283
|
-
]
|
|
284
|
-
if len(parsed_map_data[item["path"]]["points"]) >= 2:
|
|
285
|
-
parsed_map_data[item["path"]]["current_angle"] = math.degrees(
|
|
286
|
-
math.atan2(
|
|
287
|
-
parsed_map_data[item["path"]]["points"][-1][1]
|
|
288
|
-
- parsed_map_data[item["path"]]["points"][-2][1],
|
|
289
|
-
parsed_map_data[item["path"]]["points"][-1][0]
|
|
290
|
-
- parsed_map_data[item["path"]]["points"][-2][0],
|
|
291
|
-
)
|
|
292
|
-
)
|
|
293
|
-
if RRMapParser.Types.CHARGER_LOCATION.value in blocks:
|
|
294
|
-
charger = blocks[RRMapParser.Types.CHARGER_LOCATION.value]["position"]
|
|
295
|
-
# Assume no transformation needed here
|
|
296
|
-
parsed_map_data["charger"] = charger
|
|
297
|
-
|
|
298
|
-
if RRMapParser.Types.ROBOT_POSITION.value in blocks:
|
|
299
|
-
robot = blocks[RRMapParser.Types.ROBOT_POSITION.value]["position"]
|
|
300
|
-
rob_angle = blocks[RRMapParser.Types.ROBOT_POSITION.value]["angle"]
|
|
301
|
-
# Assume no transformation needed here
|
|
302
|
-
parsed_map_data["robot"] = robot
|
|
303
|
-
parsed_map_data["robot_angle"] = rob_angle
|
|
304
|
-
|
|
305
|
-
if RRMapParser.Types.GOTO_TARGET.value in blocks:
|
|
306
|
-
parsed_map_data["goto_target"] = blocks[
|
|
307
|
-
RRMapParser.Types.GOTO_TARGET.value
|
|
308
|
-
]["position"]
|
|
309
|
-
# Assume no transformation needed here
|
|
310
|
-
|
|
311
|
-
if RRMapParser.Types.CURRENTLY_CLEANED_ZONES.value in blocks:
|
|
312
|
-
parsed_map_data["currently_cleaned_zones"] = blocks[
|
|
313
|
-
RRMapParser.Types.CURRENTLY_CLEANED_ZONES.value
|
|
314
|
-
]
|
|
315
|
-
parsed_map_data["currently_cleaned_zones"] = [
|
|
316
|
-
[
|
|
317
|
-
zone[0],
|
|
318
|
-
RRMapParser.Tools.DIMENSION_MM - zone[1],
|
|
319
|
-
zone[2],
|
|
320
|
-
RRMapParser.Tools.DIMENSION_MM - zone[3],
|
|
321
|
-
]
|
|
322
|
-
for zone in parsed_map_data["currently_cleaned_zones"]
|
|
323
|
-
]
|
|
324
|
-
|
|
325
|
-
if RRMapParser.Types.FORBIDDEN_ZONES.value in blocks:
|
|
326
|
-
parsed_map_data["forbidden_zones"] = blocks[
|
|
327
|
-
RRMapParser.Types.FORBIDDEN_ZONES.value
|
|
328
|
-
]
|
|
329
|
-
parsed_map_data["forbidden_zones"] = [
|
|
330
|
-
[
|
|
331
|
-
zone[0],
|
|
332
|
-
RRMapParser.Tools.DIMENSION_MM - zone[1],
|
|
333
|
-
zone[2],
|
|
334
|
-
RRMapParser.Tools.DIMENSION_MM - zone[3],
|
|
335
|
-
zone[4],
|
|
336
|
-
RRMapParser.Tools.DIMENSION_MM - zone[5],
|
|
337
|
-
zone[6],
|
|
338
|
-
RRMapParser.Tools.DIMENSION_MM - zone[7],
|
|
339
|
-
]
|
|
340
|
-
for zone in parsed_map_data["forbidden_zones"]
|
|
341
|
-
]
|
|
342
|
-
|
|
343
|
-
if RRMapParser.Types.VIRTUAL_WALLS.value in blocks:
|
|
344
|
-
parsed_map_data["virtual_walls"] = blocks[
|
|
345
|
-
RRMapParser.Types.VIRTUAL_WALLS.value
|
|
346
|
-
]
|
|
347
|
-
parsed_map_data["virtual_walls"] = [
|
|
348
|
-
[
|
|
349
|
-
wall[0],
|
|
350
|
-
RRMapParser.Tools.DIMENSION_MM - wall[1],
|
|
351
|
-
wall[2],
|
|
352
|
-
RRMapParser.Tools.DIMENSION_MM - wall[3],
|
|
353
|
-
]
|
|
354
|
-
for wall in parsed_map_data["virtual_walls"]
|
|
355
|
-
]
|
|
356
|
-
|
|
357
|
-
if RRMapParser.Types.CURRENTLY_CLEANED_BLOCKS.value in blocks:
|
|
358
|
-
parsed_map_data["currently_cleaned_blocks"] = blocks[
|
|
359
|
-
RRMapParser.Types.CURRENTLY_CLEANED_BLOCKS.value
|
|
360
|
-
]
|
|
361
|
-
|
|
362
|
-
if RRMapParser.Types.FORBIDDEN_MOP_ZONES.value in blocks:
|
|
363
|
-
parsed_map_data["forbidden_mop_zones"] = blocks[
|
|
364
|
-
RRMapParser.Types.FORBIDDEN_MOP_ZONES.value
|
|
365
|
-
]
|
|
366
|
-
parsed_map_data["forbidden_mop_zones"] = [
|
|
367
|
-
[
|
|
368
|
-
zone[0],
|
|
369
|
-
RRMapParser.Tools.DIMENSION_MM - zone[1],
|
|
370
|
-
zone[2],
|
|
371
|
-
RRMapParser.Tools.DIMENSION_MM - zone[3],
|
|
372
|
-
zone[4],
|
|
373
|
-
RRMapParser.Tools.DIMENSION_MM - zone[5],
|
|
374
|
-
zone[6],
|
|
375
|
-
RRMapParser.Tools.DIMENSION_MM - zone[7],
|
|
376
|
-
]
|
|
377
|
-
for zone in parsed_map_data["forbidden_mop_zones"]
|
|
378
|
-
]
|
|
379
|
-
|
|
380
|
-
return parsed_map_data
|
|
381
|
-
|
|
382
|
-
def parse_data(
|
|
383
|
-
self, payload: Optional[bytes] = None, pixels: bool = False
|
|
384
|
-
) -> Optional[Dict[str, Any]]:
|
|
385
|
-
"""Get the map data from MQTT and return the json."""
|
|
386
|
-
if payload:
|
|
387
|
-
self.map_data = self.parse(payload)
|
|
388
|
-
self.map_data.update(self.parse_rrm_data(payload, pixels) or {})
|
|
389
|
-
return self.map_data
|
|
390
|
-
|
|
391
|
-
def get_image(self) -> Dict[str, Any]:
|
|
392
|
-
"""Get the image data from the map data."""
|
|
393
|
-
return self.map_data.get("image", {})
|
|
394
|
-
|
|
395
|
-
@staticmethod
|
|
396
|
-
def get_int32(data: bytes, address: int) -> int:
|
|
397
|
-
"""Get a 32-bit integer from the data."""
|
|
398
|
-
return struct.unpack_from("<i", data, address)[0]
|