@camera.ui/server 0.0.10 → 0.0.11-alpha.0
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.
- package/dist/interface/assets/@mdi-B8Roxr1z.js +1 -0
- package/dist/interface/assets/{@tanstack-B-9PO-kT.js → @tanstack-BvYNCsQh.js} +1 -1
- package/dist/interface/assets/{@vee-validate-D_G0ehOl.js → @vee-validate-BY5H7fGS.js} +1 -1
- package/dist/interface/assets/@vue-DMh6qW6s.js +17 -0
- package/dist/interface/assets/{@vueform-Bj73kRPS.js → @vueform-B62o9zLe.js} +1 -1
- package/dist/interface/assets/@vueuse-D76s02Ot.js +1 -0
- package/dist/interface/assets/Account-DlOUWknb.css +1 -0
- package/dist/interface/assets/Account-UkBkrzMK.js +1 -0
- package/dist/interface/assets/Adminpanel-Duo20795.js +2 -0
- package/dist/interface/assets/Appearance-rMWpzqff.js +1 -0
- package/dist/interface/assets/Backup-DhjSkqF7.js +1 -0
- package/dist/interface/assets/{Camera-BOu5dUel.js → Camera-CZ9JeXob.js} +1 -1
- package/dist/interface/assets/{Cameras-C7eUXdZk.js → Cameras-1zl5Xo1h.js} +1 -1
- package/dist/interface/assets/Cameras-Du4Q1fbV.css +1 -0
- package/dist/interface/assets/{Camview-CEgwGCGR.js → Camview-Bd7my9N3.js} +1 -1
- package/dist/interface/assets/{Config-Dt-etQ3h.js → Config-DB7gvh-P.js} +1 -1
- package/dist/interface/assets/{Console-FCve5CKy.js → Console-DCF1GwRU.js} +1 -1
- package/dist/interface/assets/FirstSteps-CGEDVu4n.css +1 -0
- package/dist/interface/assets/FirstSteps-DMQGcOZU.js +1 -0
- package/dist/interface/assets/{NewCamera-Cc1X79Ns.js → NewCamera-qLp7x0cL.js} +2 -2
- package/dist/interface/assets/{Plugin-CnQjafMC.js → Plugin-OP2-xz9S.js} +1 -1
- package/dist/interface/assets/{Plugins-CwyUdMlv.js → Plugins-qABzLjjT.js} +1 -1
- package/dist/interface/assets/Recordings-CLxIZLl0.js +1 -0
- package/dist/interface/assets/Recordings-Ctfkr-5E.js +1 -0
- package/dist/interface/assets/Settings-1CGQDosw.js +1 -0
- package/dist/interface/assets/System-DScEkzIf.js +1 -0
- package/dist/interface/assets/User-BQg52K_d.js +1 -0
- package/dist/interface/assets/User-DBVny1Dv.css +1 -0
- package/dist/interface/assets/VConfigEditor.vue_vue_type_script_setup_true_lang-BZltc68s.js +2 -0
- package/dist/interface/assets/{VConsole-BHy92Ws0.js → VConsole-BCO6q8J5.js} +1 -1
- package/dist/interface/assets/VPlayer-B_e1Qv8r.js +1 -0
- package/dist/interface/assets/{VPlayer-D3KhRfx-.css → VPlayer-DJjwfULk.css} +1 -1
- package/dist/interface/assets/VPluginCard-BL86NY9l.js +4 -0
- package/dist/interface/assets/VPluginCard-gBag9k-r.css +1 -0
- package/dist/interface/assets/main-2jkpYOC_.css +1 -0
- package/dist/interface/assets/main-Dv8zMGzJ.js +9 -0
- package/dist/interface/assets/{pinia-CitQ5b66.js → pinia-BQbsPkIS.js} +1 -1
- package/dist/interface/assets/{plugins-D80RNVmI.js → plugins-CS-GWC5l.js} +1 -1
- package/dist/interface/assets/{rxjs-B53o3e_J.js → rxjs-CQrF441D.js} +1 -1
- package/dist/interface/assets/{system-CS_ZOs3_.js → system-D7XWalnh.js} +1 -1
- package/dist/interface/assets/{ui-CHKoHLl-.js → ui-CyEgSsGE.js} +1 -1
- package/dist/interface/assets/{v-calendar-C-8W4FeM.js → v-calendar-CVkp7hgG.js} +1 -1
- package/dist/interface/assets/{vee-validate-Ck3I2guh.js → vee-validate-9vrYaQFq.js} +1 -1
- package/dist/interface/assets/{vue-i18n-DuCDz9TJ.js → vue-i18n-DqKZtX1N.js} +1 -1
- package/dist/interface/assets/{vue-inline-svg-C2gR6nRD.js → vue-inline-svg-D1BV6A5r.js} +1 -1
- package/dist/interface/assets/{vue-router-OPGDMnws.js → vue-router-Bje-Muh5.js} +1 -1
- package/dist/interface/assets/vue3-apexcharts-B8Nznyy3.js +703 -0
- package/dist/interface/assets/{vue3-dnd-Hf295yge.js → vue3-dnd-CvPSCHQb.js} +1 -1
- package/dist/interface/assets/{vue3-toastify-DQr2dOCx.js → vue3-toastify-D8Ru9hkX.js} +1 -1
- package/dist/interface/assets/{vuetify-B__3Y-at.css → vuetify-CoMF_JkX.css} +2 -2
- package/dist/interface/assets/vuetify-DYU2dOLI.js +5 -0
- package/dist/interface/index.html +17 -17
- package/dist/interface/sw.js +1 -1
- package/dist/server/bin/cui-service.js +4 -8
- package/dist/server/bin/cui-service.js.map +1 -1
- package/dist/server/package.json +3 -3
- package/dist/server/requirements.txt +1 -1
- package/dist/server/src/api/controllers/api.controller.d.ts +1 -0
- package/dist/server/src/api/controllers/api.controller.js +3 -0
- package/dist/server/src/api/controllers/api.controller.js.map +1 -1
- package/dist/server/src/api/controllers/cameras.controller.d.ts +2 -1
- package/dist/server/src/api/controllers/cameras.controller.js +27 -0
- package/dist/server/src/api/controllers/cameras.controller.js.map +1 -1
- package/dist/server/src/api/controllers/system.controller.d.ts +3 -0
- package/dist/server/src/api/controllers/system.controller.js +39 -0
- package/dist/server/src/api/controllers/system.controller.js.map +1 -1
- package/dist/server/src/api/controllers/users.controller.js +21 -2
- package/dist/server/src/api/controllers/users.controller.js.map +1 -1
- package/dist/server/src/api/database/types.d.ts +6 -6
- package/dist/server/src/api/index.js +8 -12
- package/dist/server/src/api/index.js.map +1 -1
- package/dist/server/src/api/routes/api.routes.js +1 -0
- package/dist/server/src/api/routes/api.routes.js.map +1 -1
- package/dist/server/src/api/routes/cameras.routes.js +19 -1
- package/dist/server/src/api/routes/cameras.routes.js.map +1 -1
- package/dist/server/src/api/routes/system.routes.js +6 -0
- package/dist/server/src/api/routes/system.routes.js.map +1 -1
- package/dist/server/src/api/schemas/cameras.schema.d.ts +61 -54
- package/dist/server/src/api/schemas/cameras.schema.js +7 -6
- package/dist/server/src/api/schemas/cameras.schema.js.map +1 -1
- package/dist/server/src/api/schemas/users.schema.d.ts +5 -0
- package/dist/server/src/api/schemas/users.schema.js +2 -1
- package/dist/server/src/api/schemas/users.schema.js.map +1 -1
- package/dist/server/src/api/types/index.d.ts +12 -2
- package/dist/server/src/api/types/index.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/metrics.d.ts +4 -22
- package/dist/server/src/api/websocket/nsp/metrics.js +74 -214
- package/dist/server/src/api/websocket/nsp/metrics.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/status.d.ts +4 -15
- package/dist/server/src/api/websocket/nsp/status.js +10 -16
- package/dist/server/src/api/websocket/nsp/status.js.map +1 -1
- package/dist/server/src/api/websocket/types.d.ts +25 -64
- package/dist/server/src/decoder/worker.d.ts +1 -2
- package/dist/server/src/decoder/worker.js +5 -11
- package/dist/server/src/decoder/worker.js.map +1 -1
- package/dist/server/src/go2rtc/index.js +4 -6
- package/dist/server/src/go2rtc/index.js.map +1 -1
- package/dist/server/src/index.d.ts +2 -2
- package/dist/server/src/index.js.map +1 -1
- package/dist/server/src/nats/index.d.ts +1 -1
- package/dist/server/src/nats/index.js +3 -3
- package/dist/server/src/nats/index.js.map +1 -1
- package/dist/server/src/nats/proxy/cameraDevice.d.ts +1 -1
- package/dist/server/src/nats/proxy/cameraDevice.js +1 -1
- package/dist/server/src/nats/proxy/cameraDevice.js.map +1 -1
- package/dist/server/src/nats/proxy/deviceManager.d.ts +1 -1
- package/dist/server/src/nats/proxy/deviceManager.js +1 -1
- package/dist/server/src/nats/proxy/deviceManager.js.map +1 -1
- package/dist/server/src/nats/server.js +4 -6
- package/dist/server/src/nats/server.js.map +1 -1
- package/dist/server/src/nats/websocket.js +2 -2
- package/dist/server/src/nats/websocket.js.map +1 -1
- package/dist/server/src/plugins/types.d.ts +10 -41
- package/dist/server/src/plugins/worker.js +4 -7
- package/dist/server/src/plugins/worker.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/cameraStorage.d.ts +9 -10
- package/dist/server/src/polyglot/node/plugins/cameraStorage.js +51 -55
- package/dist/server/src/polyglot/node/plugins/cameraStorage.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/child.js +18 -4
- package/dist/server/src/polyglot/node/plugins/child.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js +18 -4
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/schema.d.ts +22 -9
- package/dist/server/src/polyglot/node/plugins/schema.js +22 -2
- package/dist/server/src/polyglot/node/plugins/schema.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/storageController.d.ts +3 -3
- package/dist/server/src/polyglot/node/plugins/storageController.js.map +1 -1
- package/dist/server/src/polyglot/python/camera_ui_types/__init__.py +59 -93
- package/dist/server/src/polyglot/python/plugins/camera_storage.py +75 -80
- package/dist/server/src/polyglot/python/plugins/child.py +12 -4
- package/dist/server/src/polyglot/python/plugins/constants.py +0 -1
- package/dist/server/src/polyglot/python/plugins/proxy/camera_device.py +12 -4
- package/dist/server/src/polyglot/python/plugins/schema.py +19 -230
- package/dist/server/src/polyglot/python/plugins/storage_controller.py +2 -2
- package/dist/server/src/services/config/types.d.ts +1 -1
- package/package.json +3 -3
- package/dist/interface/assets/@mdi-C-QA1nE3.js +0 -1
- package/dist/interface/assets/@vue-C10tA4b9.js +0 -17
- package/dist/interface/assets/@vueuse-BPeqNGoM.js +0 -1
- package/dist/interface/assets/Account-B_tHnXoX.css +0 -1
- package/dist/interface/assets/Account-MEaGtu1D.js +0 -1
- package/dist/interface/assets/Adminpanel-D1ycltxf.js +0 -1
- package/dist/interface/assets/Appearance-Jlzp_P21.js +0 -1
- package/dist/interface/assets/Backup-1-ju9NDo.js +0 -1
- package/dist/interface/assets/Cameras-tmTzi1M6.css +0 -1
- package/dist/interface/assets/FirstSteps-DLkKDSe9.js +0 -1
- package/dist/interface/assets/FirstSteps-DNHhyDSw.css +0 -1
- package/dist/interface/assets/Recordings-Boeev1lV.js +0 -1
- package/dist/interface/assets/Recordings-D5ta7AYS.js +0 -1
- package/dist/interface/assets/Settings-Cvm2jnBr.js +0 -1
- package/dist/interface/assets/System-fHQ7XKri.js +0 -1
- package/dist/interface/assets/User-5o1VKizc.js +0 -1
- package/dist/interface/assets/User-BXColIbU.css +0 -1
- package/dist/interface/assets/VConfigEditor.vue_vue_type_script_setup_true_lang-C_95ELTZ.js +0 -2
- package/dist/interface/assets/VPlayer-LX5HGLrY.js +0 -1
- package/dist/interface/assets/VPluginCard-CFpg0LM4.js +0 -4
- package/dist/interface/assets/VPluginCard-Fl0AYmnF.css +0 -1
- package/dist/interface/assets/main-BCWSiwnj.js +0 -9
- package/dist/interface/assets/main-CQNVVncO.css +0 -1
- package/dist/interface/assets/vuetify-CrcT8VHB.js +0 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from abc import ABCMeta, abstractmethod
|
|
2
2
|
from collections.abc import AsyncGenerator, Awaitable, Coroutine
|
|
3
|
-
from typing import Any, Callable, Generic, Optional,
|
|
3
|
+
from typing import Any, Callable, Generic, Optional, Union, overload, runtime_checkable
|
|
4
4
|
|
|
5
5
|
from PIL import Image
|
|
6
6
|
from reactivex import Observable
|
|
@@ -9,6 +9,7 @@ from typing_extensions import (
|
|
|
9
9
|
NotRequired,
|
|
10
10
|
Protocol,
|
|
11
11
|
TypedDict,
|
|
12
|
+
TypeVar,
|
|
12
13
|
)
|
|
13
14
|
|
|
14
15
|
Callback = Union[
|
|
@@ -18,7 +19,7 @@ Callback = Union[
|
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
# schema
|
|
21
|
-
JsonSchemaType = Literal["string", "number", "boolean", "object", "array"]
|
|
22
|
+
JsonSchemaType = Literal["string", "number", "boolean", "object", "array", "button"]
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class JsonBaseSchema(TypedDict):
|
|
@@ -32,59 +33,12 @@ class JsonBaseSchema(TypedDict):
|
|
|
32
33
|
group: NotRequired[Optional[str]]
|
|
33
34
|
defaultValue: NotRequired[Optional[Union[str, int, bool]]]
|
|
34
35
|
store: NotRequired[Optional[bool]]
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class PluginJsonBaseSchema(JsonBaseSchema):
|
|
38
36
|
onSet: NotRequired[
|
|
39
37
|
Union[Callable[[Any, Any], Awaitable[Union[None, Any]]], Callable[[Any, Any], Union[None, Any]]]
|
|
40
|
-
]
|
|
41
|
-
onGet: NotRequired[
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class PluginJsonSchemaString(PluginJsonBaseSchema):
|
|
45
|
-
type: Literal["string"]
|
|
46
|
-
format: NotRequired[str]
|
|
47
|
-
minLength: NotRequired[int]
|
|
48
|
-
maxLength: NotRequired[int]
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class PluginJsonSchemaNumber(PluginJsonBaseSchema):
|
|
52
|
-
type: Literal["number"]
|
|
53
|
-
minimum: NotRequired[int]
|
|
54
|
-
maximum: NotRequired[int]
|
|
55
|
-
step: NotRequired[float]
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class PluginJsonSchemaBoolean(PluginJsonBaseSchema):
|
|
59
|
-
type: Literal["boolean"]
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class PluginJsonSchemaEnum(PluginJsonBaseSchema):
|
|
63
|
-
type: Literal["string"]
|
|
64
|
-
enum: list[str]
|
|
65
|
-
multiple: NotRequired[bool]
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class PluginJsonSchemaObject(PluginJsonBaseSchema):
|
|
69
|
-
type: Literal["object"]
|
|
70
|
-
opened: NotRequired[bool]
|
|
71
|
-
properties: NotRequired["PluginJsonSchemaForm"]
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
PluginJsonSchema = Union[
|
|
75
|
-
PluginJsonSchemaString,
|
|
76
|
-
PluginJsonSchemaNumber,
|
|
77
|
-
PluginJsonSchemaBoolean,
|
|
78
|
-
PluginJsonSchemaEnum,
|
|
79
|
-
PluginJsonSchemaObject,
|
|
80
|
-
]
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
PluginJsonSchemaForm = dict[str, PluginJsonSchema]
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class PluginRootSchema(TypedDict):
|
|
87
|
-
schema: PluginJsonSchemaForm
|
|
38
|
+
] # only for plugins
|
|
39
|
+
onGet: NotRequired[
|
|
40
|
+
Union[Callable[[], Awaitable[Union[Any, None]]], Callable[[], Union[Any, None]]]
|
|
41
|
+
] # only for plugins
|
|
88
42
|
|
|
89
43
|
|
|
90
44
|
class JsonSchemaString(JsonBaseSchema):
|
|
@@ -113,25 +67,29 @@ class JsonSchemaEnum(JsonBaseSchema):
|
|
|
113
67
|
multiple: NotRequired[bool]
|
|
114
68
|
|
|
115
69
|
|
|
70
|
+
class JsonSchemaButton(JsonBaseSchema):
|
|
71
|
+
type: Literal["button"]
|
|
72
|
+
|
|
73
|
+
|
|
116
74
|
class JsonSchemaObject(JsonBaseSchema):
|
|
117
75
|
type: Literal["object"]
|
|
118
76
|
opened: NotRequired[bool]
|
|
119
77
|
properties: NotRequired["JsonSchemaForm"]
|
|
120
78
|
|
|
121
79
|
|
|
122
|
-
class
|
|
80
|
+
class JsonSchemaArray(JsonBaseSchema):
|
|
81
|
+
type: Literal["array"]
|
|
82
|
+
opened: NotRequired[bool]
|
|
83
|
+
items: NotRequired["JsonSchema"]
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class JsonSchemaObjectButton(TypedDict):
|
|
123
87
|
label: str
|
|
124
88
|
onSubmit: str
|
|
125
89
|
|
|
126
90
|
|
|
127
91
|
class JsonSchemaObjectWithButtons(JsonSchemaObject):
|
|
128
|
-
buttons:
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
class JsonSchemaArray(JsonBaseSchema):
|
|
132
|
-
type: Literal["array"]
|
|
133
|
-
opened: NotRequired[bool]
|
|
134
|
-
items: NotRequired["JsonSchema"]
|
|
92
|
+
buttons: list[JsonSchemaObjectButton]
|
|
135
93
|
|
|
136
94
|
|
|
137
95
|
JsonSchema = Union[
|
|
@@ -142,6 +100,7 @@ JsonSchema = Union[
|
|
|
142
100
|
JsonSchemaObject,
|
|
143
101
|
JsonSchemaObjectWithButtons,
|
|
144
102
|
JsonSchemaArray,
|
|
103
|
+
JsonSchemaButton,
|
|
145
104
|
]
|
|
146
105
|
|
|
147
106
|
|
|
@@ -153,8 +112,8 @@ class RootSchema(TypedDict):
|
|
|
153
112
|
|
|
154
113
|
|
|
155
114
|
class SchemaConfig(TypedDict):
|
|
156
|
-
rootSchema:
|
|
157
|
-
config: dict[str,
|
|
115
|
+
rootSchema: RootSchema
|
|
116
|
+
config: dict[str, Any]
|
|
158
117
|
|
|
159
118
|
|
|
160
119
|
# camera object
|
|
@@ -240,12 +199,12 @@ class DetectionZone(TypedDict):
|
|
|
240
199
|
|
|
241
200
|
|
|
242
201
|
class CameraInformation(TypedDict):
|
|
243
|
-
model: str
|
|
244
|
-
manufacturer: str
|
|
245
|
-
hardware: str
|
|
246
|
-
serialNumber: str
|
|
247
|
-
firmwareVersion: str
|
|
248
|
-
supportUrl: str
|
|
202
|
+
model: NotRequired[str]
|
|
203
|
+
manufacturer: NotRequired[str]
|
|
204
|
+
hardware: NotRequired[str]
|
|
205
|
+
serialNumber: NotRequired[str]
|
|
206
|
+
firmwareVersion: NotRequired[str]
|
|
207
|
+
supportUrl: NotRequired[str]
|
|
249
208
|
|
|
250
209
|
|
|
251
210
|
class MotionDetectionSettings(TypedDict):
|
|
@@ -1037,47 +996,52 @@ class DeviceManager(Protocol):
|
|
|
1037
996
|
|
|
1038
997
|
# camera storage
|
|
1039
998
|
P = TypeVar("P")
|
|
999
|
+
CS = TypeVar("CS", default=dict[str, Any])
|
|
1040
1000
|
|
|
1041
1001
|
|
|
1042
1002
|
@runtime_checkable
|
|
1043
|
-
class CameraStorage(Protocol):
|
|
1044
|
-
values:
|
|
1003
|
+
class CameraStorage(Protocol, Generic[CS]):
|
|
1004
|
+
values: CS
|
|
1005
|
+
schema: JsonSchemaForm
|
|
1045
1006
|
|
|
1046
|
-
async def
|
|
1007
|
+
async def initializeStorage(self) -> None: ...
|
|
1047
1008
|
@overload
|
|
1048
|
-
def
|
|
1009
|
+
def getValue(self, path: str) -> Union[Awaitable[P], P, None]: ...
|
|
1049
1010
|
@overload
|
|
1050
|
-
def
|
|
1051
|
-
def
|
|
1052
|
-
async def
|
|
1053
|
-
def
|
|
1011
|
+
def getValue(self, path: str, default_value: P) -> Union[Awaitable[P], P]: ...
|
|
1012
|
+
def getValue(self, path: str, default_value: Optional[P] = None) -> Union[Awaitable[P], P, None]: ...
|
|
1013
|
+
async def setValue(self, path: str, new_value: Any) -> None: ...
|
|
1014
|
+
def hasValue(self, path: str) -> bool: ...
|
|
1054
1015
|
async def getConfig(self) -> SchemaConfig: ...
|
|
1055
|
-
async def setConfig(self, new_config:
|
|
1016
|
+
async def setConfig(self, new_config: CS) -> None: ...
|
|
1056
1017
|
@overload
|
|
1057
|
-
async def
|
|
1018
|
+
async def addSchema(self, schema_or_path: JsonSchemaForm) -> None: ...
|
|
1058
1019
|
@overload
|
|
1059
|
-
async def
|
|
1060
|
-
async def
|
|
1020
|
+
async def addSchema(self, schema_or_path: str, schema: JsonSchema) -> None: ...
|
|
1021
|
+
async def addSchema(
|
|
1061
1022
|
self,
|
|
1062
|
-
schema_or_path: Union[
|
|
1063
|
-
schema: Optional[
|
|
1023
|
+
schema_or_path: Union[JsonSchemaForm, str],
|
|
1024
|
+
schema: Optional[JsonSchema] = None,
|
|
1064
1025
|
) -> None: ...
|
|
1065
|
-
def
|
|
1066
|
-
async def
|
|
1067
|
-
def
|
|
1068
|
-
def
|
|
1026
|
+
def removeSchema(self, path: str) -> None: ...
|
|
1027
|
+
async def changeSchema(self, path: str, new_schema: dict[str, Any]) -> None: ...
|
|
1028
|
+
def getSchema(self, path: str) -> Optional[JsonSchema]: ...
|
|
1029
|
+
def hasSchema(self, path: str) -> bool: ...
|
|
1030
|
+
|
|
1031
|
+
|
|
1032
|
+
SC = TypeVar("SC", default=CameraStorage[dict[str, Any]], covariant=True)
|
|
1069
1033
|
|
|
1070
1034
|
|
|
1071
1035
|
# StorageController
|
|
1072
1036
|
@runtime_checkable
|
|
1073
|
-
class StorageController(Protocol):
|
|
1037
|
+
class StorageController(Protocol[SC]):
|
|
1074
1038
|
def create_camera_storage(
|
|
1075
1039
|
self,
|
|
1076
1040
|
instance: Any,
|
|
1077
1041
|
camera_id: str,
|
|
1078
|
-
schema: Optional[
|
|
1079
|
-
) ->
|
|
1080
|
-
def get_camera_storage(self, camera_id: str) -> Optional[
|
|
1042
|
+
schema: Optional[JsonSchemaForm] = None,
|
|
1043
|
+
) -> SC: ...
|
|
1044
|
+
def get_camera_storage(self, camera_id: str) -> Optional[SC]: ...
|
|
1081
1045
|
def remove_camera_storage(self, camera_id: str) -> None: ...
|
|
1082
1046
|
|
|
1083
1047
|
|
|
@@ -1123,13 +1087,15 @@ class PluginConfigService(Protocol):
|
|
|
1123
1087
|
# Plugin API
|
|
1124
1088
|
APIEventType = Literal["finishLaunching", "shutdown"]
|
|
1125
1089
|
|
|
1090
|
+
PA = TypeVar("PA", bound=CameraStorage[Any], default=CameraStorage[Any])
|
|
1091
|
+
|
|
1126
1092
|
|
|
1127
1093
|
@runtime_checkable
|
|
1128
|
-
class PluginAPI(Protocol):
|
|
1094
|
+
class PluginAPI(Protocol[PA]):
|
|
1129
1095
|
storage_path: str
|
|
1130
1096
|
config_file: str
|
|
1131
1097
|
config_service: PluginConfigService
|
|
1132
|
-
storage_controller: StorageController
|
|
1098
|
+
storage_controller: StorageController[PA]
|
|
1133
1099
|
device_manager: DeviceManager
|
|
1134
1100
|
|
|
1135
1101
|
def on(self, event: APIEventType, listener: Callback) -> "PluginAPI": ...
|
|
@@ -6,10 +6,10 @@ from pathlib import Path
|
|
|
6
6
|
from typing import Any, Optional, TypeVar, Union, cast
|
|
7
7
|
|
|
8
8
|
from camera_ui_types import (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
JsonBaseSchema,
|
|
10
|
+
JsonSchema,
|
|
11
|
+
JsonSchemaForm,
|
|
12
|
+
RootSchema,
|
|
13
13
|
SchemaConfig,
|
|
14
14
|
)
|
|
15
15
|
from deepdiff import DeepDiff
|
|
@@ -62,15 +62,15 @@ class CameraStorage:
|
|
|
62
62
|
api: PluginAPI,
|
|
63
63
|
instance: Any,
|
|
64
64
|
camera_id: str,
|
|
65
|
-
schema: Optional[
|
|
65
|
+
schema: Optional[JsonSchemaForm] = None,
|
|
66
66
|
) -> None:
|
|
67
67
|
if schema is None:
|
|
68
68
|
schema = {}
|
|
69
69
|
self.__api = api
|
|
70
70
|
self.__instance = instance
|
|
71
71
|
self.__camera_id = camera_id
|
|
72
|
-
self.
|
|
73
|
-
self.
|
|
72
|
+
self.schema: JsonSchemaForm = schema or {}
|
|
73
|
+
self.values: dict[str, Any] = {}
|
|
74
74
|
|
|
75
75
|
db_path = Path(api.storage_path) / "volume"
|
|
76
76
|
self.__db: Lmdb[Literal["config"], dict[str, Any]] = JsonLmdb.open(file=str(db_path), flag="c")
|
|
@@ -78,11 +78,7 @@ class CameraStorage:
|
|
|
78
78
|
self.__api.device_manager.once("cameraDeselected", self.__deselected)
|
|
79
79
|
self.__api.once("shutdown", self.__close)
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
def values(self) -> dict[str, Any]:
|
|
83
|
-
return self.__values
|
|
84
|
-
|
|
85
|
-
def initialize_storage(self) -> None:
|
|
81
|
+
def initializeStorage(self) -> None:
|
|
86
82
|
"""
|
|
87
83
|
Initialize the storage.
|
|
88
84
|
This will load the configuration from the database.
|
|
@@ -96,17 +92,17 @@ class CameraStorage:
|
|
|
96
92
|
except: # noqa: E722
|
|
97
93
|
pass
|
|
98
94
|
|
|
99
|
-
schema_config = generate_json_from_root_schema({"schema": self.
|
|
95
|
+
schema_config = generate_json_from_root_schema({"schema": self.schema})
|
|
100
96
|
|
|
101
|
-
self.
|
|
97
|
+
self.values = merge_with(schema_config, camera_config, merge, [])
|
|
102
98
|
|
|
103
99
|
self.__save_db()
|
|
104
100
|
|
|
105
101
|
@overload
|
|
106
|
-
async def
|
|
102
|
+
async def getValue(self, path: str) -> Union[Any, None]: ...
|
|
107
103
|
@overload
|
|
108
|
-
async def
|
|
109
|
-
async def
|
|
104
|
+
async def getValue(self, path: str, default_value: P) -> P: ...
|
|
105
|
+
async def getValue(self, path: str, default_value: Optional[P] = None) -> Union[P, None]:
|
|
110
106
|
"""
|
|
111
107
|
Get a value from the configuration by its key/path.
|
|
112
108
|
If the schema has an onGet function, the onGet function will be called.
|
|
@@ -119,8 +115,8 @@ class CameraStorage:
|
|
|
119
115
|
"""
|
|
120
116
|
|
|
121
117
|
schema_path = config_path_to_schema_path(path)
|
|
122
|
-
schema:
|
|
123
|
-
config_value = ObjectPath.get(self.
|
|
118
|
+
schema: JsonBaseSchema = ObjectPath.get(self.schema, schema_path)
|
|
119
|
+
config_value = ObjectPath.get(self.values, path)
|
|
124
120
|
|
|
125
121
|
if schema:
|
|
126
122
|
on_get_function = schema.get("onGet", None)
|
|
@@ -136,7 +132,7 @@ class CameraStorage:
|
|
|
136
132
|
else:
|
|
137
133
|
return default_value
|
|
138
134
|
|
|
139
|
-
async def
|
|
135
|
+
async def setValue(self, path: str, new_value: Any) -> None:
|
|
140
136
|
"""
|
|
141
137
|
Set a new value for a given key/path in the configuration.
|
|
142
138
|
If the schema of the value has an onSet function, and the value has changed, the onSet function will be called.
|
|
@@ -147,18 +143,18 @@ class CameraStorage:
|
|
|
147
143
|
"""
|
|
148
144
|
|
|
149
145
|
schema_path = config_path_to_schema_path(path)
|
|
150
|
-
schema:
|
|
146
|
+
schema: JsonSchema = ObjectPath.get(self.schema, schema_path)
|
|
151
147
|
|
|
152
148
|
if schema:
|
|
153
|
-
old_config = deepcopy(self.
|
|
154
|
-
ObjectPath.set(self.
|
|
149
|
+
old_config = deepcopy(self.values)
|
|
150
|
+
ObjectPath.set(self.values, path, new_value)
|
|
155
151
|
|
|
156
|
-
await self.__trigger_on_set_for_changes(old_config, self.
|
|
152
|
+
await self.__trigger_on_set_for_changes(old_config, self.values)
|
|
157
153
|
|
|
158
154
|
if self.__contains_storable_schema(schema):
|
|
159
155
|
self.__save_db()
|
|
160
156
|
|
|
161
|
-
def
|
|
157
|
+
def hasValue(self, path: str) -> bool:
|
|
162
158
|
"""
|
|
163
159
|
Check if a value exists by its config path/key.
|
|
164
160
|
|
|
@@ -166,7 +162,7 @@ class CameraStorage:
|
|
|
166
162
|
:return: True if the value exists, false otherwise.
|
|
167
163
|
"""
|
|
168
164
|
|
|
169
|
-
config_value = ObjectPath.get(self.
|
|
165
|
+
config_value = ObjectPath.get(self.values, path)
|
|
170
166
|
return config_value is not None
|
|
171
167
|
|
|
172
168
|
async def getConfig(self) -> SchemaConfig:
|
|
@@ -177,12 +173,12 @@ class CameraStorage:
|
|
|
177
173
|
:return: The root schema and configuration.
|
|
178
174
|
"""
|
|
179
175
|
|
|
180
|
-
filtered_schema = remove_functions_from_schema_form(self.
|
|
181
|
-
root_schema:
|
|
176
|
+
filtered_schema = remove_functions_from_schema_form(self.schema)
|
|
177
|
+
root_schema: RootSchema = {"schema": filtered_schema}
|
|
182
178
|
|
|
183
|
-
await self.__resolve_on_get_functions(self.
|
|
179
|
+
await self.__resolve_on_get_functions(self.schema)
|
|
184
180
|
|
|
185
|
-
return {"rootSchema": root_schema, "config": self.
|
|
181
|
+
return {"rootSchema": root_schema, "config": self.values}
|
|
186
182
|
|
|
187
183
|
async def setConfig(self, new_config: dict[str, Any]) -> None:
|
|
188
184
|
"""
|
|
@@ -192,20 +188,20 @@ class CameraStorage:
|
|
|
192
188
|
:param new_config: The new configuration to set.
|
|
193
189
|
"""
|
|
194
190
|
|
|
195
|
-
old_config = deepcopy(self.
|
|
196
|
-
self.
|
|
191
|
+
old_config = deepcopy(self.values)
|
|
192
|
+
self.values = new_config
|
|
197
193
|
|
|
198
|
-
await self.__trigger_on_set_for_changes(old_config, self.
|
|
194
|
+
await self.__trigger_on_set_for_changes(old_config, self.values)
|
|
199
195
|
self.__save_db()
|
|
200
196
|
|
|
201
197
|
@overload
|
|
202
|
-
async def
|
|
198
|
+
async def addSchema(self, schema_or_path: JsonSchemaForm) -> None: ...
|
|
203
199
|
@overload
|
|
204
|
-
async def
|
|
205
|
-
async def
|
|
200
|
+
async def addSchema(self, schema_or_path: str, schema: JsonSchema) -> None: ...
|
|
201
|
+
async def addSchema(
|
|
206
202
|
self,
|
|
207
|
-
schema_or_path: Union[
|
|
208
|
-
schema: Optional[
|
|
203
|
+
schema_or_path: Union[JsonSchemaForm, str],
|
|
204
|
+
schema: Optional[JsonSchema] = None,
|
|
209
205
|
) -> None:
|
|
210
206
|
"""
|
|
211
207
|
Add a new schema to the existing schema.
|
|
@@ -222,7 +218,7 @@ class CameraStorage:
|
|
|
222
218
|
path = schema_or_path
|
|
223
219
|
schema_path = config_path_to_schema_path(path)
|
|
224
220
|
|
|
225
|
-
ObjectPath.set(self.
|
|
221
|
+
ObjectPath.set(self.schema, schema_path, schema)
|
|
226
222
|
|
|
227
223
|
await self.__resolve_on_get_functions(schema, schema_path)
|
|
228
224
|
|
|
@@ -232,7 +228,7 @@ class CameraStorage:
|
|
|
232
228
|
elif isinstance(schema_or_path, dict) and schema is None:
|
|
233
229
|
new_schema = schema_or_path
|
|
234
230
|
|
|
235
|
-
self.
|
|
231
|
+
self.schema = merge_with(self.schema, new_schema, merge, [])
|
|
236
232
|
|
|
237
233
|
await self.__resolve_on_get_functions(new_schema)
|
|
238
234
|
|
|
@@ -240,12 +236,12 @@ class CameraStorage:
|
|
|
240
236
|
should_save = True
|
|
241
237
|
|
|
242
238
|
else:
|
|
243
|
-
raise Exception("Invalid arguments for
|
|
239
|
+
raise Exception("Invalid arguments for addSchema")
|
|
244
240
|
|
|
245
241
|
if should_save:
|
|
246
242
|
self.__save_db()
|
|
247
243
|
|
|
248
|
-
def
|
|
244
|
+
def removeSchema(self, path: str) -> None:
|
|
249
245
|
"""
|
|
250
246
|
Remove a schema by its config path/key from the existing schema.
|
|
251
247
|
It will also remove the value from the configuration.
|
|
@@ -255,16 +251,16 @@ class CameraStorage:
|
|
|
255
251
|
"""
|
|
256
252
|
|
|
257
253
|
schema_path = config_path_to_schema_path(path)
|
|
258
|
-
schema: Optional[
|
|
254
|
+
schema: Optional[JsonSchema] = ObjectPath.get(self.schema, schema_path) or None
|
|
259
255
|
|
|
260
256
|
if schema:
|
|
261
|
-
ObjectPath.delete(self.
|
|
262
|
-
ObjectPath.delete(self.
|
|
257
|
+
ObjectPath.delete(self.schema, schema_path)
|
|
258
|
+
ObjectPath.delete(self.values, path)
|
|
263
259
|
|
|
264
260
|
if self.__contains_storable_schema(schema):
|
|
265
261
|
self.__remove_db()
|
|
266
262
|
|
|
267
|
-
async def
|
|
263
|
+
async def changeSchema(self, path: str, new_schema: dict[str, Any]) -> None:
|
|
268
264
|
"""
|
|
269
265
|
Change a schema by its config path/key from the existing schema.
|
|
270
266
|
It will also change the value from the configuration.
|
|
@@ -275,18 +271,18 @@ class CameraStorage:
|
|
|
275
271
|
"""
|
|
276
272
|
|
|
277
273
|
schema_path = config_path_to_schema_path(path)
|
|
278
|
-
schema: Optional[
|
|
274
|
+
schema: Optional[JsonSchema] = ObjectPath.get(self.schema, schema_path) or None
|
|
279
275
|
|
|
280
276
|
if schema:
|
|
281
277
|
merge_with(schema, new_schema, merge, [])
|
|
282
|
-
ObjectPath.set(self.
|
|
278
|
+
ObjectPath.set(self.schema, schema_path, schema)
|
|
283
279
|
|
|
284
280
|
await self.__resolve_on_get_functions(schema, schema_path)
|
|
285
281
|
|
|
286
282
|
if self.__contains_storable_schema(schema):
|
|
287
283
|
self.__save_db()
|
|
288
284
|
|
|
289
|
-
def
|
|
285
|
+
def getSchema(self, path: str) -> Optional[JsonSchema]:
|
|
290
286
|
"""
|
|
291
287
|
Get a schema by its config path/key.
|
|
292
288
|
|
|
@@ -295,11 +291,11 @@ class CameraStorage:
|
|
|
295
291
|
"""
|
|
296
292
|
|
|
297
293
|
schema_path = config_path_to_schema_path(path)
|
|
298
|
-
schema: Optional[
|
|
294
|
+
schema: Optional[JsonSchema] = ObjectPath.get(self.schema, schema_path) or None
|
|
299
295
|
|
|
300
296
|
return schema
|
|
301
297
|
|
|
302
|
-
def
|
|
298
|
+
def hasSchema(self, path: str) -> bool:
|
|
303
299
|
"""
|
|
304
300
|
Check if a schema exists by its config path/key.
|
|
305
301
|
|
|
@@ -308,13 +304,13 @@ class CameraStorage:
|
|
|
308
304
|
"""
|
|
309
305
|
|
|
310
306
|
schema_path = config_path_to_schema_path(path)
|
|
311
|
-
schema: Optional[
|
|
307
|
+
schema: Optional[JsonSchema] = ObjectPath.get(self.schema, schema_path) or None
|
|
312
308
|
|
|
313
309
|
return schema is not None
|
|
314
310
|
|
|
315
311
|
async def __resolve_on_get_functions(
|
|
316
312
|
self,
|
|
317
|
-
schema: Union[
|
|
313
|
+
schema: Union[JsonSchemaForm, JsonSchema],
|
|
318
314
|
base_schema_path: str = "",
|
|
319
315
|
) -> None:
|
|
320
316
|
if "onGet" in schema or "onSet" in schema:
|
|
@@ -326,7 +322,7 @@ class CameraStorage:
|
|
|
326
322
|
base_schema_path,
|
|
327
323
|
)
|
|
328
324
|
else:
|
|
329
|
-
_schema = cast(
|
|
325
|
+
_schema = cast(JsonSchemaForm, schema)
|
|
330
326
|
|
|
331
327
|
for key, value in _schema.items():
|
|
332
328
|
schema_path = f"{base_schema_path}.{key}" if base_schema_path else key
|
|
@@ -340,7 +336,7 @@ class CameraStorage:
|
|
|
340
336
|
|
|
341
337
|
async def ___resolve_on_get_functions_for_object(
|
|
342
338
|
self,
|
|
343
|
-
schema:
|
|
339
|
+
schema: JsonSchemaForm,
|
|
344
340
|
base_schema_path: str,
|
|
345
341
|
) -> None:
|
|
346
342
|
for key, _ in schema.items():
|
|
@@ -349,10 +345,10 @@ class CameraStorage:
|
|
|
349
345
|
|
|
350
346
|
async def __resolve_on_get_functions_for_schema(self, schema_path: str) -> None:
|
|
351
347
|
config_path = schema_path_to_config_path(schema_path)
|
|
352
|
-
schema_value = await self.
|
|
348
|
+
schema_value = await self.getValue(config_path)
|
|
353
349
|
|
|
354
350
|
if schema_value is not None:
|
|
355
|
-
ObjectPath.set(self.
|
|
351
|
+
ObjectPath.set(self.values, config_path, schema_value)
|
|
356
352
|
|
|
357
353
|
async def __trigger_on_set_for_changes(
|
|
358
354
|
self, old_config: dict[str, Any], new_config: dict[str, Any], path: str = ""
|
|
@@ -364,7 +360,7 @@ class CameraStorage:
|
|
|
364
360
|
|
|
365
361
|
if DeepDiff(old_value, new_value, ignore_order=True) != {}:
|
|
366
362
|
schema_path = config_path_to_schema_path(new_path)
|
|
367
|
-
schema_item: Optional[
|
|
363
|
+
schema_item: Optional[JsonBaseSchema] = get_value_by_path(self.schema, schema_path)
|
|
368
364
|
|
|
369
365
|
if schema_item:
|
|
370
366
|
on_set_function = schema_item.get("onSet", None)
|
|
@@ -380,12 +376,15 @@ class CameraStorage:
|
|
|
380
376
|
|
|
381
377
|
def __filter_storable_values(
|
|
382
378
|
self,
|
|
383
|
-
schema:
|
|
379
|
+
schema: JsonSchemaForm,
|
|
384
380
|
base_schema_path: str = "",
|
|
385
381
|
result: dict[str, Any] = {},
|
|
386
382
|
) -> dict[str, Any]:
|
|
387
383
|
for key, value in schema.items():
|
|
388
|
-
if
|
|
384
|
+
if value["type"] == "button":
|
|
385
|
+
continue
|
|
386
|
+
|
|
387
|
+
if value["type"] == "object":
|
|
389
388
|
if "properties" in value:
|
|
390
389
|
s: Any = value["properties"]
|
|
391
390
|
path = f"{base_schema_path}.{key}" if base_schema_path else key
|
|
@@ -393,7 +392,7 @@ class CameraStorage:
|
|
|
393
392
|
elif "store" in value and value["store"]:
|
|
394
393
|
schema_path = f"{base_schema_path}.{key}" if base_schema_path else key
|
|
395
394
|
config_path = schema_path_to_config_path(schema_path)
|
|
396
|
-
config_value = get_value_by_path(self.
|
|
395
|
+
config_value = get_value_by_path(self.values, config_path)
|
|
397
396
|
|
|
398
397
|
ObjectPath.set(result, config_path, config_value)
|
|
399
398
|
|
|
@@ -401,30 +400,25 @@ class CameraStorage:
|
|
|
401
400
|
|
|
402
401
|
def __contains_storable_schema(
|
|
403
402
|
self,
|
|
404
|
-
schema: Union[
|
|
403
|
+
schema: Union[JsonSchemaForm, JsonSchema],
|
|
405
404
|
) -> bool:
|
|
406
|
-
if
|
|
407
|
-
if "type" in schema and schema["type"] == "object":
|
|
408
|
-
if "store" in schema and schema["store"]:
|
|
409
|
-
return True
|
|
410
|
-
if "properties" in schema and schema["properties"]:
|
|
411
|
-
for sub_schema in schema["properties"].values():
|
|
412
|
-
sub: Any = sub_schema
|
|
413
|
-
if self.__contains_storable_schema(sub):
|
|
414
|
-
return True
|
|
415
|
-
|
|
416
|
-
return False
|
|
417
|
-
|
|
405
|
+
if schema["type"] == "boolean":
|
|
418
406
|
return False
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
407
|
+
|
|
408
|
+
if "store" in schema and schema["store"]:
|
|
409
|
+
return True
|
|
410
|
+
|
|
411
|
+
if schema["type"] == "object" and "properties" in schema:
|
|
412
|
+
schema_values: Any = schema["properties"].values()
|
|
413
|
+
return any(self.__contains_storable_schema(sub_schema) for sub_schema in schema_values)
|
|
414
|
+
elif schema["type"] == "array" and "items" in schema:
|
|
415
|
+
return self.__contains_storable_schema(schema["items"])
|
|
416
|
+
|
|
417
|
+
return False
|
|
424
418
|
|
|
425
419
|
def __save_db(self) -> None:
|
|
426
420
|
config: Any = self.__db.get("config") or {}
|
|
427
|
-
storable_config = self.__filter_storable_values(self.
|
|
421
|
+
storable_config = self.__filter_storable_values(self.schema)
|
|
428
422
|
|
|
429
423
|
config[self.__camera_id] = storable_config
|
|
430
424
|
|
|
@@ -443,4 +437,5 @@ class CameraStorage:
|
|
|
443
437
|
|
|
444
438
|
def __close(self) -> None:
|
|
445
439
|
with suppress(Exception):
|
|
440
|
+
self.__save_db()
|
|
446
441
|
self.__db.close()
|
|
@@ -143,6 +143,9 @@ class PluginChild:
|
|
|
143
143
|
if not self.message_queue:
|
|
144
144
|
raise Exception("Message queue not initialized")
|
|
145
145
|
|
|
146
|
+
reply = message.copy()
|
|
147
|
+
reply["type"] = "reply"
|
|
148
|
+
|
|
146
149
|
try:
|
|
147
150
|
plugin = None
|
|
148
151
|
|
|
@@ -165,7 +168,7 @@ class PluginChild:
|
|
|
165
168
|
else:
|
|
166
169
|
response = method_to_call(*args)
|
|
167
170
|
|
|
168
|
-
|
|
171
|
+
reply["response"] = response or {}
|
|
169
172
|
elif camera_storage and hasattr(camera_storage, fn) and callable(getattr(camera_storage, fn)):
|
|
170
173
|
method_to_call = getattr(camera_storage, fn)
|
|
171
174
|
|
|
@@ -174,9 +177,9 @@ class PluginChild:
|
|
|
174
177
|
else:
|
|
175
178
|
response = method_to_call(*args)
|
|
176
179
|
|
|
177
|
-
|
|
180
|
+
reply["response"] = response or {}
|
|
178
181
|
else:
|
|
179
|
-
|
|
182
|
+
raise Exception(f"Unknown function: {fn}")
|
|
180
183
|
except Exception as e:
|
|
181
184
|
deserialized_error: DeserializedError = {
|
|
182
185
|
"name": type(e).__name__,
|
|
@@ -184,7 +187,12 @@ class PluginChild:
|
|
|
184
187
|
"stack": traceback.format_exc(),
|
|
185
188
|
}
|
|
186
189
|
|
|
187
|
-
|
|
190
|
+
reply["error"] = deserialized_error
|
|
191
|
+
|
|
192
|
+
if message["timeout"] == 0:
|
|
193
|
+
return
|
|
194
|
+
else:
|
|
195
|
+
await self.message_queue.enqueue(reply)
|
|
188
196
|
|
|
189
197
|
async def on_worker_message(self, msg: Msg) -> None:
|
|
190
198
|
if self.stopped:
|