valetudo-map-parser 0.1.9b22__tar.gz → 0.1.9b24__tar.gz
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-0.1.9b22 → valetudo_map_parser-0.1.9b24}/PKG-INFO +1 -1
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/__init__.py +1 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/auto_crop.py +13 -29
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/colors.py +1 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/rand25_parser.py +1 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/shared.py +33 -2
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/types.py +13 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/utils.py +21 -18
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/hypfer_draw.py +1 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/hypfer_handler.py +14 -5
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/rand25_handler.py +14 -4
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/reimg_draw.py +1 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/pyproject.toml +4 -3
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/LICENSE +0 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/README.md +0 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/__init__.py +0 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/config/drawable.py +0 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/map_data.py +0 -0
- {valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/py.typed +0 -0
@@ -10,6 +10,7 @@ from numpy import rot90
|
|
10
10
|
|
11
11
|
from .types import Color, NumpyArray, TrimCropData
|
12
12
|
|
13
|
+
|
13
14
|
_LOGGER = logging.getLogger(__name__)
|
14
15
|
|
15
16
|
|
@@ -27,9 +28,6 @@ class AutoCrop:
|
|
27
28
|
def __init__(self, image_handler):
|
28
29
|
self.imh = image_handler
|
29
30
|
self.file_name = self.imh.file_name
|
30
|
-
# self.path_to_data = self.hass.config.path(
|
31
|
-
# STORAGE_DIR, CAMERA_STORAGE, f"auto_crop_{self.file_name}.json"
|
32
|
-
# )
|
33
31
|
|
34
32
|
def check_trim(
|
35
33
|
self, trimmed_height, trimmed_width, margin_size, image_array, file_name, rotate
|
@@ -70,19 +68,18 @@ class AutoCrop:
|
|
70
68
|
)
|
71
69
|
return trimmed_width, trimmed_height
|
72
70
|
|
73
|
-
async def _async_auto_crop_data(self): # , tdata=None
|
71
|
+
async def _async_auto_crop_data(self, tdata=None): # , tdata=None
|
74
72
|
"""Load the auto crop data from the Camera config."""
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
# return trims_data
|
73
|
+
if not self.imh.auto_crop:
|
74
|
+
trims_data = TrimCropData.from_dict(dict(tdata)).to_list()
|
75
|
+
(
|
76
|
+
self.imh.trim_left,
|
77
|
+
self.imh.trim_up,
|
78
|
+
self.imh.trim_right,
|
79
|
+
self.imh.trim_down,
|
80
|
+
) = trims_data
|
81
|
+
self._calculate_trimmed_dimensions()
|
82
|
+
return trims_data
|
86
83
|
return None
|
87
84
|
|
88
85
|
def auto_crop_offset(self):
|
@@ -96,26 +93,13 @@ class AutoCrop:
|
|
96
93
|
async def _init_auto_crop(self):
|
97
94
|
"""Initialize the auto crop data."""
|
98
95
|
if not self.imh.auto_crop and self.imh.shared.vacuum_state == "docked":
|
99
|
-
self.imh.auto_crop = await self._async_auto_crop_data()
|
96
|
+
self.imh.auto_crop = await self._async_auto_crop_data(self.imh.shared.trims)
|
100
97
|
if self.imh.auto_crop:
|
101
98
|
self.auto_crop_offset()
|
102
99
|
else:
|
103
100
|
self.imh.max_frames = 5
|
104
101
|
return self.imh.auto_crop
|
105
102
|
|
106
|
-
# async def _async_save_auto_crop_data(self):
|
107
|
-
# """Save the auto crop data to the disk."""
|
108
|
-
# try:
|
109
|
-
# if not os.path.exists(self.path_to_data):
|
110
|
-
# data = TrimCropData(
|
111
|
-
# self.imh.trim_left,
|
112
|
-
# self.imh.trim_up,
|
113
|
-
# self.imh.trim_right,
|
114
|
-
# self.imh.trim_down,
|
115
|
-
# ).to_dict()
|
116
|
-
# except Exception as e:
|
117
|
-
# _LOGGER.error(f"Failed to save trim data due to an error: {e}")
|
118
|
-
|
119
103
|
async def async_image_margins(
|
120
104
|
self, image_array: NumpyArray, detect_colour: Color
|
121
105
|
) -> tuple[int, int, int, int]:
|
@@ -6,6 +6,7 @@ Version: v2024.12.0
|
|
6
6
|
|
7
7
|
import asyncio
|
8
8
|
import logging
|
9
|
+
from typing import Dict, List
|
9
10
|
|
10
11
|
from .types import (
|
11
12
|
ATTR_CALIBRATION_POINTS,
|
@@ -36,8 +37,10 @@ from .types import (
|
|
36
37
|
DEFAULT_VALUES,
|
37
38
|
CameraModes,
|
38
39
|
Colors,
|
40
|
+
TrimsData,
|
39
41
|
)
|
40
42
|
|
43
|
+
|
41
44
|
_LOGGER = logging.getLogger(__name__)
|
42
45
|
|
43
46
|
|
@@ -99,8 +102,23 @@ class CameraShared:
|
|
99
102
|
self.map_pred_points = None # Predefined points data
|
100
103
|
self.map_new_path = None # New path data
|
101
104
|
self.map_old_path = None # Old path data
|
102
|
-
self.trim_crop_data = None
|
103
105
|
self.user_language = None # User language
|
106
|
+
self.trim_crop_data = None
|
107
|
+
self.trims: Dict[TrimsData, int] = {
|
108
|
+
TrimsData.TRIM_LEFT: 0,
|
109
|
+
TrimsData.TRIM_UP: 0,
|
110
|
+
TrimsData.TRIM_RIGHT: 0,
|
111
|
+
TrimsData.TRIM_DOWN: 0,
|
112
|
+
}
|
113
|
+
self.skip_room_ids: List[str] = []
|
114
|
+
|
115
|
+
def get_trims_dictionary(self):
|
116
|
+
return {
|
117
|
+
"trim_left": self.trims.get(TrimsData.TRIM_LEFT, 0),
|
118
|
+
"trim_up": self.trims.get(TrimsData.TRIM_UP, 0),
|
119
|
+
"trim_right": self.trims.get(TrimsData.TRIM_RIGHT, 0),
|
120
|
+
"trim_down": self.trims.get(TrimsData.TRIM_DOWN, 0),
|
121
|
+
}
|
104
122
|
|
105
123
|
def update_user_colors(self, user_colors):
|
106
124
|
"""Update the user colors."""
|
@@ -218,11 +236,24 @@ class CameraSharedManager:
|
|
218
236
|
instance.vacuum_status_position = device_info.get(
|
219
237
|
CONF_VAC_STAT_POS, DEFAULT_VALUES["vac_status_position"]
|
220
238
|
)
|
221
|
-
|
222
239
|
# If enable_snapshots, check for png in www.
|
223
240
|
instance.enable_snapshots = device_info.get(
|
224
241
|
CONF_SNAPSHOTS_ENABLE, DEFAULT_VALUES["enable_www_snapshots"]
|
225
242
|
)
|
243
|
+
instance.trims = {
|
244
|
+
TrimsData.TRIM_LEFT: device_info.get(
|
245
|
+
"trims_data", DEFAULT_VALUES["trims_data"]
|
246
|
+
).get("trim_left", 0),
|
247
|
+
TrimsData.TRIM_UP: device_info.get(
|
248
|
+
"trims_data", DEFAULT_VALUES["trims_data"]
|
249
|
+
).get("trim_up", 0),
|
250
|
+
TrimsData.TRIM_RIGHT: device_info.get(
|
251
|
+
"trims_data", DEFAULT_VALUES["trims_data"]
|
252
|
+
).get("trim_right", 0),
|
253
|
+
TrimsData.TRIM_DOWN: device_info.get(
|
254
|
+
"trims_data", DEFAULT_VALUES["trims_data"]
|
255
|
+
).get("trim_down", 0),
|
256
|
+
}
|
226
257
|
|
227
258
|
except TypeError as ex:
|
228
259
|
_LOGGER.error("Shared data can't be initialized due to a TypeError! %s", ex)
|
@@ -7,11 +7,13 @@ import asyncio
|
|
7
7
|
import json
|
8
8
|
import logging
|
9
9
|
from dataclasses import dataclass
|
10
|
+
from enum import Enum
|
10
11
|
from typing import Any, Dict, Tuple, Union
|
11
12
|
|
12
13
|
import numpy as np
|
13
14
|
from PIL import Image
|
14
15
|
|
16
|
+
|
15
17
|
DEFAULT_ROOMS = 1
|
16
18
|
|
17
19
|
MY_LOGGER = logging.getLogger(__name__)
|
@@ -283,6 +285,7 @@ DEFAULT_VALUES = {
|
|
283
285
|
"vac_status_position": True,
|
284
286
|
"get_svg_file": False,
|
285
287
|
"save_trims": True,
|
288
|
+
"trims_data": {"trim_left": 0, "trim_up": 0, "trim_right": 0, "trim_down": 0},
|
286
289
|
"enable_www_snapshots": False,
|
287
290
|
"color_charger": [255, 128, 0],
|
288
291
|
"color_move": [238, 247, 255],
|
@@ -344,6 +347,7 @@ KEYS_TO_UPDATE = [
|
|
344
347
|
"offset_bottom",
|
345
348
|
"offset_left",
|
346
349
|
"offset_right",
|
350
|
+
"trims_data",
|
347
351
|
"auto_zoom",
|
348
352
|
"zoom_lock_ratio",
|
349
353
|
"show_vac_status",
|
@@ -587,3 +591,12 @@ class CameraModes:
|
|
587
591
|
CAMERA_STANDBY = "camera_standby"
|
588
592
|
CAMERA_OFF = False
|
589
593
|
CAMERA_ON = True
|
594
|
+
|
595
|
+
|
596
|
+
class TrimsData(Enum):
|
597
|
+
"""Constants for the trims data."""
|
598
|
+
|
599
|
+
TRIM_LEFT = "trim_left"
|
600
|
+
TRIM_UP = "trim_up"
|
601
|
+
TRIM_RIGHT = "trim_right"
|
602
|
+
TRIM_DOWN = "trim_down"
|
@@ -4,10 +4,12 @@ import hashlib
|
|
4
4
|
import json
|
5
5
|
from dataclasses import dataclass
|
6
6
|
from logging import getLogger
|
7
|
+
from typing import Callable, List, Optional
|
7
8
|
|
8
|
-
from PIL import
|
9
|
+
from PIL import ImageOps
|
10
|
+
|
11
|
+
from .types import ChargerPosition, ImageSize, NumpyArray, PilPNG, RobotPosition
|
9
12
|
|
10
|
-
from .types import ChargerPosition, ImageSize, NumpyArray, RobotPosition
|
11
13
|
|
12
14
|
_LOGGER = getLogger(__name__)
|
13
15
|
|
@@ -16,13 +18,13 @@ _LOGGER = getLogger(__name__)
|
|
16
18
|
class ResizeParams:
|
17
19
|
"""Resize the image to the given dimensions and aspect ratio."""
|
18
20
|
|
19
|
-
pil_img:
|
21
|
+
pil_img: PilPNG
|
20
22
|
width: int
|
21
23
|
height: int
|
22
|
-
aspect_ratio: str
|
23
|
-
crop_size:
|
24
|
-
is_rand: bool = False
|
25
|
-
offset_func:
|
24
|
+
aspect_ratio: str
|
25
|
+
crop_size: List[int]
|
26
|
+
is_rand: Optional[bool] = False
|
27
|
+
offset_func: Optional[Callable] = None
|
26
28
|
|
27
29
|
|
28
30
|
@dataclass
|
@@ -33,7 +35,7 @@ class OffsetParams:
|
|
33
35
|
hsf: int
|
34
36
|
width: int
|
35
37
|
height: int
|
36
|
-
rand256: bool = False
|
38
|
+
rand256: Optional[bool] = False
|
37
39
|
|
38
40
|
|
39
41
|
class BaseHandler:
|
@@ -91,7 +93,7 @@ class BaseHandler:
|
|
91
93
|
)
|
92
94
|
|
93
95
|
def _set_image_offset_ratio_1_1(
|
94
|
-
self, width: int, height: int, rand256: bool = False
|
96
|
+
self, width: int, height: int, rand256: Optional[bool] = False
|
95
97
|
) -> None:
|
96
98
|
"""Set the image offset ratio to 1:1."""
|
97
99
|
|
@@ -118,7 +120,7 @@ class BaseHandler:
|
|
118
120
|
)
|
119
121
|
|
120
122
|
def _set_image_offset_ratio_2_1(
|
121
|
-
self, width: int, height: int, rand256: bool = False
|
123
|
+
self, width: int, height: int, rand256: Optional[bool] = False
|
122
124
|
) -> None:
|
123
125
|
"""Set the image offset ratio to 2:1."""
|
124
126
|
|
@@ -146,7 +148,7 @@ class BaseHandler:
|
|
146
148
|
)
|
147
149
|
|
148
150
|
def _set_image_offset_ratio_3_2(
|
149
|
-
self, width: int, height: int, rand256: bool = False
|
151
|
+
self, width: int, height: int, rand256: Optional[bool] = False
|
150
152
|
) -> None:
|
151
153
|
"""Set the image offset ratio to 3:2."""
|
152
154
|
|
@@ -177,7 +179,7 @@ class BaseHandler:
|
|
177
179
|
)
|
178
180
|
|
179
181
|
def _set_image_offset_ratio_5_4(
|
180
|
-
self, width: int, height: int, rand256: bool = False
|
182
|
+
self, width: int, height: int, rand256: Optional[bool] = False
|
181
183
|
) -> None:
|
182
184
|
"""Set the image offset ratio to 5:4."""
|
183
185
|
|
@@ -209,7 +211,7 @@ class BaseHandler:
|
|
209
211
|
)
|
210
212
|
|
211
213
|
def _set_image_offset_ratio_9_16(
|
212
|
-
self, width: int, height: int, rand256: bool = False
|
214
|
+
self, width: int, height: int, rand256: Optional[bool] = False
|
213
215
|
) -> None:
|
214
216
|
"""Set the image offset ratio to 9:16."""
|
215
217
|
|
@@ -237,7 +239,7 @@ class BaseHandler:
|
|
237
239
|
)
|
238
240
|
|
239
241
|
def _set_image_offset_ratio_16_9(
|
240
|
-
self, width: int, height: int, rand256: bool = False
|
242
|
+
self, width: int, height: int, rand256: Optional[bool] = False
|
241
243
|
) -> None:
|
242
244
|
"""Set the image offset ratio to 16:9."""
|
243
245
|
|
@@ -298,8 +300,8 @@ class BaseHandler:
|
|
298
300
|
|
299
301
|
@staticmethod
|
300
302
|
async def calculate_array_hash(
|
301
|
-
layers: dict, active:
|
302
|
-
) -> str
|
303
|
+
layers: dict, active: Optional[List[int]]
|
304
|
+
) -> str | None:
|
303
305
|
"""Calculate the hash of the image based on layers and active zones."""
|
304
306
|
if layers and active:
|
305
307
|
data_to_hash = {
|
@@ -499,7 +501,7 @@ async def async_resize_image(params: ResizeParams):
|
|
499
501
|
str(hsf),
|
500
502
|
)
|
501
503
|
|
502
|
-
if params.crop_size is not None:
|
504
|
+
if (params.crop_size is not None) and (params.offset_func is not None):
|
503
505
|
offset = OffsetParams(wsf, hsf, new_width, new_height, params.is_rand)
|
504
506
|
params.crop_size[0], params.crop_size[1] = await params.offset_func(offset)
|
505
507
|
|
@@ -507,6 +509,7 @@ async def async_resize_image(params: ResizeParams):
|
|
507
509
|
|
508
510
|
return ImageOps.pad(params.pil_img, (params.width, params.height))
|
509
511
|
|
512
|
+
|
510
513
|
def prepare_resize_params(handler, pil_img, rand):
|
511
514
|
"""Prepare resize parameters for image resizing."""
|
512
515
|
return ResizeParams(
|
@@ -516,5 +519,5 @@ def prepare_resize_params(handler, pil_img, rand):
|
|
516
519
|
aspect_ratio=handler.shared.image_aspect_ratio,
|
517
520
|
crop_size=handler.crop_img_size,
|
518
521
|
offset_func=handler.async_map_coordinates_offset,
|
519
|
-
is_rand=rand
|
522
|
+
is_rand=rand,
|
520
523
|
)
|
@@ -15,11 +15,12 @@ from PIL import Image
|
|
15
15
|
from .config.auto_crop import AutoCrop
|
16
16
|
from .config.drawable import Drawable
|
17
17
|
from .config.shared import CameraShared
|
18
|
-
from .config.types import COLORS, CalibrationPoints, Colors, RoomsProperties
|
18
|
+
from .config.types import COLORS, CalibrationPoints, Colors, RoomsProperties, TrimsData
|
19
19
|
from .config.utils import BaseHandler, prepare_resize_params
|
20
20
|
from .hypfer_draw import ImageDraw as ImDraw
|
21
21
|
from .map_data import ImageData
|
22
22
|
|
23
|
+
|
23
24
|
_LOGGER = logging.getLogger(__name__)
|
24
25
|
|
25
26
|
|
@@ -41,10 +42,18 @@ class HypferMapImageHandler(BaseHandler):
|
|
41
42
|
self.img_base_layer = None # numpy array store the map base layer.
|
42
43
|
self.active_zones = None # vacuum active zones.
|
43
44
|
self.svg_wait = False # SVG image creation wait.
|
44
|
-
self.
|
45
|
-
|
46
|
-
|
47
|
-
self.
|
45
|
+
self.trim_up = self.shared.trims.get(
|
46
|
+
TrimsData.TRIM_UP, 0
|
47
|
+
) # memory stored trims calculated once.
|
48
|
+
self.trim_down = self.shared.trims.get(
|
49
|
+
TrimsData.TRIM_DOWN, 0
|
50
|
+
) # memory stored trims calculated once.
|
51
|
+
self.trim_left = self.shared.trims.get(
|
52
|
+
TrimsData.TRIM_LEFT, 0
|
53
|
+
) # memory stored trims calculated once.
|
54
|
+
self.trim_right = self.shared.trims.get(
|
55
|
+
TrimsData.TRIM_RIGHT, 0
|
56
|
+
) # memory stored trims calculated once.
|
48
57
|
self.offset_top = self.shared.offset_top # offset top
|
49
58
|
self.offset_bottom = self.shared.offset_down # offset bottom
|
50
59
|
self.offset_left = self.shared.offset_left # offset left
|
@@ -23,11 +23,13 @@ from .config.types import (
|
|
23
23
|
PilPNG,
|
24
24
|
RobotPosition,
|
25
25
|
RoomsProperties,
|
26
|
+
TrimsData,
|
26
27
|
)
|
27
28
|
from .config.utils import BaseHandler, prepare_resize_params
|
28
29
|
from .map_data import RandImageData
|
29
30
|
from .reimg_draw import ImageDraw
|
30
31
|
|
32
|
+
|
31
33
|
_LOGGER = logging.getLogger(__name__)
|
32
34
|
|
33
35
|
|
@@ -51,10 +53,18 @@ class ReImageHandler(BaseHandler):
|
|
51
53
|
self.room_propriety = None # Room propriety data
|
52
54
|
self.shared = camera_shared # Shared data
|
53
55
|
self.active_zones = None # Active zones
|
54
|
-
self.
|
55
|
-
|
56
|
-
|
57
|
-
self.
|
56
|
+
self.trim_up = self.shared.trims.get(
|
57
|
+
TrimsData.TRIM_UP, 0
|
58
|
+
) # memory stored trims calculated once.
|
59
|
+
self.trim_down = self.shared.trims.get(
|
60
|
+
TrimsData.TRIM_DOWN, 0
|
61
|
+
) # memory stored trims calculated once.
|
62
|
+
self.trim_left = self.shared.trims.get(
|
63
|
+
TrimsData.TRIM_LEFT, 0
|
64
|
+
) # memory stored trims calculated once.
|
65
|
+
self.trim_right = self.shared.trims.get(
|
66
|
+
TrimsData.TRIM_RIGHT, 0
|
67
|
+
) # memory stored trims calculated once.
|
58
68
|
self.file_name = self.shared.file_name # File name
|
59
69
|
self.offset_top = self.shared.offset_top # offset top
|
60
70
|
self.offset_bottom = self.shared.offset_down # offset bottom
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "valetudo-map-parser"
|
3
|
-
version = "0.1.9.
|
3
|
+
version = "0.1.9.b24"
|
4
4
|
description = "A Python library to parse Valetudo map data returning a PIL Image object."
|
5
5
|
authors = ["Sandro Cantarella <gsca075@gmail.com>"]
|
6
6
|
license = "Apache-2.0"
|
@@ -41,8 +41,9 @@ lines_after_imports = 2
|
|
41
41
|
|
42
42
|
# Pylint settings
|
43
43
|
[tool.pylint]
|
44
|
-
disable = ["C0103", "C0116", "R0902", "R0903", "R0913",
|
45
|
-
|
44
|
+
disable = ["C0103", "C0116", "R0902", "R0903", "R0904","R0913",
|
45
|
+
"R0914", "R0917", "R0915", "W0640"]
|
46
|
+
|
46
47
|
max-line-length = 120
|
47
48
|
|
48
49
|
[build-system]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/map_data.py
RENAMED
File without changes
|
{valetudo_map_parser-0.1.9b22 → valetudo_map_parser-0.1.9b24}/SCR/valetudo_map_parser/py.typed
RENAMED
File without changes
|