@camera.ui/server 0.0.6 → 0.0.8
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/{@tanstack-BqH4GyO-.js → @tanstack-B-9PO-kT.js} +1 -1
- package/dist/interface/assets/{@vee-validate-DCBdnGo-.js → @vee-validate-D_G0ehOl.js} +1 -1
- package/dist/interface/assets/{@vue-C7-KaDG4.js → @vue-C10tA4b9.js} +6 -6
- package/dist/interface/assets/{@vueform-arggO0eF.js → @vueform-Bj73kRPS.js} +1 -1
- package/dist/interface/assets/{@vueuse-C3WMTDqL.js → @vueuse-BPeqNGoM.js} +1 -1
- package/dist/interface/assets/Account-MEaGtu1D.js +1 -0
- package/dist/interface/assets/Adminpanel-D1ycltxf.js +1 -0
- package/dist/interface/assets/Appearance-Jlzp_P21.js +1 -0
- package/dist/interface/assets/Backup-1-ju9NDo.js +1 -0
- package/dist/interface/assets/Camera-BOu5dUel.js +1 -0
- package/dist/interface/assets/Cameras-C7eUXdZk.js +1 -0
- package/dist/interface/assets/Cameras-tmTzi1M6.css +1 -0
- package/dist/interface/assets/Camview-CEgwGCGR.js +1 -0
- package/dist/interface/assets/{Camview-vUAs5YHU.css → Camview-CWTrsoY0.css} +1 -1
- package/dist/interface/assets/Config-Dt-etQ3h.js +1 -0
- package/dist/interface/assets/{Console-Caz7y-T0.js → Console-FCve5CKy.js} +2 -2
- package/dist/interface/assets/FirstSteps-DLkKDSe9.js +1 -0
- package/dist/interface/assets/{NewCamera-B9t-0NCc.js → NewCamera-Cc1X79Ns.js} +2 -2
- package/dist/interface/assets/Plugin-CnQjafMC.js +1 -0
- package/dist/interface/assets/{Plugin-BSHKKjrl.css → Plugin-DzKKCoqQ.css} +1 -1
- package/dist/interface/assets/Plugins-B8gCgxOx.css +1 -0
- package/dist/interface/assets/Plugins-CwyUdMlv.js +1 -0
- package/dist/interface/assets/Recordings-Boeev1lV.js +1 -0
- package/dist/interface/assets/Recordings-D5ta7AYS.js +1 -0
- package/dist/interface/assets/Settings-Cvm2jnBr.js +1 -0
- package/dist/interface/assets/System-fHQ7XKri.js +1 -0
- package/dist/interface/assets/User-5o1VKizc.js +1 -0
- package/dist/interface/assets/VConfigEditor.vue_vue_type_script_setup_true_lang-C_95ELTZ.js +2 -0
- package/dist/interface/assets/VConsole-BHy92Ws0.js +1 -0
- package/dist/interface/assets/VConsole-MV9pQtJj.css +1 -0
- package/dist/interface/assets/{VPlayer-YdRn97Bs.js → VPlayer-LX5HGLrY.js} +1 -1
- package/dist/interface/assets/{VPluginCard--3bx6UJb.js → VPluginCard-CFpg0LM4.js} +2 -2
- package/dist/interface/assets/VPluginCard-Fl0AYmnF.css +1 -0
- package/dist/interface/assets/main-BCWSiwnj.js +9 -0
- package/dist/interface/assets/{main-B3IVLctZ.css → main-CQNVVncO.css} +1 -1
- package/dist/interface/assets/{pinia-D8MtiGcH.js → pinia-CitQ5b66.js} +2 -2
- package/dist/interface/assets/{plugins-Bf03y242.js → plugins-D80RNVmI.js} +1 -1
- package/dist/interface/assets/qrcode-SHonoxyK.js +8 -0
- package/dist/interface/assets/{system-BONnDA4y.js → system-CS_ZOs3_.js} +1 -1
- package/dist/interface/assets/{ui-CNpIJotI.js → ui-CHKoHLl-.js} +1 -1
- package/dist/interface/assets/{v-calendar-uh0aTGqP.js → v-calendar-C-8W4FeM.js} +1 -1
- package/dist/interface/assets/{vee-validate-D3FqbChK.js → vee-validate-Ck3I2guh.js} +1 -1
- package/dist/interface/assets/{vue-i18n-1AU8MPys.js → vue-i18n-DuCDz9TJ.js} +1 -1
- package/dist/interface/assets/{vue-inline-svg-2DDwYW6V.js → vue-inline-svg-C2gR6nRD.js} +1 -1
- package/dist/interface/assets/{vue-router-DfeQ8s4I.js → vue-router-OPGDMnws.js} +1 -1
- package/dist/interface/assets/{vue3-dnd-BwxcSU9Z.js → vue3-dnd-Hf295yge.js} +1 -1
- package/dist/interface/assets/{vue3-toastify-Ul-rf53I.js → vue3-toastify-DQr2dOCx.js} +1 -1
- package/dist/interface/assets/vuetify-CrcT8VHB.js +5 -0
- package/dist/interface/index.html +14 -15
- package/dist/interface/sw.js +1 -1
- package/dist/server/bin/cui-service.d.ts +1 -0
- package/dist/server/bin/cui-service.js +41 -9
- package/dist/server/bin/cui-service.js.map +1 -1
- package/dist/server/package.json +8 -7
- package/dist/server/requirements.txt +2 -3
- package/dist/server/src/api/controllers/cameras.controller.js +2 -2
- package/dist/server/src/api/controllers/cameras.controller.js.map +1 -1
- package/dist/server/src/api/controllers/plugins.controller.js +7 -6
- package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
- package/dist/server/src/api/go2rtc/api/streams.d.ts +4 -4
- package/dist/server/src/api/go2rtc/api/streams.js +2 -24
- package/dist/server/src/api/go2rtc/api/streams.js.map +1 -1
- package/dist/server/src/api/go2rtc/types.d.ts +6 -2
- package/dist/server/src/api/schemas/go2rtc.schema.d.ts +5 -5
- package/dist/server/src/api/services/cameras.service.d.ts +6 -5
- package/dist/server/src/api/services/cameras.service.js +72 -59
- package/dist/server/src/api/services/cameras.service.js.map +1 -1
- package/dist/server/src/api/services/plugins.service.js +11 -13
- package/dist/server/src/api/services/plugins.service.js.map +1 -1
- package/dist/server/src/api.d.ts +2 -2
- package/dist/server/src/camera/controller.d.ts +9 -4
- package/dist/server/src/camera/controller.js +21 -7
- package/dist/server/src/camera/controller.js.map +1 -1
- package/dist/server/src/camera/device.d.ts +15 -3
- package/dist/server/src/camera/device.js.map +1 -1
- package/dist/server/src/camera/index.d.ts +18 -39
- package/dist/server/src/camera/index.js +137 -165
- package/dist/server/src/camera/index.js.map +1 -1
- package/dist/server/src/camera/interfaces/camera.d.ts +0 -1
- package/dist/server/src/camera/interfaces/camera.js +0 -8
- package/dist/server/src/camera/interfaces/camera.js.map +1 -1
- package/dist/server/src/camera/streaming/werift-session.d.ts +10 -1
- package/dist/server/src/camera/streaming/werift-session.js +16 -1
- package/dist/server/src/camera/streaming/werift-session.js.map +1 -1
- package/dist/server/src/camera/types.d.ts +0 -1
- package/dist/server/src/camera/types.js.map +1 -1
- package/dist/server/src/camera/videoFrame.d.ts +3 -3
- package/dist/server/src/camera/videoFrame.js +6 -7
- package/dist/server/src/camera/videoFrame.js.map +1 -1
- package/dist/server/src/decoder/types.d.ts +4 -9
- package/dist/server/src/decoder/worker.d.ts +3 -5
- package/dist/server/src/decoder/worker.js +40 -64
- package/dist/server/src/decoder/worker.js.map +1 -1
- package/dist/server/src/go2rtc/index.js +1 -1
- package/dist/server/src/go2rtc/index.js.map +1 -1
- package/dist/server/src/index.d.ts +3 -3
- package/dist/server/src/main.js +1 -2
- package/dist/server/src/main.js.map +1 -1
- package/dist/server/src/nats/connection.d.ts +17 -0
- package/dist/server/src/nats/connection.js +66 -0
- package/dist/server/src/nats/connection.js.map +1 -0
- package/dist/server/src/nats/error.d.ts +9 -0
- package/dist/server/src/nats/error.js +11 -0
- package/dist/server/src/nats/error.js.map +1 -0
- package/dist/server/src/nats/index.d.ts +6 -4
- package/dist/server/src/nats/index.js +22 -17
- package/dist/server/src/nats/index.js.map +1 -1
- package/dist/server/src/nats/messageQueue.d.ts +7 -4
- package/dist/server/src/nats/messageQueue.js +43 -59
- package/dist/server/src/nats/messageQueue.js.map +1 -1
- package/dist/server/src/nats/proxy/cameraDevice.js +19 -24
- package/dist/server/src/nats/proxy/cameraDevice.js.map +1 -1
- package/dist/server/src/nats/proxy/deviceManager.d.ts +2 -2
- package/dist/server/src/nats/proxy/deviceManager.js +4 -14
- package/dist/server/src/nats/proxy/deviceManager.js.map +1 -1
- package/dist/server/src/nats/server.js +4 -10
- package/dist/server/src/nats/server.js.map +1 -1
- package/dist/server/src/nats/subscription.d.ts +12 -0
- package/dist/server/src/nats/subscription.js +21 -0
- package/dist/server/src/nats/subscription.js.map +1 -0
- package/dist/server/src/nats/types.d.ts +25 -40
- package/dist/server/src/nats/types.js +1 -10
- package/dist/server/src/nats/types.js.map +1 -1
- package/dist/server/src/nats/utils.d.ts +2 -4
- package/dist/server/src/nats/utils.js +3 -3
- package/dist/server/src/nats/utils.js.map +1 -1
- package/dist/server/src/plugins/index.d.ts +3 -5
- package/dist/server/src/plugins/index.js +54 -141
- package/dist/server/src/plugins/index.js.map +1 -1
- package/dist/server/src/plugins/plugin.d.ts +4 -13
- package/dist/server/src/plugins/plugin.js +40 -90
- package/dist/server/src/plugins/plugin.js.map +1 -1
- package/dist/server/src/plugins/types.d.ts +4 -0
- package/dist/server/src/plugins/types.js.map +1 -1
- package/dist/server/src/plugins/worker.d.ts +1 -1
- package/dist/server/src/plugins/worker.js +52 -66
- package/dist/server/src/plugins/worker.js.map +1 -1
- package/dist/server/src/polyglot/node/decoder/child.js +87 -159
- package/dist/server/src/polyglot/node/decoder/child.js.map +1 -1
- package/dist/server/src/polyglot/node/decoder/imageUtils.d.ts +1 -1
- package/dist/server/src/polyglot/node/plugins/cameraStorage.d.ts +2 -2
- package/dist/server/src/polyglot/node/plugins/cameraStorage.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/child.d.ts +1 -1
- package/dist/server/src/polyglot/node/plugins/child.js +34 -60
- package/dist/server/src/polyglot/node/plugins/child.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/{config.js → configService.js} +1 -1
- package/dist/server/src/polyglot/node/plugins/configService.js.map +1 -0
- package/dist/server/src/polyglot/node/plugins/{api.d.ts → pluginApi.d.ts} +9 -12
- package/dist/server/src/polyglot/node/plugins/pluginApi.js +34 -0
- package/dist/server/src/polyglot/node/plugins/pluginApi.js.map +1 -0
- package/dist/server/src/polyglot/node/plugins/{logger.d.ts → pluginLogger.d.ts} +2 -0
- package/dist/server/src/polyglot/node/plugins/pluginLogger.js +89 -0
- package/dist/server/src/polyglot/node/plugins/pluginLogger.js.map +1 -0
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.d.ts +8 -11
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js +67 -129
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.d.ts +6 -8
- package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.js +15 -43
- package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/storageController.d.ts +2 -2
- package/dist/server/src/polyglot/node/plugins/storageController.js.map +1 -1
- package/dist/server/src/polyglot/python/camera/interfaces/camera.py +0 -6
- package/dist/server/src/polyglot/python/camera/video_frame.py +10 -18
- package/dist/server/src/polyglot/python/camera_ui_types/__init__.py +1 -5
- package/dist/server/src/polyglot/python/decoder/child.py +102 -161
- package/dist/server/src/polyglot/python/plugins/camera_storage.py +10 -23
- package/dist/server/src/polyglot/python/plugins/child.py +35 -60
- package/dist/server/src/polyglot/python/plugins/{proxy/message_queue.py → message_queue.py} +50 -81
- package/dist/server/src/polyglot/python/plugins/plugin_api.py +13 -21
- package/dist/server/src/polyglot/python/plugins/proxy/camera_device.py +90 -173
- package/dist/server/src/polyglot/python/plugins/proxy/device_manager.py +25 -64
- package/dist/server/src/polyglot/python/plugins/storage_controller.py +3 -4
- package/dist/server/src/polyglot/python/utilities/connection.py +86 -0
- package/dist/server/src/polyglot/python/utilities/object_path.py +12 -4
- package/dist/server/src/polyglot/python/utilities/subscriptions.py +20 -0
- package/dist/server/src/polyglot/python/utilities/task.py +11 -1
- package/dist/server/src/services/config/index.js +4 -2
- package/dist/server/src/services/config/index.js.map +1 -1
- package/dist/server/src/services/logger/index.js +11 -8
- package/dist/server/src/services/logger/index.js.map +1 -1
- package/dist/server/src/utils/ffmpeg.d.ts +2 -0
- package/dist/server/src/{decoder → utils}/ffmpeg.js +2 -2
- package/dist/server/src/utils/ffmpeg.js.map +1 -0
- package/dist/server/src/utils/pythonInstaller.d.ts +1 -1
- package/dist/server/src/utils/pythonInstaller.js +10 -4
- package/dist/server/src/utils/pythonInstaller.js.map +1 -1
- package/dist/server/src/utils/reader.js.map +1 -0
- package/dist/server/src/utils/subscribed.d.ts +4 -4
- package/dist/server/src/utils/subscribed.js.map +1 -1
- package/package.json +8 -7
- package/dist/interface/assets/@camera.ui-2NVnv26v.js +0 -8
- package/dist/interface/assets/Account-gJpkf0nE.js +0 -1
- package/dist/interface/assets/Adminpanel-Bge9nu5N.js +0 -1
- package/dist/interface/assets/Appearance-D22q-X_I.js +0 -1
- package/dist/interface/assets/Backup-pJm6s10G.js +0 -1
- package/dist/interface/assets/Camera-BgO2yRjb.js +0 -1
- package/dist/interface/assets/Cameras-BM3vSM_R.css +0 -1
- package/dist/interface/assets/Cameras-DjeKruR_.js +0 -1
- package/dist/interface/assets/Camview-DfzlprzN.js +0 -1
- package/dist/interface/assets/Config-BKIOIkjC.js +0 -1
- package/dist/interface/assets/FirstSteps-mQK4XFTs.js +0 -1
- package/dist/interface/assets/Plugin-Di_bBsg-.js +0 -1
- package/dist/interface/assets/Plugins-BsMITags.css +0 -1
- package/dist/interface/assets/Plugins-DhmzMNuO.js +0 -1
- package/dist/interface/assets/Recordings-Bu53bSBp.js +0 -1
- package/dist/interface/assets/Recordings-XY20w8yp.js +0 -1
- package/dist/interface/assets/Settings-gGRBRVST.js +0 -1
- package/dist/interface/assets/System-ZDrcLNk0.js +0 -1
- package/dist/interface/assets/User-D4vEhhzi.js +0 -1
- package/dist/interface/assets/VConfigEditor.vue_vue_type_script_setup_true_lang-CXFI-IeE.js +0 -2
- package/dist/interface/assets/VConsole-BHo3xprq.js +0 -1
- package/dist/interface/assets/VConsole-f-nUkOuD.css +0 -1
- package/dist/interface/assets/VPluginCard-BJYMuCLk.css +0 -1
- package/dist/interface/assets/encode-utf8-Cn5aGd7v.js +0 -1
- package/dist/interface/assets/main-C4rYiRNz.js +0 -2
- package/dist/interface/assets/qrcode-CGiDONbL.js +0 -8
- package/dist/interface/assets/vuetify-_-Oqac3B.js +0 -5
- package/dist/server/src/decoder/ffmpeg.d.ts +0 -2
- package/dist/server/src/decoder/ffmpeg.js.map +0 -1
- package/dist/server/src/nats/proxy/index.d.ts +0 -2
- package/dist/server/src/nats/proxy/index.js +0 -3
- package/dist/server/src/nats/proxy/index.js.map +0 -1
- package/dist/server/src/polyglot/node/decoder/reader.js.map +0 -1
- package/dist/server/src/polyglot/node/plugins/api.js +0 -34
- package/dist/server/src/polyglot/node/plugins/api.js.map +0 -1
- package/dist/server/src/polyglot/node/plugins/config.js.map +0 -1
- package/dist/server/src/polyglot/node/plugins/logger.js +0 -128
- package/dist/server/src/polyglot/node/plugins/logger.js.map +0 -1
- package/dist/server/src/polyglot/node/plugins/proxy/index.d.ts +0 -2
- package/dist/server/src/polyglot/node/plugins/proxy/index.js +0 -3
- package/dist/server/src/polyglot/node/plugins/proxy/index.js.map +0 -1
- package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.d.ts +0 -20
- package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.js +0 -152
- package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.js.map +0 -1
- /package/dist/server/src/polyglot/node/plugins/{config.d.ts → configService.d.ts} +0 -0
- /package/dist/server/src/polyglot/python/plugins/{logger.py → plugin_logger.py} +0 -0
- /package/dist/server/src/{polyglot/node/decoder → utils}/reader.d.ts +0 -0
- /package/dist/server/src/{polyglot/node/decoder → utils}/reader.js +0 -0
|
@@ -10,18 +10,16 @@ from camera_ui_types import (
|
|
|
10
10
|
ImageOptions,
|
|
11
11
|
MotionState,
|
|
12
12
|
)
|
|
13
|
-
from nats.aio.client import Client as NatsConnection
|
|
14
|
-
from nats.aio.msg import Msg
|
|
15
13
|
from PIL import Image
|
|
16
14
|
from plugins.typings import ProcessPrebufferedImageRequest
|
|
17
|
-
from utilities.
|
|
15
|
+
from utilities.connection import ProxyConnection
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
class VideoFrame:
|
|
21
19
|
def __init__(
|
|
22
20
|
self,
|
|
23
21
|
camera_id: str,
|
|
24
|
-
publisher:
|
|
22
|
+
publisher: ProxyConnection,
|
|
25
23
|
frame_data: FrameData,
|
|
26
24
|
metadata: FrameMetadata,
|
|
27
25
|
prebuffer_duration: int,
|
|
@@ -57,10 +55,10 @@ class VideoFrame:
|
|
|
57
55
|
options = self.__validate_options("buffer", options)
|
|
58
56
|
image_information = self.__get_image_information(options)
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
data = await self.__send(options)
|
|
61
59
|
|
|
62
60
|
return {
|
|
63
|
-
"image":
|
|
61
|
+
"image": data,
|
|
64
62
|
"info": image_information,
|
|
65
63
|
}
|
|
66
64
|
|
|
@@ -76,12 +74,10 @@ class VideoFrame:
|
|
|
76
74
|
else "RGB"
|
|
77
75
|
)
|
|
78
76
|
|
|
79
|
-
|
|
77
|
+
data = await self.__send(options)
|
|
80
78
|
|
|
81
79
|
return {
|
|
82
|
-
"image": Image.frombytes(
|
|
83
|
-
mode, (image_information["width"], image_information["height"]), response.data
|
|
84
|
-
),
|
|
80
|
+
"image": Image.frombytes(mode, (image_information["width"], image_information["height"]), data),
|
|
85
81
|
"info": image_information,
|
|
86
82
|
}
|
|
87
83
|
|
|
@@ -90,8 +86,8 @@ class VideoFrame:
|
|
|
90
86
|
image["image"].save(path)
|
|
91
87
|
image["image"].close()
|
|
92
88
|
|
|
93
|
-
async def __send(self, options: ImageOptions) ->
|
|
94
|
-
if not self.__publisher
|
|
89
|
+
async def __send(self, options: ImageOptions) -> bytes:
|
|
90
|
+
if not self.__publisher:
|
|
95
91
|
raise Exception("Frame generator closed?")
|
|
96
92
|
|
|
97
93
|
request: ProcessPrebufferedImageRequest = {
|
|
@@ -101,11 +97,7 @@ class VideoFrame:
|
|
|
101
97
|
"prebufferDuration": self.__prebuffer_duration,
|
|
102
98
|
}
|
|
103
99
|
|
|
104
|
-
return await self.__publisher.request(
|
|
105
|
-
self.__frame_generator_subject,
|
|
106
|
-
pack(request),
|
|
107
|
-
10000,
|
|
108
|
-
)
|
|
100
|
+
return await self.__publisher.request(self.__frame_generator_subject, request, 10000)
|
|
109
101
|
|
|
110
102
|
def __validate_options(
|
|
111
103
|
self,
|
|
@@ -183,7 +175,7 @@ class MotionFrame(VideoFrame):
|
|
|
183
175
|
def __init__(
|
|
184
176
|
self,
|
|
185
177
|
camera_id: str,
|
|
186
|
-
publisher:
|
|
178
|
+
publisher: ProxyConnection,
|
|
187
179
|
frame_data: FrameData,
|
|
188
180
|
motion_state: MotionState,
|
|
189
181
|
metadata: FrameMetadata,
|
|
@@ -646,9 +646,6 @@ class CameraDelegate(metaclass=ABCMeta):
|
|
|
646
646
|
@abstractmethod
|
|
647
647
|
async def snapshot(self) -> bytes: ...
|
|
648
648
|
|
|
649
|
-
@abstractmethod
|
|
650
|
-
async def reboot(self) -> None: ...
|
|
651
|
-
|
|
652
649
|
|
|
653
650
|
CameraDelegateMethodNames = Literal["reboot", "snapshot"]
|
|
654
651
|
|
|
@@ -836,8 +833,7 @@ class CameraDevice(Protocol):
|
|
|
836
833
|
mid_resolution_source: Optional[CameraSource]
|
|
837
834
|
low_resolution_source: Optional[CameraSource]
|
|
838
835
|
|
|
839
|
-
|
|
840
|
-
ptzDelegate: CameraPTZDelegate
|
|
836
|
+
ptz: CameraPTZDelegate
|
|
841
837
|
|
|
842
838
|
@overload
|
|
843
839
|
def set_delegate(self, name: Literal["cameraDelegate"], delegate: CameraDelegate) -> None: ...
|
|
@@ -9,14 +9,11 @@ from contextlib import suppress
|
|
|
9
9
|
from datetime import datetime
|
|
10
10
|
from typing import Any, Literal, Optional, Union, cast
|
|
11
11
|
|
|
12
|
-
import nats
|
|
13
12
|
from camera_ui_types import DecoderFormat, FrameData, FrameMetadata, ImageOptions
|
|
14
13
|
from image_utils import process_image_threaded
|
|
15
|
-
from nats.aio.client import Client as NatsConnection
|
|
16
14
|
from nats.aio.msg import Msg
|
|
17
|
-
from nats.aio.subscription import Subscription
|
|
18
15
|
from nats.errors import NoRespondersError, TimeoutError
|
|
19
|
-
from plugins.
|
|
16
|
+
from plugins.plugin_logger import PluginLogger
|
|
20
17
|
from plugins.typings import ProcessPrebufferedImageRequest
|
|
21
18
|
from typings import (
|
|
22
19
|
BaseFrameWorkerConfig,
|
|
@@ -35,7 +32,9 @@ from typings import (
|
|
|
35
32
|
WorkerToMainMessage,
|
|
36
33
|
WorkerToMainResponse,
|
|
37
34
|
)
|
|
35
|
+
from utilities.connection import ProxyConnection
|
|
38
36
|
from utilities.packer import pack, unpack
|
|
37
|
+
from utilities.subscriptions import ProxySubscription
|
|
39
38
|
from utilities.task import TaskSet
|
|
40
39
|
|
|
41
40
|
config: BaseFrameWorkerConfig = {
|
|
@@ -73,14 +72,14 @@ class FrameWorkerChild:
|
|
|
73
72
|
self.signaling_subject = f"{config['cameraId']}.frameGenerator.signaling"
|
|
74
73
|
self.frame_subject = f"{config['cameraId']}.frameReceiver"
|
|
75
74
|
|
|
76
|
-
self.publisher: Optional[
|
|
77
|
-
self.signaling_publisher: Optional[
|
|
78
|
-
self.image_publisher: Optional[
|
|
79
|
-
self.frame_publisher: Optional[
|
|
75
|
+
self.publisher: Optional[ProxyConnection] = None
|
|
76
|
+
self.signaling_publisher: Optional[ProxyConnection] = None
|
|
77
|
+
self.image_publisher: Optional[ProxyConnection] = None
|
|
78
|
+
self.frame_publisher: Optional[ProxyConnection] = None
|
|
80
79
|
|
|
81
|
-
self.subscriber: Optional[
|
|
82
|
-
self.image_subscriber: Optional[
|
|
83
|
-
self.signal_subscriber: Optional[
|
|
80
|
+
self.subscriber: Optional[ProxySubscription] = None
|
|
81
|
+
self.image_subscriber: Optional[ProxySubscription] = None
|
|
82
|
+
self.signal_subscriber: Optional[ProxySubscription] = None
|
|
84
83
|
|
|
85
84
|
self.max_diff_frame = 3
|
|
86
85
|
self.restart_delay = 5
|
|
@@ -105,6 +104,12 @@ class FrameWorkerChild:
|
|
|
105
104
|
self.stdout_task: Optional[asyncio.Task[None]] = None
|
|
106
105
|
self.close_task: Optional[asyncio.Task[None]] = None
|
|
107
106
|
|
|
107
|
+
self.restart_timeout: Optional[asyncio.TimerHandle] = None
|
|
108
|
+
self.restart_delay = 10
|
|
109
|
+
|
|
110
|
+
self.close_timeout: Optional[asyncio.TimerHandle] = None
|
|
111
|
+
self.close_delay = 5
|
|
112
|
+
|
|
108
113
|
@property
|
|
109
114
|
def log_prefix(self) -> str:
|
|
110
115
|
return f"{self.camera_name}:"
|
|
@@ -119,72 +124,30 @@ class FrameWorkerChild:
|
|
|
119
124
|
async def listen(self) -> None:
|
|
120
125
|
self.setup_signal_handlers()
|
|
121
126
|
|
|
122
|
-
|
|
123
|
-
pass
|
|
127
|
+
servers = [endpoint for endpoint in config["proxyEndpoints"] if endpoint.startswith("nats://")]
|
|
124
128
|
|
|
125
|
-
self.publisher =
|
|
126
|
-
|
|
127
|
-
name=self.subject,
|
|
128
|
-
user=config["auth"]["user"],
|
|
129
|
-
password=config["auth"]["password"],
|
|
130
|
-
max_reconnect_attempts=-1,
|
|
131
|
-
error_cb=ignore_cb,
|
|
132
|
-
disconnected_cb=ignore_cb,
|
|
133
|
-
closed_cb=ignore_cb,
|
|
134
|
-
reconnected_cb=ignore_cb,
|
|
135
|
-
discovered_server_cb=ignore_cb,
|
|
136
|
-
)
|
|
129
|
+
self.publisher = ProxyConnection(self.subject, servers, config["auth"])
|
|
130
|
+
await self.publisher.connect()
|
|
137
131
|
|
|
138
|
-
self.image_publisher =
|
|
139
|
-
|
|
140
|
-
name=self.image_subject,
|
|
141
|
-
user=config["auth"]["user"],
|
|
142
|
-
password=config["auth"]["password"],
|
|
143
|
-
max_reconnect_attempts=-1,
|
|
144
|
-
error_cb=ignore_cb,
|
|
145
|
-
disconnected_cb=ignore_cb,
|
|
146
|
-
closed_cb=ignore_cb,
|
|
147
|
-
reconnected_cb=ignore_cb,
|
|
148
|
-
discovered_server_cb=ignore_cb,
|
|
149
|
-
)
|
|
132
|
+
self.image_publisher = ProxyConnection(self.image_subject, servers, config["auth"])
|
|
133
|
+
await self.image_publisher.connect()
|
|
150
134
|
|
|
151
|
-
self.frame_publisher =
|
|
152
|
-
|
|
153
|
-
name=self.frame_subject,
|
|
154
|
-
user=config["auth"]["user"],
|
|
155
|
-
password=config["auth"]["password"],
|
|
156
|
-
max_reconnect_attempts=-1,
|
|
157
|
-
error_cb=ignore_cb,
|
|
158
|
-
disconnected_cb=ignore_cb,
|
|
159
|
-
closed_cb=ignore_cb,
|
|
160
|
-
reconnected_cb=ignore_cb,
|
|
161
|
-
discovered_server_cb=ignore_cb,
|
|
162
|
-
)
|
|
135
|
+
self.frame_publisher = ProxyConnection(self.frame_subject, servers, config["auth"])
|
|
136
|
+
await self.frame_publisher.connect()
|
|
163
137
|
|
|
164
|
-
self.signaling_publisher =
|
|
165
|
-
|
|
166
|
-
name=self.signaling_subject,
|
|
167
|
-
user=config["auth"]["user"],
|
|
168
|
-
password=config["auth"]["password"],
|
|
169
|
-
max_reconnect_attempts=-1,
|
|
170
|
-
error_cb=ignore_cb,
|
|
171
|
-
disconnected_cb=ignore_cb,
|
|
172
|
-
closed_cb=ignore_cb,
|
|
173
|
-
reconnected_cb=ignore_cb,
|
|
174
|
-
discovered_server_cb=ignore_cb,
|
|
175
|
-
)
|
|
138
|
+
self.signaling_publisher = ProxyConnection(self.signaling_subject, servers, config["auth"])
|
|
139
|
+
await self.signaling_publisher.connect()
|
|
176
140
|
|
|
177
141
|
self.subscriber = await self.publisher.subscribe(subject=self.subject)
|
|
142
|
+
self.subscriber.on("message", self.on_worker_message)
|
|
143
|
+
|
|
178
144
|
self.image_subscriber = await self.image_publisher.subscribe(subject=self.image_subject)
|
|
179
|
-
self.
|
|
145
|
+
self.image_subscriber.on("message", self.on_image_request)
|
|
180
146
|
|
|
181
|
-
await
|
|
182
|
-
|
|
183
|
-
self.listen_to_ipc_messages(),
|
|
184
|
-
self.listen_to_signaling_messages(),
|
|
185
|
-
self.listen_to_prebuffered_image_messages(),
|
|
186
|
-
)
|
|
147
|
+
self.signal_subscriber = await self.signaling_publisher.subscribe(subject=self.signaling_subject)
|
|
148
|
+
self.signal_subscriber.on("message", self.on_signaling_message)
|
|
187
149
|
|
|
150
|
+
await self.send("started")
|
|
188
151
|
await self.shutdown_event.wait()
|
|
189
152
|
|
|
190
153
|
async def close(self) -> None:
|
|
@@ -209,13 +172,14 @@ class FrameWorkerChild:
|
|
|
209
172
|
async def start(self) -> None:
|
|
210
173
|
try:
|
|
211
174
|
self.closed = False
|
|
175
|
+
|
|
176
|
+
if self.close_timeout:
|
|
177
|
+
self.close_timeout.cancel()
|
|
178
|
+
self.close_timeout = None
|
|
179
|
+
|
|
212
180
|
await self.start_video_session()
|
|
213
181
|
except Exception as e:
|
|
214
|
-
self.logger.error(
|
|
215
|
-
f"{self.log_prefix} An error occurred while starting frame session:",
|
|
216
|
-
e,
|
|
217
|
-
)
|
|
218
|
-
|
|
182
|
+
self.logger.error(f"{self.log_prefix} An error occurred while starting frame session:", e)
|
|
219
183
|
await self.restart_ffmpeg()
|
|
220
184
|
|
|
221
185
|
async def stop(self) -> None:
|
|
@@ -237,6 +201,14 @@ class FrameWorkerChild:
|
|
|
237
201
|
self._metadata = None
|
|
238
202
|
|
|
239
203
|
async def reset_video_session(self) -> None:
|
|
204
|
+
if self.close_timeout:
|
|
205
|
+
self.close_timeout.cancel()
|
|
206
|
+
self.close_timeout = None
|
|
207
|
+
|
|
208
|
+
if self.restart_timeout:
|
|
209
|
+
self.restart_timeout.cancel()
|
|
210
|
+
self.restart_timeout = None
|
|
211
|
+
|
|
240
212
|
if self.stderr_task:
|
|
241
213
|
self.stderr_task.cancel()
|
|
242
214
|
self.stderr_task = None
|
|
@@ -256,8 +228,7 @@ class FrameWorkerChild:
|
|
|
256
228
|
self.ffmpeg_process = None
|
|
257
229
|
|
|
258
230
|
async def start_video_session(self) -> None:
|
|
259
|
-
|
|
260
|
-
return
|
|
231
|
+
await self.reset_video_session()
|
|
261
232
|
|
|
262
233
|
# await self.reset()
|
|
263
234
|
self.stopped = False
|
|
@@ -267,9 +238,6 @@ class FrameWorkerChild:
|
|
|
267
238
|
await asyncio.wait_for(self.metadata_event.wait(), timeout=15)
|
|
268
239
|
self.logger.debug(f"{self.log_prefix} Frame session started")
|
|
269
240
|
except asyncio.TimeoutError:
|
|
270
|
-
ffmpeg_process = cast(Optional[asyncio.subprocess.Process], self.ffmpeg_process)
|
|
271
|
-
if ffmpeg_process and ffmpeg_process.returncode is None:
|
|
272
|
-
ffmpeg_process.kill()
|
|
273
241
|
raise Exception("FFmpeg process timed out") from None
|
|
274
242
|
|
|
275
243
|
def build_ffmpeg_args(self, ffmpeg_path: str, camera_source: str, ffmpeg_args: FfmpegArgs) -> list[str]:
|
|
@@ -335,7 +303,7 @@ class FrameWorkerChild:
|
|
|
335
303
|
self.close_task = self.tasks.add(self.handle_ffmpeg_close())
|
|
336
304
|
|
|
337
305
|
async def restart_ffmpeg(self) -> None:
|
|
338
|
-
if not self.stopped and not self.closed and not self.restarting:
|
|
306
|
+
if not self.stopped and not self.closed and not self.restarting and len(self.clients) > 0:
|
|
339
307
|
self.restarting = True
|
|
340
308
|
|
|
341
309
|
self.logger.log(f"{self.log_prefix} Restarting FFmpeg process in {self.restart_delay} seconds...")
|
|
@@ -343,7 +311,7 @@ class FrameWorkerChild:
|
|
|
343
311
|
with suppress(asyncio.TimeoutError):
|
|
344
312
|
await asyncio.wait_for(asyncio.sleep(self.restart_delay), timeout=self.restart_delay)
|
|
345
313
|
|
|
346
|
-
if not self.stopped and not self.closed:
|
|
314
|
+
if not self.stopped and not self.closed and len(self.clients) > 0:
|
|
347
315
|
await self.start()
|
|
348
316
|
|
|
349
317
|
self.restarting = False
|
|
@@ -392,32 +360,40 @@ class FrameWorkerChild:
|
|
|
392
360
|
async def handle_ffmpeg_stdout(self) -> None:
|
|
393
361
|
try:
|
|
394
362
|
metadata = (await self.metadata).copy()
|
|
395
|
-
|
|
363
|
+
warned = False
|
|
396
364
|
|
|
397
365
|
def is_closed() -> bool:
|
|
398
366
|
return (
|
|
399
367
|
self.stopped
|
|
400
368
|
or self.closed
|
|
401
369
|
or not self.frame_publisher
|
|
402
|
-
or self.frame_publisher.is_closed
|
|
403
370
|
or not self.ffmpeg_process
|
|
404
371
|
or not self.ffmpeg_process.stdout
|
|
405
372
|
or self.ffmpeg_process.returncode is not None
|
|
406
373
|
)
|
|
407
374
|
|
|
375
|
+
def reset_restart_watchdog():
|
|
376
|
+
if self.restart_timeout:
|
|
377
|
+
self.restart_timeout.cancel()
|
|
378
|
+
self.restart_timeout = None
|
|
379
|
+
|
|
408
380
|
def restart_watchdog():
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
restart_timeout = asyncio.get_event_loop().call_later(
|
|
413
|
-
3, lambda: asyncio.create_task(restart_ffmpeg())
|
|
381
|
+
reset_restart_watchdog()
|
|
382
|
+
self.restart_timeout = asyncio.get_event_loop().call_later(
|
|
383
|
+
self.restart_delay, lambda: asyncio.create_task(restart_ffmpeg())
|
|
414
384
|
)
|
|
415
385
|
|
|
416
386
|
async def restart_ffmpeg():
|
|
417
387
|
if not self.stopped and not self.closed and not self.restarting:
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
388
|
+
message = "FFmpeg process is not producing frames, terminating..."
|
|
389
|
+
|
|
390
|
+
nonlocal warned
|
|
391
|
+
if warned is False:
|
|
392
|
+
self.logger.debug(f"{self.log_prefix} {message}")
|
|
393
|
+
warned = True
|
|
394
|
+
else:
|
|
395
|
+
self.logger.error(f"{self.log_prefix} {message}")
|
|
396
|
+
|
|
421
397
|
await self.reset()
|
|
422
398
|
await self.restart_ffmpeg()
|
|
423
399
|
|
|
@@ -429,7 +405,10 @@ class FrameWorkerChild:
|
|
|
429
405
|
int(metadata["frameSize"]),
|
|
430
406
|
)
|
|
431
407
|
|
|
408
|
+
warned = False
|
|
409
|
+
|
|
432
410
|
if is_closed():
|
|
411
|
+
reset_restart_watchdog()
|
|
433
412
|
break
|
|
434
413
|
|
|
435
414
|
frame_id = self.generate_id()
|
|
@@ -459,7 +438,7 @@ class FrameWorkerChild:
|
|
|
459
438
|
if self.prebuffer_full:
|
|
460
439
|
frame_data: FrameData = {"frameId": frame_id, "timestamp": now}
|
|
461
440
|
|
|
462
|
-
await self.frame_publisher.publish(self.frame_subject,
|
|
441
|
+
await self.frame_publisher.publish(self.frame_subject, frame_data) # type: ignore
|
|
463
442
|
|
|
464
443
|
except asyncio.IncompleteReadError as e:
|
|
465
444
|
if not is_closed() and not self.restarting:
|
|
@@ -473,6 +452,8 @@ class FrameWorkerChild:
|
|
|
473
452
|
e,
|
|
474
453
|
)
|
|
475
454
|
break
|
|
455
|
+
finally:
|
|
456
|
+
reset_restart_watchdog()
|
|
476
457
|
except asyncio.CancelledError:
|
|
477
458
|
pass
|
|
478
459
|
|
|
@@ -480,9 +461,6 @@ class FrameWorkerChild:
|
|
|
480
461
|
try:
|
|
481
462
|
if self.ffmpeg_process:
|
|
482
463
|
code = await self.ffmpeg_process.wait()
|
|
483
|
-
self.ffmpeg_process = None
|
|
484
|
-
|
|
485
|
-
await self.reset()
|
|
486
464
|
|
|
487
465
|
if code != 0 and code != -9 or not self.stopped:
|
|
488
466
|
self.logger.error(
|
|
@@ -494,6 +472,9 @@ class FrameWorkerChild:
|
|
|
494
472
|
f"{self.log_prefix} FFmpeg process has exited with code {code} (expected)"
|
|
495
473
|
)
|
|
496
474
|
|
|
475
|
+
self.ffmpeg_process = None
|
|
476
|
+
|
|
477
|
+
await self.reset()
|
|
497
478
|
await self.restart_ffmpeg()
|
|
498
479
|
except asyncio.CancelledError:
|
|
499
480
|
pass
|
|
@@ -547,14 +528,10 @@ class FrameWorkerChild:
|
|
|
547
528
|
"data": data,
|
|
548
529
|
}
|
|
549
530
|
|
|
550
|
-
|
|
551
|
-
self.ipc_subject,
|
|
552
|
-
pack(worker_message),
|
|
553
|
-
timeout=30,
|
|
531
|
+
response: MainToWorkerResponse = await self.publisher.request(
|
|
532
|
+
self.ipc_subject, worker_message, timeout=30
|
|
554
533
|
)
|
|
555
534
|
|
|
556
|
-
response: MainToWorkerResponse = unpack(msg.data)
|
|
557
|
-
|
|
558
535
|
return response.get("response")
|
|
559
536
|
|
|
560
537
|
async def add_client(self, plugin_id: str, request_id: str) -> None:
|
|
@@ -593,7 +570,12 @@ class FrameWorkerChild:
|
|
|
593
570
|
await self.send("updateClient", {"pluginId": client.plugin_id, "requestIds": client.request_ids})
|
|
594
571
|
|
|
595
572
|
if len(self.clients) == 0:
|
|
596
|
-
|
|
573
|
+
if self.close_timeout:
|
|
574
|
+
self.close_timeout.cancel()
|
|
575
|
+
|
|
576
|
+
self.close_timeout = asyncio.get_event_loop().call_later(
|
|
577
|
+
self.close_delay, lambda: asyncio.create_task(self.stop())
|
|
578
|
+
)
|
|
597
579
|
|
|
598
580
|
async def recover_clients(self, clients: list[RecoveredClient]) -> None:
|
|
599
581
|
for client in clients:
|
|
@@ -617,7 +599,7 @@ class FrameWorkerChild:
|
|
|
617
599
|
|
|
618
600
|
response: SignalingResponse = {"type": "disconnect", "requestId": request_id}
|
|
619
601
|
|
|
620
|
-
await self.signaling_publisher.publish(ping_target_subject,
|
|
602
|
+
await self.signaling_publisher.publish(ping_target_subject, response)
|
|
621
603
|
await self.remove_client(plugin_id, request_id)
|
|
622
604
|
|
|
623
605
|
async def disconnect_all_clients(self) -> None:
|
|
@@ -653,22 +635,20 @@ class FrameWorkerChild:
|
|
|
653
635
|
|
|
654
636
|
while self.signaling_publisher and request_id_exists():
|
|
655
637
|
try:
|
|
656
|
-
|
|
638
|
+
message: PingMessage = {"type": "ping", "requestId": request_id}
|
|
657
639
|
|
|
658
640
|
# self.logger.trace(f"{self.log_prefix} Sending ping to {camera_id}:{plugin_id}")
|
|
659
641
|
|
|
660
|
-
|
|
642
|
+
response: PongMessage = await self.signaling_publisher.request(
|
|
661
643
|
ping_target_subject,
|
|
662
|
-
|
|
644
|
+
message,
|
|
663
645
|
timeout=ping_timeout,
|
|
664
646
|
)
|
|
665
647
|
|
|
666
|
-
ping_response: PongMessage = unpack(msg.data)
|
|
667
|
-
|
|
668
648
|
if not request_id_exists():
|
|
669
649
|
break
|
|
670
650
|
|
|
671
|
-
if
|
|
651
|
+
if response["type"] != "pong":
|
|
672
652
|
raise Exception("Invalid response to ping")
|
|
673
653
|
|
|
674
654
|
# self.logger.trace(f"{self.log_prefix} Received pong from {camera_id}:{plugin_id}")
|
|
@@ -684,62 +664,23 @@ class FrameWorkerChild:
|
|
|
684
664
|
|
|
685
665
|
break
|
|
686
666
|
|
|
687
|
-
async def
|
|
688
|
-
if
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
async for msg in self.subscriber.messages:
|
|
692
|
-
try:
|
|
693
|
-
if self.closed:
|
|
694
|
-
break
|
|
695
|
-
|
|
696
|
-
if len(msg.data) == 0:
|
|
697
|
-
continue
|
|
698
|
-
|
|
699
|
-
self.tasks.add(self.respond_on_ipc_message(msg))
|
|
700
|
-
except Exception as e:
|
|
701
|
-
if not self.closed:
|
|
702
|
-
self.logger.error(f"{self.log_prefix} Error while processing IPC message:", e)
|
|
703
|
-
else:
|
|
704
|
-
break
|
|
705
|
-
|
|
706
|
-
async def listen_to_signaling_messages(self) -> None:
|
|
707
|
-
if not self.signal_subscriber:
|
|
708
|
-
raise Exception("Subscriber not initialized")
|
|
709
|
-
|
|
710
|
-
async for msg in self.signal_subscriber.messages:
|
|
711
|
-
try:
|
|
712
|
-
if self.closed:
|
|
713
|
-
break
|
|
714
|
-
|
|
715
|
-
if len(msg.data) == 0:
|
|
716
|
-
continue
|
|
667
|
+
async def on_worker_message(self, msg: Msg) -> None:
|
|
668
|
+
if self.closed:
|
|
669
|
+
return
|
|
717
670
|
|
|
718
|
-
|
|
719
|
-
except Exception as e:
|
|
720
|
-
if not self.closed:
|
|
721
|
-
self.logger.error(f"{self.log_prefix} Error while processing signaling message:", e)
|
|
722
|
-
else:
|
|
723
|
-
break
|
|
671
|
+
self.tasks.add(self.respond_on_ipc_message(msg))
|
|
724
672
|
|
|
725
|
-
async def
|
|
726
|
-
if
|
|
727
|
-
|
|
673
|
+
async def on_signaling_message(self, msg: Msg) -> None:
|
|
674
|
+
if self.closed:
|
|
675
|
+
return
|
|
728
676
|
|
|
729
|
-
|
|
730
|
-
try:
|
|
731
|
-
if self.closed:
|
|
732
|
-
break
|
|
677
|
+
self.tasks.add(self.respond_on_signaling_message(msg))
|
|
733
678
|
|
|
734
|
-
|
|
735
|
-
|
|
679
|
+
async def on_image_request(self, msg: Msg) -> None:
|
|
680
|
+
if self.closed:
|
|
681
|
+
return
|
|
736
682
|
|
|
737
|
-
|
|
738
|
-
except Exception as e:
|
|
739
|
-
if not self.closed:
|
|
740
|
-
self.logger.error(f"{self.log_prefix} Error while processing image message:", e)
|
|
741
|
-
else:
|
|
742
|
-
break
|
|
683
|
+
self.tasks.add(self.respond_on_prebuffered_image_message(msg))
|
|
743
684
|
|
|
744
685
|
async def respond_on_ipc_message(self, msg: Msg) -> None:
|
|
745
686
|
try:
|
|
@@ -788,10 +729,10 @@ class FrameWorkerChild:
|
|
|
788
729
|
processed_image = await self.process_frame(
|
|
789
730
|
target_frame["frame"], width, height, format, options
|
|
790
731
|
)
|
|
791
|
-
await msg.respond(processed_image)
|
|
732
|
+
await msg.respond(pack(processed_image))
|
|
792
733
|
return
|
|
793
734
|
|
|
794
|
-
await msg.respond(b"")
|
|
735
|
+
await msg.respond(pack(b""))
|
|
795
736
|
except Exception as e:
|
|
796
737
|
self.logger.error(f"{self.log_prefix} Error while processing image respond:", e)
|
|
797
738
|
|
|
@@ -14,7 +14,6 @@ from camera_ui_types import (
|
|
|
14
14
|
)
|
|
15
15
|
from deepdiff import DeepDiff
|
|
16
16
|
from lmdbm import Lmdb
|
|
17
|
-
from logger import PluginLogger
|
|
18
17
|
from plugin_api import PluginAPI
|
|
19
18
|
from schema import (
|
|
20
19
|
config_path_to_schema_path,
|
|
@@ -61,7 +60,6 @@ class CameraStorage:
|
|
|
61
60
|
def __init__(
|
|
62
61
|
self,
|
|
63
62
|
api: PluginAPI,
|
|
64
|
-
logger: PluginLogger,
|
|
65
63
|
instance: Any,
|
|
66
64
|
camera_id: str,
|
|
67
65
|
schema: Optional[PluginJsonSchemaForm] = None,
|
|
@@ -69,7 +67,6 @@ class CameraStorage:
|
|
|
69
67
|
if schema is None:
|
|
70
68
|
schema = {}
|
|
71
69
|
self.__api = api
|
|
72
|
-
self.__logger = logger
|
|
73
70
|
self.__instance = instance
|
|
74
71
|
self.__camera_id = camera_id
|
|
75
72
|
self.__schema: PluginJsonSchemaForm = schema or {}
|
|
@@ -96,8 +93,8 @@ class CameraStorage:
|
|
|
96
93
|
try:
|
|
97
94
|
config: Any = self.__db.get("config") or {}
|
|
98
95
|
camera_config = config.get(self.__camera_id, {})
|
|
99
|
-
except
|
|
100
|
-
|
|
96
|
+
except: # noqa: E722
|
|
97
|
+
pass
|
|
101
98
|
|
|
102
99
|
schema_config = generate_json_from_root_schema({"schema": self.__schema})
|
|
103
100
|
|
|
@@ -426,29 +423,19 @@ class CameraStorage:
|
|
|
426
423
|
)
|
|
427
424
|
|
|
428
425
|
def __save_db(self) -> None:
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
storable_config = self.__filter_storable_values(self.__schema)
|
|
426
|
+
config: Any = self.__db.get("config") or {}
|
|
427
|
+
storable_config = self.__filter_storable_values(self.__schema)
|
|
432
428
|
|
|
433
|
-
|
|
429
|
+
config[self.__camera_id] = storable_config
|
|
434
430
|
|
|
435
|
-
|
|
436
|
-
{
|
|
437
|
-
"config": config,
|
|
438
|
-
}
|
|
439
|
-
)
|
|
440
|
-
except Exception as e:
|
|
441
|
-
self.__logger.error("Error saving to database:", e)
|
|
431
|
+
self.__db.update({"config": config})
|
|
442
432
|
|
|
443
433
|
def __remove_db(self) -> None:
|
|
444
|
-
|
|
445
|
-
config: Any = self.__db.get("config") or {}
|
|
434
|
+
config: Any = self.__db.get("config") or {}
|
|
446
435
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
except Exception as e:
|
|
451
|
-
self.__logger.error("Error removing from database:", e)
|
|
436
|
+
if self.__camera_id in config:
|
|
437
|
+
del config[self.__camera_id]
|
|
438
|
+
self.__db.update(config)
|
|
452
439
|
|
|
453
440
|
def __deselected(self, id: str) -> None:
|
|
454
441
|
if id == self.__camera_id:
|