valetudo-map-parser 0.1.11b1__tar.gz → 0.1.12b0__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.11b1 → valetudo_map_parser-0.1.12b0}/PKG-INFO +1 -1
- valetudo_map_parser-0.1.12b0/SCR/valetudo_map_parser/__init__.py +175 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/async_utils.py +1 -1
- valetudo_map_parser-0.1.12b0/SCR/valetudo_map_parser/config/colors.py +410 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/drawable.py +10 -73
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/rand256_parser.py +129 -111
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/shared.py +27 -8
- valetudo_map_parser-0.1.12b0/SCR/valetudo_map_parser/config/status_text/__init__.py +6 -0
- valetudo_map_parser-0.1.12b0/SCR/valetudo_map_parser/config/status_text/status_text.py +121 -0
- valetudo_map_parser-0.1.12b0/SCR/valetudo_map_parser/config/types.py +337 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/utils.py +99 -75
- valetudo_map_parser-0.1.12b0/SCR/valetudo_map_parser/const.py +288 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/hypfer_draw.py +121 -150
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/hypfer_handler.py +210 -183
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/map_data.py +31 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/rand256_handler.py +207 -218
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/rooms_handler.py +4 -5
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/pyproject.toml +1 -1
- valetudo_map_parser-0.1.11b1/SCR/valetudo_map_parser/__init__.py +0 -66
- valetudo_map_parser-0.1.11b1/SCR/valetudo_map_parser/config/colors.py +0 -827
- valetudo_map_parser-0.1.11b1/SCR/valetudo_map_parser/config/status_text/status_text.py +0 -96
- valetudo_map_parser-0.1.11b1/SCR/valetudo_map_parser/config/types.py +0 -671
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/LICENSE +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/NOTICE.txt +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/README.md +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/__init__.py +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/drawable_elements.py +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/fonts/FiraSans.ttf +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/fonts/Inter-VF.ttf +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/fonts/Lato-Regular.ttf +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/fonts/MPLUSRegular.ttf +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/fonts/NotoKufiArabic-VF.ttf +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/fonts/NotoSansCJKhk-VF.ttf +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/fonts/NotoSansKhojki.ttf +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/optimized_element_map.py +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/config/status_text/translations.py +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/py.typed +0 -0
- {valetudo_map_parser-0.1.11b1 → valetudo_map_parser-0.1.12b0}/SCR/valetudo_map_parser/reimg_draw.py +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""Valetudo map parser.
|
|
2
|
+
Version: 0.1.12"""
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .config.colors import ColorsManagement
|
|
7
|
+
from .config.drawable import Drawable
|
|
8
|
+
from .config.drawable_elements import DrawableElement, DrawingConfig
|
|
9
|
+
from .config.rand256_parser import RRMapParser
|
|
10
|
+
from .config.shared import CameraShared, CameraSharedManager
|
|
11
|
+
from .config.status_text.status_text import StatusText
|
|
12
|
+
from .config.status_text.translations import translations as STATUS_TEXT_TRANSLATIONS
|
|
13
|
+
from .config.types import (
|
|
14
|
+
CameraModes,
|
|
15
|
+
ImageSize,
|
|
16
|
+
JsonType,
|
|
17
|
+
NumpyArray,
|
|
18
|
+
PilPNG,
|
|
19
|
+
RoomsProperties,
|
|
20
|
+
RoomStore,
|
|
21
|
+
SnapshotStore,
|
|
22
|
+
TrimCropData,
|
|
23
|
+
UserLanguageStore,
|
|
24
|
+
)
|
|
25
|
+
from .config.utils import ResizeParams, async_resize_image
|
|
26
|
+
from .const import (
|
|
27
|
+
ATTR_CALIBRATION_POINTS,
|
|
28
|
+
ATTR_CAMERA_MODE,
|
|
29
|
+
ATTR_CONTENT_TYPE,
|
|
30
|
+
ATTR_FRIENDLY_NAME,
|
|
31
|
+
ATTR_IMAGE_LAST_UPDATED,
|
|
32
|
+
ATTR_JSON_DATA,
|
|
33
|
+
ATTR_OBSTACLES,
|
|
34
|
+
ATTR_POINTS,
|
|
35
|
+
ATTR_ROOMS,
|
|
36
|
+
ATTR_ROTATE,
|
|
37
|
+
ATTR_SNAPSHOT,
|
|
38
|
+
ATTR_SNAPSHOT_PATH,
|
|
39
|
+
ATTR_VACUUM_BATTERY,
|
|
40
|
+
ATTR_VACUUM_CHARGING,
|
|
41
|
+
ATTR_VACUUM_JSON_ID,
|
|
42
|
+
ATTR_VACUUM_POSITION,
|
|
43
|
+
ATTR_VACUUM_STATUS,
|
|
44
|
+
ATTR_VACUUM_TOPIC,
|
|
45
|
+
ATTR_ZONES,
|
|
46
|
+
CAMERA_STORAGE,
|
|
47
|
+
COLORS,
|
|
48
|
+
CONF_ASPECT_RATIO,
|
|
49
|
+
CONF_AUTO_ZOOM,
|
|
50
|
+
CONF_EXPORT_SVG,
|
|
51
|
+
CONF_OFFSET_BOTTOM,
|
|
52
|
+
CONF_OFFSET_LEFT,
|
|
53
|
+
CONF_OFFSET_RIGHT,
|
|
54
|
+
CONF_OFFSET_TOP,
|
|
55
|
+
CONF_SNAPSHOTS_ENABLE,
|
|
56
|
+
CONF_TRIMS_SAVE,
|
|
57
|
+
CONF_VACUUM_CONFIG_ENTRY_ID,
|
|
58
|
+
CONF_VACUUM_CONNECTION_STRING,
|
|
59
|
+
CONF_VACUUM_ENTITY_ID,
|
|
60
|
+
CONF_VACUUM_IDENTIFIERS,
|
|
61
|
+
CONF_VAC_STAT,
|
|
62
|
+
CONF_VAC_STAT_FONT,
|
|
63
|
+
CONF_VAC_STAT_POS,
|
|
64
|
+
CONF_VAC_STAT_SIZE,
|
|
65
|
+
CONF_ZOOM_LOCK_RATIO,
|
|
66
|
+
DECODED_TOPICS,
|
|
67
|
+
DEFAULT_IMAGE_SIZE,
|
|
68
|
+
DEFAULT_PIXEL_SIZE,
|
|
69
|
+
DEFAULT_VALUES,
|
|
70
|
+
FONTS_AVAILABLE,
|
|
71
|
+
ICON,
|
|
72
|
+
NAME,
|
|
73
|
+
NON_DECODED_TOPICS,
|
|
74
|
+
NOT_STREAMING_STATES,
|
|
75
|
+
SENSOR_NO_DATA,
|
|
76
|
+
)
|
|
77
|
+
from .hypfer_handler import HypferMapImageHandler
|
|
78
|
+
from .map_data import HyperMapData
|
|
79
|
+
from .rand256_handler import ReImageHandler
|
|
80
|
+
from .rooms_handler import RandRoomsHandler, RoomsHandler
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_default_font_path() -> str:
|
|
84
|
+
"""Return the absolute path to the bundled default font directory.
|
|
85
|
+
|
|
86
|
+
This returns the path to the fonts folder; the caller can join a specific font file
|
|
87
|
+
to avoid hard-coding a particular font here.
|
|
88
|
+
"""
|
|
89
|
+
return str((Path(__file__).resolve().parent / "config" / "fonts").resolve())
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
__all__ = [
|
|
93
|
+
# Attribute Constants
|
|
94
|
+
"ATTR_CALIBRATION_POINTS",
|
|
95
|
+
"ATTR_CAMERA_MODE",
|
|
96
|
+
"ATTR_CONTENT_TYPE",
|
|
97
|
+
"ATTR_FRIENDLY_NAME",
|
|
98
|
+
"ATTR_IMAGE_LAST_UPDATED",
|
|
99
|
+
"ATTR_JSON_DATA",
|
|
100
|
+
"ATTR_OBSTACLES",
|
|
101
|
+
"ATTR_POINTS",
|
|
102
|
+
"ATTR_ROOMS",
|
|
103
|
+
"ATTR_ROTATE",
|
|
104
|
+
"ATTR_SNAPSHOT",
|
|
105
|
+
"ATTR_SNAPSHOT_PATH",
|
|
106
|
+
"ATTR_VACUUM_BATTERY",
|
|
107
|
+
"ATTR_VACUUM_CHARGING",
|
|
108
|
+
"ATTR_VACUUM_JSON_ID",
|
|
109
|
+
"ATTR_VACUUM_POSITION",
|
|
110
|
+
"ATTR_VACUUM_STATUS",
|
|
111
|
+
"ATTR_VACUUM_TOPIC",
|
|
112
|
+
"ATTR_ZONES",
|
|
113
|
+
# Configuration Constants
|
|
114
|
+
"CAMERA_STORAGE",
|
|
115
|
+
"COLORS",
|
|
116
|
+
"CONF_ASPECT_RATIO",
|
|
117
|
+
"CONF_AUTO_ZOOM",
|
|
118
|
+
"CONF_EXPORT_SVG",
|
|
119
|
+
"CONF_OFFSET_BOTTOM",
|
|
120
|
+
"CONF_OFFSET_LEFT",
|
|
121
|
+
"CONF_OFFSET_RIGHT",
|
|
122
|
+
"CONF_OFFSET_TOP",
|
|
123
|
+
"CONF_SNAPSHOTS_ENABLE",
|
|
124
|
+
"CONF_TRIMS_SAVE",
|
|
125
|
+
"CONF_VACUUM_CONFIG_ENTRY_ID",
|
|
126
|
+
"CONF_VACUUM_CONNECTION_STRING",
|
|
127
|
+
"CONF_VACUUM_ENTITY_ID",
|
|
128
|
+
"CONF_VACUUM_IDENTIFIERS",
|
|
129
|
+
"CONF_VAC_STAT",
|
|
130
|
+
"CONF_VAC_STAT_FONT",
|
|
131
|
+
"CONF_VAC_STAT_POS",
|
|
132
|
+
"CONF_VAC_STAT_SIZE",
|
|
133
|
+
"CONF_ZOOM_LOCK_RATIO",
|
|
134
|
+
# Default Values
|
|
135
|
+
"DECODED_TOPICS",
|
|
136
|
+
"DEFAULT_IMAGE_SIZE",
|
|
137
|
+
"DEFAULT_PIXEL_SIZE",
|
|
138
|
+
"DEFAULT_VALUES",
|
|
139
|
+
"FONTS_AVAILABLE",
|
|
140
|
+
"ICON",
|
|
141
|
+
"NAME",
|
|
142
|
+
"NON_DECODED_TOPICS",
|
|
143
|
+
"NOT_STREAMING_STATES",
|
|
144
|
+
"SENSOR_NO_DATA",
|
|
145
|
+
# Classes and Handlers
|
|
146
|
+
"CameraShared",
|
|
147
|
+
"CameraSharedManager",
|
|
148
|
+
"ColorsManagement",
|
|
149
|
+
"Drawable",
|
|
150
|
+
"DrawableElement",
|
|
151
|
+
"DrawingConfig",
|
|
152
|
+
"HyperMapData",
|
|
153
|
+
"HypferMapImageHandler",
|
|
154
|
+
"RRMapParser",
|
|
155
|
+
"RandRoomsHandler",
|
|
156
|
+
"ReImageHandler",
|
|
157
|
+
"RoomsHandler",
|
|
158
|
+
"StatusText",
|
|
159
|
+
# Types
|
|
160
|
+
"CameraModes",
|
|
161
|
+
"ImageSize",
|
|
162
|
+
"JsonType",
|
|
163
|
+
"NumpyArray",
|
|
164
|
+
"PilPNG",
|
|
165
|
+
"RoomsProperties",
|
|
166
|
+
"RoomStore",
|
|
167
|
+
"SnapshotStore",
|
|
168
|
+
"TrimCropData",
|
|
169
|
+
"UserLanguageStore",
|
|
170
|
+
# Utilities
|
|
171
|
+
"ResizeParams",
|
|
172
|
+
"STATUS_TEXT_TRANSLATIONS",
|
|
173
|
+
"async_resize_image",
|
|
174
|
+
"get_default_font_path",
|
|
175
|
+
]
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
"""Colors for the maps Elements."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
from typing import Dict, List, Tuple
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from ..const import (
|
|
11
|
+
ALPHA_BACKGROUND,
|
|
12
|
+
ALPHA_CHARGER,
|
|
13
|
+
ALPHA_GO_TO,
|
|
14
|
+
ALPHA_MOVE,
|
|
15
|
+
ALPHA_NO_GO,
|
|
16
|
+
ALPHA_ROBOT,
|
|
17
|
+
ALPHA_ROOM_0,
|
|
18
|
+
ALPHA_ROOM_1,
|
|
19
|
+
ALPHA_ROOM_2,
|
|
20
|
+
ALPHA_ROOM_3,
|
|
21
|
+
ALPHA_ROOM_4,
|
|
22
|
+
ALPHA_ROOM_5,
|
|
23
|
+
ALPHA_ROOM_6,
|
|
24
|
+
ALPHA_ROOM_7,
|
|
25
|
+
ALPHA_ROOM_8,
|
|
26
|
+
ALPHA_ROOM_9,
|
|
27
|
+
ALPHA_ROOM_10,
|
|
28
|
+
ALPHA_ROOM_11,
|
|
29
|
+
ALPHA_ROOM_12,
|
|
30
|
+
ALPHA_ROOM_13,
|
|
31
|
+
ALPHA_ROOM_14,
|
|
32
|
+
ALPHA_ROOM_15,
|
|
33
|
+
ALPHA_TEXT,
|
|
34
|
+
ALPHA_WALL,
|
|
35
|
+
ALPHA_ZONE_CLEAN,
|
|
36
|
+
COLOR_BACKGROUND,
|
|
37
|
+
COLOR_CHARGER,
|
|
38
|
+
COLOR_GO_TO,
|
|
39
|
+
COLOR_MOVE,
|
|
40
|
+
COLOR_NO_GO,
|
|
41
|
+
COLOR_ROBOT,
|
|
42
|
+
COLOR_ROOM_0,
|
|
43
|
+
COLOR_ROOM_1,
|
|
44
|
+
COLOR_ROOM_2,
|
|
45
|
+
COLOR_ROOM_3,
|
|
46
|
+
COLOR_ROOM_4,
|
|
47
|
+
COLOR_ROOM_5,
|
|
48
|
+
COLOR_ROOM_6,
|
|
49
|
+
COLOR_ROOM_7,
|
|
50
|
+
COLOR_ROOM_8,
|
|
51
|
+
COLOR_ROOM_9,
|
|
52
|
+
COLOR_ROOM_10,
|
|
53
|
+
COLOR_ROOM_11,
|
|
54
|
+
COLOR_ROOM_12,
|
|
55
|
+
COLOR_ROOM_13,
|
|
56
|
+
COLOR_ROOM_14,
|
|
57
|
+
COLOR_ROOM_15,
|
|
58
|
+
COLOR_TEXT,
|
|
59
|
+
COLOR_WALL,
|
|
60
|
+
COLOR_ZONE_CLEAN,
|
|
61
|
+
)
|
|
62
|
+
from .types import LOGGER, Color
|
|
63
|
+
|
|
64
|
+
color_transparent = (0, 0, 0, 0)
|
|
65
|
+
color_charger = (0, 128, 0, 255)
|
|
66
|
+
color_move = (238, 247, 255, 255)
|
|
67
|
+
color_robot = (255, 255, 204, 255)
|
|
68
|
+
color_no_go = (255, 0, 0, 255)
|
|
69
|
+
color_go_to = (0, 255, 0, 255)
|
|
70
|
+
color_background = (0, 125, 255, 255)
|
|
71
|
+
color_zone_clean = (255, 255, 255, 125)
|
|
72
|
+
color_wall = (255, 255, 0, 255)
|
|
73
|
+
color_text = (255, 255, 255, 255)
|
|
74
|
+
color_grey = (125, 125, 125, 255)
|
|
75
|
+
color_black = (0, 0, 0, 255)
|
|
76
|
+
color_room_0 = (135, 206, 250, 255)
|
|
77
|
+
color_room_1 = (176, 226, 255, 255)
|
|
78
|
+
color_room_2 = (164, 211, 238, 255)
|
|
79
|
+
color_room_3 = (141, 182, 205, 255)
|
|
80
|
+
color_room_4 = (96, 123, 139, 255)
|
|
81
|
+
color_room_5 = (224, 255, 255, 255)
|
|
82
|
+
color_room_6 = (209, 238, 238, 255)
|
|
83
|
+
color_room_7 = (180, 205, 205, 255)
|
|
84
|
+
color_room_8 = (122, 139, 139, 255)
|
|
85
|
+
color_room_9 = (175, 238, 238, 255)
|
|
86
|
+
color_room_10 = (84, 153, 199, 255)
|
|
87
|
+
color_room_11 = (133, 193, 233, 255)
|
|
88
|
+
color_room_12 = (245, 176, 65, 255)
|
|
89
|
+
color_room_13 = (82, 190, 128, 255)
|
|
90
|
+
color_room_14 = (72, 201, 176, 255)
|
|
91
|
+
color_room_15 = (165, 105, 18, 255)
|
|
92
|
+
|
|
93
|
+
rooms_color = [
|
|
94
|
+
color_room_0,
|
|
95
|
+
color_room_1,
|
|
96
|
+
color_room_2,
|
|
97
|
+
color_room_3,
|
|
98
|
+
color_room_4,
|
|
99
|
+
color_room_5,
|
|
100
|
+
color_room_6,
|
|
101
|
+
color_room_7,
|
|
102
|
+
color_room_8,
|
|
103
|
+
color_room_9,
|
|
104
|
+
color_room_10,
|
|
105
|
+
color_room_11,
|
|
106
|
+
color_room_12,
|
|
107
|
+
color_room_13,
|
|
108
|
+
color_room_14,
|
|
109
|
+
color_room_15,
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
base_colors_array = [
|
|
113
|
+
color_wall,
|
|
114
|
+
color_zone_clean,
|
|
115
|
+
color_robot,
|
|
116
|
+
color_background,
|
|
117
|
+
color_move,
|
|
118
|
+
color_charger,
|
|
119
|
+
color_no_go,
|
|
120
|
+
color_go_to,
|
|
121
|
+
color_text,
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
color_array = [
|
|
125
|
+
base_colors_array[0], # color_wall
|
|
126
|
+
base_colors_array[6], # color_no_go
|
|
127
|
+
base_colors_array[7], # color_go_to
|
|
128
|
+
color_black,
|
|
129
|
+
base_colors_array[2], # color_robot
|
|
130
|
+
base_colors_array[5], # color_charger
|
|
131
|
+
color_text,
|
|
132
|
+
base_colors_array[4], # color_move
|
|
133
|
+
base_colors_array[3], # color_background
|
|
134
|
+
base_colors_array[1], # color_zone_clean
|
|
135
|
+
color_transparent,
|
|
136
|
+
rooms_color,
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class SupportedColor(StrEnum):
|
|
141
|
+
"""Color of a supported map element."""
|
|
142
|
+
|
|
143
|
+
CHARGER = "color_charger"
|
|
144
|
+
PATH = "color_move"
|
|
145
|
+
PREDICTED_PATH = "color_predicted_move"
|
|
146
|
+
WALLS = "color_wall"
|
|
147
|
+
ROBOT = "color_robot"
|
|
148
|
+
GO_TO = "color_go_to"
|
|
149
|
+
NO_GO = "color_no_go"
|
|
150
|
+
ZONE_CLEAN = "color_zone_clean"
|
|
151
|
+
MAP_BACKGROUND = "color_background"
|
|
152
|
+
TEXT = "color_text"
|
|
153
|
+
TRANSPARENT = "color_transparent"
|
|
154
|
+
COLOR_ROOM_PREFIX = "color_room_"
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def room_key(index: int) -> str:
|
|
158
|
+
return f"{SupportedColor.COLOR_ROOM_PREFIX}{index}"
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class DefaultColors:
|
|
162
|
+
"""Container that simplifies retrieving default RGB and RGBA colors."""
|
|
163
|
+
|
|
164
|
+
COLORS_RGB: Dict[str, Tuple[int, int, int]] = {
|
|
165
|
+
SupportedColor.CHARGER: (255, 128, 0),
|
|
166
|
+
SupportedColor.PATH: (50, 150, 255), # More vibrant blue for better visibility
|
|
167
|
+
SupportedColor.PREDICTED_PATH: (93, 109, 126),
|
|
168
|
+
SupportedColor.WALLS: (255, 255, 0),
|
|
169
|
+
SupportedColor.ROBOT: (255, 255, 204),
|
|
170
|
+
SupportedColor.GO_TO: (0, 255, 0),
|
|
171
|
+
SupportedColor.NO_GO: (255, 0, 0),
|
|
172
|
+
SupportedColor.ZONE_CLEAN: (255, 255, 255),
|
|
173
|
+
SupportedColor.MAP_BACKGROUND: (0, 125, 255),
|
|
174
|
+
SupportedColor.TEXT: (0, 0, 0),
|
|
175
|
+
SupportedColor.TRANSPARENT: (0, 0, 0),
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
DEFAULT_ROOM_COLORS: Dict[str, Tuple[int, int, int]] = {
|
|
179
|
+
SupportedColor.room_key(i): color
|
|
180
|
+
for i, color in enumerate(
|
|
181
|
+
[
|
|
182
|
+
(135, 206, 250),
|
|
183
|
+
(176, 226, 255),
|
|
184
|
+
(165, 105, 18),
|
|
185
|
+
(164, 211, 238),
|
|
186
|
+
(141, 182, 205),
|
|
187
|
+
(96, 123, 139),
|
|
188
|
+
(224, 255, 255),
|
|
189
|
+
(209, 238, 238),
|
|
190
|
+
(180, 205, 205),
|
|
191
|
+
(122, 139, 139),
|
|
192
|
+
(175, 238, 238),
|
|
193
|
+
(84, 153, 199),
|
|
194
|
+
(133, 193, 233),
|
|
195
|
+
(245, 176, 65),
|
|
196
|
+
(82, 190, 128),
|
|
197
|
+
(72, 201, 176),
|
|
198
|
+
]
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
DEFAULT_ALPHA: Dict[str, float] = {
|
|
203
|
+
f"alpha_{key}": 255.0 for key in COLORS_RGB.keys()
|
|
204
|
+
}
|
|
205
|
+
# Override specific alpha values
|
|
206
|
+
DEFAULT_ALPHA.update(
|
|
207
|
+
{
|
|
208
|
+
"alpha_color_path": 200.0, # Make path slightly transparent but still very visible
|
|
209
|
+
"alpha_color_wall": 150.0, # Keep walls semi-transparent
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
DEFAULT_ALPHA.update({f"alpha_room_{i}": 255.0 for i in range(16)})
|
|
213
|
+
|
|
214
|
+
@classmethod
|
|
215
|
+
def get_rgba(cls, key: str, alpha: float) -> Color:
|
|
216
|
+
rgb = cls.COLORS_RGB.get(key, (0, 0, 0))
|
|
217
|
+
r, g, b = rgb # Explicitly unpack the RGB values
|
|
218
|
+
return r, g, b, int(alpha)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class ColorsManagement:
|
|
222
|
+
"""Manages user-defined and default colors for map elements."""
|
|
223
|
+
|
|
224
|
+
def __init__(self, shared_var) -> None:
|
|
225
|
+
"""
|
|
226
|
+
Initialize ColorsManagement for Home Assistant.
|
|
227
|
+
Uses optimized initialization for better performance.
|
|
228
|
+
"""
|
|
229
|
+
self.shared_var = shared_var
|
|
230
|
+
self.color_cache = {} # Cache for frequently used color blends
|
|
231
|
+
|
|
232
|
+
# Initialize colors efficiently
|
|
233
|
+
self.user_colors = self.initialize_user_colors(self.shared_var.device_info)
|
|
234
|
+
self.rooms_colors = self.initialize_rooms_colors(self.shared_var.device_info)
|
|
235
|
+
|
|
236
|
+
@staticmethod
|
|
237
|
+
def add_alpha_to_rgb(alpha_channels, rgb_colors):
|
|
238
|
+
"""
|
|
239
|
+
Add alpha channel to RGB colors using corresponding alpha channels.
|
|
240
|
+
Uses NumPy for vectorized operations when possible for better performance.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
alpha_channels (List[Optional[float]]): List of alpha channel values (0.0-255.0).
|
|
244
|
+
rgb_colors (List[Tuple[int, int, int]]): List of RGB colors.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
List[Tuple[int, int, int, int]]: List of RGBA colors with alpha channel added.
|
|
248
|
+
"""
|
|
249
|
+
if len(alpha_channels) != len(rgb_colors):
|
|
250
|
+
LOGGER.warning("Input lists must have the same length.")
|
|
251
|
+
return []
|
|
252
|
+
|
|
253
|
+
# Fast path for empty lists
|
|
254
|
+
if not rgb_colors:
|
|
255
|
+
return []
|
|
256
|
+
|
|
257
|
+
# Try to use NumPy for vectorized operations
|
|
258
|
+
try:
|
|
259
|
+
# Convert inputs to NumPy arrays for vectorized processing
|
|
260
|
+
alphas = np.array(alpha_channels, dtype=np.float32)
|
|
261
|
+
|
|
262
|
+
# Clip alpha values to valid range [0, 255]
|
|
263
|
+
alphas = np.clip(alphas, 0, 255).astype(np.int32)
|
|
264
|
+
|
|
265
|
+
# Process RGB colors
|
|
266
|
+
result = []
|
|
267
|
+
for _, (alpha, rgb) in enumerate(zip(alphas, rgb_colors)):
|
|
268
|
+
if rgb is None:
|
|
269
|
+
result.append((0, 0, 0, int(alpha)))
|
|
270
|
+
else:
|
|
271
|
+
result.append((rgb[0], rgb[1], rgb[2], int(alpha)))
|
|
272
|
+
|
|
273
|
+
return result
|
|
274
|
+
|
|
275
|
+
except (ValueError, TypeError, AttributeError):
|
|
276
|
+
# Fallback to non-vectorized method if NumPy processing fails
|
|
277
|
+
result = []
|
|
278
|
+
for alpha, rgb in zip(alpha_channels, rgb_colors):
|
|
279
|
+
try:
|
|
280
|
+
alpha_int = int(alpha)
|
|
281
|
+
alpha_int = max(0, min(255, alpha_int)) # Clip to valid range
|
|
282
|
+
|
|
283
|
+
if rgb is None:
|
|
284
|
+
result.append((0, 0, 0, alpha_int))
|
|
285
|
+
else:
|
|
286
|
+
result.append((rgb[0], rgb[1], rgb[2], alpha_int))
|
|
287
|
+
except (ValueError, TypeError):
|
|
288
|
+
result.append(None)
|
|
289
|
+
|
|
290
|
+
return result
|
|
291
|
+
|
|
292
|
+
def set_initial_colours(self, device_info: dict) -> None:
|
|
293
|
+
"""Set the initial colours for the map using optimized methods."""
|
|
294
|
+
try:
|
|
295
|
+
# Define color keys and default values
|
|
296
|
+
base_color_keys = [
|
|
297
|
+
(COLOR_WALL, color_wall, ALPHA_WALL),
|
|
298
|
+
(COLOR_ZONE_CLEAN, color_zone_clean, ALPHA_ZONE_CLEAN),
|
|
299
|
+
(COLOR_ROBOT, color_robot, ALPHA_ROBOT),
|
|
300
|
+
(COLOR_BACKGROUND, color_background, ALPHA_BACKGROUND),
|
|
301
|
+
(COLOR_MOVE, color_move, ALPHA_MOVE),
|
|
302
|
+
(COLOR_CHARGER, color_charger, ALPHA_CHARGER),
|
|
303
|
+
(COLOR_NO_GO, color_no_go, ALPHA_NO_GO),
|
|
304
|
+
(COLOR_GO_TO, color_go_to, ALPHA_GO_TO),
|
|
305
|
+
(COLOR_TEXT, color_text, ALPHA_TEXT),
|
|
306
|
+
]
|
|
307
|
+
|
|
308
|
+
room_color_keys = [
|
|
309
|
+
(COLOR_ROOM_0, color_room_0, ALPHA_ROOM_0),
|
|
310
|
+
(COLOR_ROOM_1, color_room_1, ALPHA_ROOM_1),
|
|
311
|
+
(COLOR_ROOM_2, color_room_2, ALPHA_ROOM_2),
|
|
312
|
+
(COLOR_ROOM_3, color_room_3, ALPHA_ROOM_3),
|
|
313
|
+
(COLOR_ROOM_4, color_room_4, ALPHA_ROOM_4),
|
|
314
|
+
(COLOR_ROOM_5, color_room_5, ALPHA_ROOM_5),
|
|
315
|
+
(COLOR_ROOM_6, color_room_6, ALPHA_ROOM_6),
|
|
316
|
+
(COLOR_ROOM_7, color_room_7, ALPHA_ROOM_7),
|
|
317
|
+
(COLOR_ROOM_8, color_room_8, ALPHA_ROOM_8),
|
|
318
|
+
(COLOR_ROOM_9, color_room_9, ALPHA_ROOM_9),
|
|
319
|
+
(COLOR_ROOM_10, color_room_10, ALPHA_ROOM_10),
|
|
320
|
+
(COLOR_ROOM_11, color_room_11, ALPHA_ROOM_11),
|
|
321
|
+
(COLOR_ROOM_12, color_room_12, ALPHA_ROOM_12),
|
|
322
|
+
(COLOR_ROOM_13, color_room_13, ALPHA_ROOM_13),
|
|
323
|
+
(COLOR_ROOM_14, color_room_14, ALPHA_ROOM_14),
|
|
324
|
+
(COLOR_ROOM_15, color_room_15, ALPHA_ROOM_15),
|
|
325
|
+
]
|
|
326
|
+
|
|
327
|
+
# Extract user colors and alphas efficiently
|
|
328
|
+
user_colors = [
|
|
329
|
+
device_info.get(color_key, default_color)
|
|
330
|
+
for color_key, default_color, _ in base_color_keys
|
|
331
|
+
]
|
|
332
|
+
user_alpha = [
|
|
333
|
+
device_info.get(alpha_key, 255) for _, _, alpha_key in base_color_keys
|
|
334
|
+
]
|
|
335
|
+
|
|
336
|
+
# Extract room colors and alphas efficiently
|
|
337
|
+
rooms_colors = [
|
|
338
|
+
device_info.get(color_key, default_color)
|
|
339
|
+
for color_key, default_color, _ in room_color_keys
|
|
340
|
+
]
|
|
341
|
+
rooms_alpha = [
|
|
342
|
+
device_info.get(alpha_key, 255) for _, _, alpha_key in room_color_keys
|
|
343
|
+
]
|
|
344
|
+
|
|
345
|
+
# Use our optimized add_alpha_to_rgb method
|
|
346
|
+
self.shared_var.update_user_colors(
|
|
347
|
+
self.add_alpha_to_rgb(user_alpha, user_colors)
|
|
348
|
+
)
|
|
349
|
+
self.shared_var.update_rooms_colors(
|
|
350
|
+
self.add_alpha_to_rgb(rooms_alpha, rooms_colors)
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
# Clear the color cache after initialization
|
|
354
|
+
self.color_cache.clear()
|
|
355
|
+
|
|
356
|
+
except (ValueError, IndexError, UnboundLocalError) as e:
|
|
357
|
+
LOGGER.warning("Error while populating colors: %s", e)
|
|
358
|
+
|
|
359
|
+
def initialize_user_colors(self, device_info: dict) -> List[Color]:
|
|
360
|
+
"""
|
|
361
|
+
Initialize user-defined colors with defaults as fallback.
|
|
362
|
+
:param device_info: Dictionary containing user-defined colors.
|
|
363
|
+
:return: List of RGBA colors for map elements.
|
|
364
|
+
"""
|
|
365
|
+
colors = []
|
|
366
|
+
for key in SupportedColor:
|
|
367
|
+
if key.startswith(SupportedColor.COLOR_ROOM_PREFIX):
|
|
368
|
+
continue # Skip room colors for user_colors
|
|
369
|
+
rgb = device_info.get(key, DefaultColors.COLORS_RGB.get(key))
|
|
370
|
+
alpha = device_info.get(
|
|
371
|
+
f"alpha_{key}", DefaultColors.DEFAULT_ALPHA.get(f"alpha_{key}")
|
|
372
|
+
)
|
|
373
|
+
colors.append(self.add_alpha_to_color(rgb, alpha))
|
|
374
|
+
return colors
|
|
375
|
+
|
|
376
|
+
def initialize_rooms_colors(self, device_info: dict) -> List[Color]:
|
|
377
|
+
"""
|
|
378
|
+
Initialize room colors with defaults as fallback.
|
|
379
|
+
:param device_info: Dictionary containing user-defined room colors.
|
|
380
|
+
:return: List of RGBA colors for rooms.
|
|
381
|
+
"""
|
|
382
|
+
colors = []
|
|
383
|
+
for i in range(16):
|
|
384
|
+
rgb = device_info.get(
|
|
385
|
+
SupportedColor.room_key(i),
|
|
386
|
+
DefaultColors.DEFAULT_ROOM_COLORS.get(SupportedColor.room_key(i)),
|
|
387
|
+
)
|
|
388
|
+
alpha = device_info.get(
|
|
389
|
+
f"alpha_room_{i}", DefaultColors.DEFAULT_ALPHA.get(f"alpha_room_{i}")
|
|
390
|
+
)
|
|
391
|
+
colors.append(self.add_alpha_to_color(rgb, alpha))
|
|
392
|
+
return colors
|
|
393
|
+
|
|
394
|
+
@staticmethod
|
|
395
|
+
def add_alpha_to_color(rgb: Tuple[int, int, int], alpha: float) -> Color:
|
|
396
|
+
"""
|
|
397
|
+
Convert RGB to RGBA by appending the alpha value.
|
|
398
|
+
:param rgb: RGB values.
|
|
399
|
+
:param alpha: Alpha value (0.0 to 255.0).
|
|
400
|
+
:return: RGBA color.
|
|
401
|
+
"""
|
|
402
|
+
return (*rgb, int(alpha)) if rgb else (0, 0, 0, int(alpha))
|
|
403
|
+
|
|
404
|
+
def get_user_colors(self) -> List[Color]:
|
|
405
|
+
"""Return the list of RGBA colors for user-defined map elements."""
|
|
406
|
+
return self.user_colors
|
|
407
|
+
|
|
408
|
+
def get_rooms_colors(self) -> List[Color]:
|
|
409
|
+
"""Return the list of RGBA colors for rooms."""
|
|
410
|
+
return self.rooms_colors
|