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
|
@@ -4,29 +4,27 @@ Version 0.0.1
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import asyncio
|
|
7
|
-
from dataclasses import dataclass
|
|
8
7
|
import json
|
|
9
8
|
import logging
|
|
10
|
-
|
|
9
|
+
import threading
|
|
10
|
+
from dataclasses import asdict, dataclass
|
|
11
|
+
from typing import Any, Dict, Optional, Tuple, TypedDict, Union
|
|
11
12
|
|
|
12
|
-
from PIL import Image
|
|
13
13
|
import numpy as np
|
|
14
|
+
from PIL import Image
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
DEFAULT_ROOMS = 1
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
LOGGER = logging.getLogger(__package__)
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
JsonType = Any # json.loads() return type is Any
|
|
27
|
-
PilPNG = Image.Image
|
|
28
|
-
NumpyArray = np.ndarray
|
|
29
|
-
Point = Tuple[int, int]
|
|
21
|
+
|
|
22
|
+
class RoomProperty(TypedDict):
|
|
23
|
+
number: int
|
|
24
|
+
outline: list[tuple[int, int]]
|
|
25
|
+
name: str
|
|
26
|
+
x: int
|
|
27
|
+
y: int
|
|
30
28
|
|
|
31
29
|
|
|
32
30
|
# pylint: disable=no-member
|
|
@@ -73,43 +71,37 @@ class TrimCropData:
|
|
|
73
71
|
)
|
|
74
72
|
|
|
75
73
|
|
|
76
|
-
# pylint: disable=no-member
|
|
77
74
|
class RoomStore:
|
|
78
|
-
""
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
75
|
+
_instances: Dict[str, "RoomStore"] = {}
|
|
76
|
+
_lock = threading.Lock()
|
|
77
|
+
|
|
78
|
+
def __new__(cls, vacuum_id: str, rooms_data: Optional[dict] = None) -> "RoomStore":
|
|
79
|
+
with cls._lock:
|
|
80
|
+
if vacuum_id not in cls._instances:
|
|
81
|
+
instance = super(RoomStore, cls).__new__(cls)
|
|
82
|
+
instance.vacuum_id = vacuum_id
|
|
83
|
+
instance.vacuums_data = rooms_data or {}
|
|
84
|
+
cls._instances[vacuum_id] = instance
|
|
85
|
+
else:
|
|
86
|
+
if rooms_data is not None:
|
|
87
|
+
cls._instances[vacuum_id].vacuums_data = rooms_data
|
|
88
|
+
return cls._instances[vacuum_id]
|
|
89
|
+
|
|
90
|
+
def get_rooms(self) -> dict:
|
|
91
|
+
return self.vacuums_data
|
|
92
|
+
|
|
93
|
+
def set_rooms(self, rooms_data: dict) -> None:
|
|
94
|
+
self.vacuums_data = rooms_data
|
|
95
|
+
|
|
96
|
+
def get_rooms_count(self) -> int:
|
|
97
|
+
if isinstance(self.vacuums_data, dict):
|
|
98
|
+
count = len(self.vacuums_data)
|
|
99
|
+
return count if count > 0 else DEFAULT_ROOMS
|
|
100
|
+
return DEFAULT_ROOMS
|
|
96
101
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
data = self.vacuums_data.get(vacuum_id, {})
|
|
101
|
-
if isinstance(data, str):
|
|
102
|
-
json_data = json.loads(data)
|
|
103
|
-
return json_data
|
|
104
|
-
return data
|
|
105
|
-
|
|
106
|
-
async def async_get_rooms_count(self, vacuum_id: str) -> int:
|
|
107
|
-
"""Count the number of rooms for a vacuum."""
|
|
108
|
-
async with self._lock:
|
|
109
|
-
count = len(self.vacuums_data.get(vacuum_id, {}))
|
|
110
|
-
if count == 0:
|
|
111
|
-
return DEFAULT_ROOMS
|
|
112
|
-
return count
|
|
102
|
+
@classmethod
|
|
103
|
+
def get_all_instances(cls) -> Dict[str, "RoomStore"]:
|
|
104
|
+
return cls._instances
|
|
113
105
|
|
|
114
106
|
|
|
115
107
|
# pylint: disable=no-member
|
|
@@ -202,8 +194,20 @@ class SnapshotStore:
|
|
|
202
194
|
self.vacuum_json_data[vacuum_id] = json_data
|
|
203
195
|
|
|
204
196
|
|
|
197
|
+
Color = Union[Tuple[int, int, int], Tuple[int, int, int, int]]
|
|
198
|
+
Colors = Dict[str, Color]
|
|
199
|
+
CalibrationPoints = list[dict[str, Any]]
|
|
200
|
+
RobotPosition = dict[str, int | float]
|
|
201
|
+
ChargerPosition = dict[str, Any]
|
|
202
|
+
RoomsProperties = dict[str, RoomProperty]
|
|
203
|
+
ImageSize = dict[str, int | list[int]]
|
|
204
|
+
JsonType = Any # json.loads() return type is Any
|
|
205
|
+
PilPNG = Image.Image # Keep for backward compatibility
|
|
206
|
+
WebPBytes = bytes # WebP image as bytes
|
|
207
|
+
NumpyArray = np.ndarray
|
|
208
|
+
Point = Tuple[int, int]
|
|
209
|
+
|
|
205
210
|
CAMERA_STORAGE = "valetudo_camera"
|
|
206
|
-
DEFAULT_ROOMS = 1 # 15 is the maximum number of rooms.
|
|
207
211
|
ATTR_ROTATE = "rotate_image"
|
|
208
212
|
ATTR_CROP = "crop_image"
|
|
209
213
|
ATTR_MARGINS = "margins"
|
|
@@ -284,6 +288,7 @@ DEFAULT_VALUES = {
|
|
|
284
288
|
"vac_status_position": True,
|
|
285
289
|
"get_svg_file": False,
|
|
286
290
|
"save_trims": True,
|
|
291
|
+
"trims_data": {"trim_left": 0, "trim_up": 0, "trim_right": 0, "trim_down": 0},
|
|
287
292
|
"enable_www_snapshots": False,
|
|
288
293
|
"color_charger": [255, 128, 0],
|
|
289
294
|
"color_move": [238, 247, 255],
|
|
@@ -345,6 +350,7 @@ KEYS_TO_UPDATE = [
|
|
|
345
350
|
"offset_bottom",
|
|
346
351
|
"offset_left",
|
|
347
352
|
"offset_right",
|
|
353
|
+
"trims_data",
|
|
348
354
|
"auto_zoom",
|
|
349
355
|
"zoom_lock_ratio",
|
|
350
356
|
"show_vac_status",
|
|
@@ -562,7 +568,8 @@ ALPHA_ROOM_15 = "alpha_room_15"
|
|
|
562
568
|
|
|
563
569
|
""" Constants for the attribute keys """
|
|
564
570
|
ATTR_FRIENDLY_NAME = "friendly_name"
|
|
565
|
-
ATTR_VACUUM_BATTERY = "
|
|
571
|
+
ATTR_VACUUM_BATTERY = "battery"
|
|
572
|
+
ATTR_VACUUM_CHARGING = "charging"
|
|
566
573
|
ATTR_VACUUM_POSITION = "vacuum_position"
|
|
567
574
|
ATTR_VACUUM_TOPIC = "vacuum_topic"
|
|
568
575
|
ATTR_VACUUM_STATUS = "vacuum_status"
|
|
@@ -588,3 +595,49 @@ class CameraModes:
|
|
|
588
595
|
CAMERA_STANDBY = "camera_standby"
|
|
589
596
|
CAMERA_OFF = False
|
|
590
597
|
CAMERA_ON = True
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
# noinspection PyTypeChecker
|
|
601
|
+
@dataclass
|
|
602
|
+
class TrimsData:
|
|
603
|
+
"""Dataclass to store and manage trims data."""
|
|
604
|
+
|
|
605
|
+
floor: str = ""
|
|
606
|
+
trim_up: int = 0
|
|
607
|
+
trim_left: int = 0
|
|
608
|
+
trim_down: int = 0
|
|
609
|
+
trim_right: int = 0
|
|
610
|
+
|
|
611
|
+
@classmethod
|
|
612
|
+
def from_json(cls, json_data: str):
|
|
613
|
+
"""Create a TrimsConfig instance from a JSON string."""
|
|
614
|
+
data = json.loads(json_data)
|
|
615
|
+
return cls(
|
|
616
|
+
floor=data.get("floor", ""),
|
|
617
|
+
trim_up=data.get("trim_up", 0),
|
|
618
|
+
trim_left=data.get("trim_left", 0),
|
|
619
|
+
trim_down=data.get("trim_down", 0),
|
|
620
|
+
trim_right=data.get("trim_right", 0),
|
|
621
|
+
)
|
|
622
|
+
|
|
623
|
+
def to_json(self) -> str:
|
|
624
|
+
"""Convert TrimsConfig instance to a JSON string."""
|
|
625
|
+
return json.dumps(asdict(self))
|
|
626
|
+
|
|
627
|
+
@classmethod
|
|
628
|
+
def from_dict(cls, data: dict):
|
|
629
|
+
"""Initialize TrimData from a dictionary."""
|
|
630
|
+
return cls(**data)
|
|
631
|
+
|
|
632
|
+
def to_dict(self) -> dict:
|
|
633
|
+
"""Convert TrimData to a dictionary."""
|
|
634
|
+
return asdict(self)
|
|
635
|
+
|
|
636
|
+
def clear(self) -> dict:
|
|
637
|
+
"""Clear all the trims."""
|
|
638
|
+
self.floor = ""
|
|
639
|
+
self.trim_up = 0
|
|
640
|
+
self.trim_left = 0
|
|
641
|
+
self.trim_down = 0
|
|
642
|
+
self.trim_right = 0
|
|
643
|
+
return asdict(self)
|