@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.
Files changed (238) hide show
  1. package/dist/interface/assets/{@tanstack-BqH4GyO-.js → @tanstack-B-9PO-kT.js} +1 -1
  2. package/dist/interface/assets/{@vee-validate-DCBdnGo-.js → @vee-validate-D_G0ehOl.js} +1 -1
  3. package/dist/interface/assets/{@vue-C7-KaDG4.js → @vue-C10tA4b9.js} +6 -6
  4. package/dist/interface/assets/{@vueform-arggO0eF.js → @vueform-Bj73kRPS.js} +1 -1
  5. package/dist/interface/assets/{@vueuse-C3WMTDqL.js → @vueuse-BPeqNGoM.js} +1 -1
  6. package/dist/interface/assets/Account-MEaGtu1D.js +1 -0
  7. package/dist/interface/assets/Adminpanel-D1ycltxf.js +1 -0
  8. package/dist/interface/assets/Appearance-Jlzp_P21.js +1 -0
  9. package/dist/interface/assets/Backup-1-ju9NDo.js +1 -0
  10. package/dist/interface/assets/Camera-BOu5dUel.js +1 -0
  11. package/dist/interface/assets/Cameras-C7eUXdZk.js +1 -0
  12. package/dist/interface/assets/Cameras-tmTzi1M6.css +1 -0
  13. package/dist/interface/assets/Camview-CEgwGCGR.js +1 -0
  14. package/dist/interface/assets/{Camview-vUAs5YHU.css → Camview-CWTrsoY0.css} +1 -1
  15. package/dist/interface/assets/Config-Dt-etQ3h.js +1 -0
  16. package/dist/interface/assets/{Console-Caz7y-T0.js → Console-FCve5CKy.js} +2 -2
  17. package/dist/interface/assets/FirstSteps-DLkKDSe9.js +1 -0
  18. package/dist/interface/assets/{NewCamera-B9t-0NCc.js → NewCamera-Cc1X79Ns.js} +2 -2
  19. package/dist/interface/assets/Plugin-CnQjafMC.js +1 -0
  20. package/dist/interface/assets/{Plugin-BSHKKjrl.css → Plugin-DzKKCoqQ.css} +1 -1
  21. package/dist/interface/assets/Plugins-B8gCgxOx.css +1 -0
  22. package/dist/interface/assets/Plugins-CwyUdMlv.js +1 -0
  23. package/dist/interface/assets/Recordings-Boeev1lV.js +1 -0
  24. package/dist/interface/assets/Recordings-D5ta7AYS.js +1 -0
  25. package/dist/interface/assets/Settings-Cvm2jnBr.js +1 -0
  26. package/dist/interface/assets/System-fHQ7XKri.js +1 -0
  27. package/dist/interface/assets/User-5o1VKizc.js +1 -0
  28. package/dist/interface/assets/VConfigEditor.vue_vue_type_script_setup_true_lang-C_95ELTZ.js +2 -0
  29. package/dist/interface/assets/VConsole-BHy92Ws0.js +1 -0
  30. package/dist/interface/assets/VConsole-MV9pQtJj.css +1 -0
  31. package/dist/interface/assets/{VPlayer-YdRn97Bs.js → VPlayer-LX5HGLrY.js} +1 -1
  32. package/dist/interface/assets/{VPluginCard--3bx6UJb.js → VPluginCard-CFpg0LM4.js} +2 -2
  33. package/dist/interface/assets/VPluginCard-Fl0AYmnF.css +1 -0
  34. package/dist/interface/assets/main-BCWSiwnj.js +9 -0
  35. package/dist/interface/assets/{main-B3IVLctZ.css → main-CQNVVncO.css} +1 -1
  36. package/dist/interface/assets/{pinia-D8MtiGcH.js → pinia-CitQ5b66.js} +2 -2
  37. package/dist/interface/assets/{plugins-Bf03y242.js → plugins-D80RNVmI.js} +1 -1
  38. package/dist/interface/assets/qrcode-SHonoxyK.js +8 -0
  39. package/dist/interface/assets/{system-BONnDA4y.js → system-CS_ZOs3_.js} +1 -1
  40. package/dist/interface/assets/{ui-CNpIJotI.js → ui-CHKoHLl-.js} +1 -1
  41. package/dist/interface/assets/{v-calendar-uh0aTGqP.js → v-calendar-C-8W4FeM.js} +1 -1
  42. package/dist/interface/assets/{vee-validate-D3FqbChK.js → vee-validate-Ck3I2guh.js} +1 -1
  43. package/dist/interface/assets/{vue-i18n-1AU8MPys.js → vue-i18n-DuCDz9TJ.js} +1 -1
  44. package/dist/interface/assets/{vue-inline-svg-2DDwYW6V.js → vue-inline-svg-C2gR6nRD.js} +1 -1
  45. package/dist/interface/assets/{vue-router-DfeQ8s4I.js → vue-router-OPGDMnws.js} +1 -1
  46. package/dist/interface/assets/{vue3-dnd-BwxcSU9Z.js → vue3-dnd-Hf295yge.js} +1 -1
  47. package/dist/interface/assets/{vue3-toastify-Ul-rf53I.js → vue3-toastify-DQr2dOCx.js} +1 -1
  48. package/dist/interface/assets/vuetify-CrcT8VHB.js +5 -0
  49. package/dist/interface/index.html +14 -15
  50. package/dist/interface/sw.js +1 -1
  51. package/dist/server/bin/cui-service.d.ts +1 -0
  52. package/dist/server/bin/cui-service.js +41 -9
  53. package/dist/server/bin/cui-service.js.map +1 -1
  54. package/dist/server/package.json +8 -7
  55. package/dist/server/requirements.txt +2 -3
  56. package/dist/server/src/api/controllers/cameras.controller.js +2 -2
  57. package/dist/server/src/api/controllers/cameras.controller.js.map +1 -1
  58. package/dist/server/src/api/controllers/plugins.controller.js +7 -6
  59. package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
  60. package/dist/server/src/api/go2rtc/api/streams.d.ts +4 -4
  61. package/dist/server/src/api/go2rtc/api/streams.js +2 -24
  62. package/dist/server/src/api/go2rtc/api/streams.js.map +1 -1
  63. package/dist/server/src/api/go2rtc/types.d.ts +6 -2
  64. package/dist/server/src/api/schemas/go2rtc.schema.d.ts +5 -5
  65. package/dist/server/src/api/services/cameras.service.d.ts +6 -5
  66. package/dist/server/src/api/services/cameras.service.js +72 -59
  67. package/dist/server/src/api/services/cameras.service.js.map +1 -1
  68. package/dist/server/src/api/services/plugins.service.js +11 -13
  69. package/dist/server/src/api/services/plugins.service.js.map +1 -1
  70. package/dist/server/src/api.d.ts +2 -2
  71. package/dist/server/src/camera/controller.d.ts +9 -4
  72. package/dist/server/src/camera/controller.js +21 -7
  73. package/dist/server/src/camera/controller.js.map +1 -1
  74. package/dist/server/src/camera/device.d.ts +15 -3
  75. package/dist/server/src/camera/device.js.map +1 -1
  76. package/dist/server/src/camera/index.d.ts +18 -39
  77. package/dist/server/src/camera/index.js +137 -165
  78. package/dist/server/src/camera/index.js.map +1 -1
  79. package/dist/server/src/camera/interfaces/camera.d.ts +0 -1
  80. package/dist/server/src/camera/interfaces/camera.js +0 -8
  81. package/dist/server/src/camera/interfaces/camera.js.map +1 -1
  82. package/dist/server/src/camera/streaming/werift-session.d.ts +10 -1
  83. package/dist/server/src/camera/streaming/werift-session.js +16 -1
  84. package/dist/server/src/camera/streaming/werift-session.js.map +1 -1
  85. package/dist/server/src/camera/types.d.ts +0 -1
  86. package/dist/server/src/camera/types.js.map +1 -1
  87. package/dist/server/src/camera/videoFrame.d.ts +3 -3
  88. package/dist/server/src/camera/videoFrame.js +6 -7
  89. package/dist/server/src/camera/videoFrame.js.map +1 -1
  90. package/dist/server/src/decoder/types.d.ts +4 -9
  91. package/dist/server/src/decoder/worker.d.ts +3 -5
  92. package/dist/server/src/decoder/worker.js +40 -64
  93. package/dist/server/src/decoder/worker.js.map +1 -1
  94. package/dist/server/src/go2rtc/index.js +1 -1
  95. package/dist/server/src/go2rtc/index.js.map +1 -1
  96. package/dist/server/src/index.d.ts +3 -3
  97. package/dist/server/src/main.js +1 -2
  98. package/dist/server/src/main.js.map +1 -1
  99. package/dist/server/src/nats/connection.d.ts +17 -0
  100. package/dist/server/src/nats/connection.js +66 -0
  101. package/dist/server/src/nats/connection.js.map +1 -0
  102. package/dist/server/src/nats/error.d.ts +9 -0
  103. package/dist/server/src/nats/error.js +11 -0
  104. package/dist/server/src/nats/error.js.map +1 -0
  105. package/dist/server/src/nats/index.d.ts +6 -4
  106. package/dist/server/src/nats/index.js +22 -17
  107. package/dist/server/src/nats/index.js.map +1 -1
  108. package/dist/server/src/nats/messageQueue.d.ts +7 -4
  109. package/dist/server/src/nats/messageQueue.js +43 -59
  110. package/dist/server/src/nats/messageQueue.js.map +1 -1
  111. package/dist/server/src/nats/proxy/cameraDevice.js +19 -24
  112. package/dist/server/src/nats/proxy/cameraDevice.js.map +1 -1
  113. package/dist/server/src/nats/proxy/deviceManager.d.ts +2 -2
  114. package/dist/server/src/nats/proxy/deviceManager.js +4 -14
  115. package/dist/server/src/nats/proxy/deviceManager.js.map +1 -1
  116. package/dist/server/src/nats/server.js +4 -10
  117. package/dist/server/src/nats/server.js.map +1 -1
  118. package/dist/server/src/nats/subscription.d.ts +12 -0
  119. package/dist/server/src/nats/subscription.js +21 -0
  120. package/dist/server/src/nats/subscription.js.map +1 -0
  121. package/dist/server/src/nats/types.d.ts +25 -40
  122. package/dist/server/src/nats/types.js +1 -10
  123. package/dist/server/src/nats/types.js.map +1 -1
  124. package/dist/server/src/nats/utils.d.ts +2 -4
  125. package/dist/server/src/nats/utils.js +3 -3
  126. package/dist/server/src/nats/utils.js.map +1 -1
  127. package/dist/server/src/plugins/index.d.ts +3 -5
  128. package/dist/server/src/plugins/index.js +54 -141
  129. package/dist/server/src/plugins/index.js.map +1 -1
  130. package/dist/server/src/plugins/plugin.d.ts +4 -13
  131. package/dist/server/src/plugins/plugin.js +40 -90
  132. package/dist/server/src/plugins/plugin.js.map +1 -1
  133. package/dist/server/src/plugins/types.d.ts +4 -0
  134. package/dist/server/src/plugins/types.js.map +1 -1
  135. package/dist/server/src/plugins/worker.d.ts +1 -1
  136. package/dist/server/src/plugins/worker.js +52 -66
  137. package/dist/server/src/plugins/worker.js.map +1 -1
  138. package/dist/server/src/polyglot/node/decoder/child.js +87 -159
  139. package/dist/server/src/polyglot/node/decoder/child.js.map +1 -1
  140. package/dist/server/src/polyglot/node/decoder/imageUtils.d.ts +1 -1
  141. package/dist/server/src/polyglot/node/plugins/cameraStorage.d.ts +2 -2
  142. package/dist/server/src/polyglot/node/plugins/cameraStorage.js.map +1 -1
  143. package/dist/server/src/polyglot/node/plugins/child.d.ts +1 -1
  144. package/dist/server/src/polyglot/node/plugins/child.js +34 -60
  145. package/dist/server/src/polyglot/node/plugins/child.js.map +1 -1
  146. package/dist/server/src/polyglot/node/plugins/{config.js → configService.js} +1 -1
  147. package/dist/server/src/polyglot/node/plugins/configService.js.map +1 -0
  148. package/dist/server/src/polyglot/node/plugins/{api.d.ts → pluginApi.d.ts} +9 -12
  149. package/dist/server/src/polyglot/node/plugins/pluginApi.js +34 -0
  150. package/dist/server/src/polyglot/node/plugins/pluginApi.js.map +1 -0
  151. package/dist/server/src/polyglot/node/plugins/{logger.d.ts → pluginLogger.d.ts} +2 -0
  152. package/dist/server/src/polyglot/node/plugins/pluginLogger.js +89 -0
  153. package/dist/server/src/polyglot/node/plugins/pluginLogger.js.map +1 -0
  154. package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.d.ts +8 -11
  155. package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js +67 -129
  156. package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js.map +1 -1
  157. package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.d.ts +6 -8
  158. package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.js +15 -43
  159. package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.js.map +1 -1
  160. package/dist/server/src/polyglot/node/plugins/storageController.d.ts +2 -2
  161. package/dist/server/src/polyglot/node/plugins/storageController.js.map +1 -1
  162. package/dist/server/src/polyglot/python/camera/interfaces/camera.py +0 -6
  163. package/dist/server/src/polyglot/python/camera/video_frame.py +10 -18
  164. package/dist/server/src/polyglot/python/camera_ui_types/__init__.py +1 -5
  165. package/dist/server/src/polyglot/python/decoder/child.py +102 -161
  166. package/dist/server/src/polyglot/python/plugins/camera_storage.py +10 -23
  167. package/dist/server/src/polyglot/python/plugins/child.py +35 -60
  168. package/dist/server/src/polyglot/python/plugins/{proxy/message_queue.py → message_queue.py} +50 -81
  169. package/dist/server/src/polyglot/python/plugins/plugin_api.py +13 -21
  170. package/dist/server/src/polyglot/python/plugins/proxy/camera_device.py +90 -173
  171. package/dist/server/src/polyglot/python/plugins/proxy/device_manager.py +25 -64
  172. package/dist/server/src/polyglot/python/plugins/storage_controller.py +3 -4
  173. package/dist/server/src/polyglot/python/utilities/connection.py +86 -0
  174. package/dist/server/src/polyglot/python/utilities/object_path.py +12 -4
  175. package/dist/server/src/polyglot/python/utilities/subscriptions.py +20 -0
  176. package/dist/server/src/polyglot/python/utilities/task.py +11 -1
  177. package/dist/server/src/services/config/index.js +4 -2
  178. package/dist/server/src/services/config/index.js.map +1 -1
  179. package/dist/server/src/services/logger/index.js +11 -8
  180. package/dist/server/src/services/logger/index.js.map +1 -1
  181. package/dist/server/src/utils/ffmpeg.d.ts +2 -0
  182. package/dist/server/src/{decoder → utils}/ffmpeg.js +2 -2
  183. package/dist/server/src/utils/ffmpeg.js.map +1 -0
  184. package/dist/server/src/utils/pythonInstaller.d.ts +1 -1
  185. package/dist/server/src/utils/pythonInstaller.js +10 -4
  186. package/dist/server/src/utils/pythonInstaller.js.map +1 -1
  187. package/dist/server/src/utils/reader.js.map +1 -0
  188. package/dist/server/src/utils/subscribed.d.ts +4 -4
  189. package/dist/server/src/utils/subscribed.js.map +1 -1
  190. package/package.json +8 -7
  191. package/dist/interface/assets/@camera.ui-2NVnv26v.js +0 -8
  192. package/dist/interface/assets/Account-gJpkf0nE.js +0 -1
  193. package/dist/interface/assets/Adminpanel-Bge9nu5N.js +0 -1
  194. package/dist/interface/assets/Appearance-D22q-X_I.js +0 -1
  195. package/dist/interface/assets/Backup-pJm6s10G.js +0 -1
  196. package/dist/interface/assets/Camera-BgO2yRjb.js +0 -1
  197. package/dist/interface/assets/Cameras-BM3vSM_R.css +0 -1
  198. package/dist/interface/assets/Cameras-DjeKruR_.js +0 -1
  199. package/dist/interface/assets/Camview-DfzlprzN.js +0 -1
  200. package/dist/interface/assets/Config-BKIOIkjC.js +0 -1
  201. package/dist/interface/assets/FirstSteps-mQK4XFTs.js +0 -1
  202. package/dist/interface/assets/Plugin-Di_bBsg-.js +0 -1
  203. package/dist/interface/assets/Plugins-BsMITags.css +0 -1
  204. package/dist/interface/assets/Plugins-DhmzMNuO.js +0 -1
  205. package/dist/interface/assets/Recordings-Bu53bSBp.js +0 -1
  206. package/dist/interface/assets/Recordings-XY20w8yp.js +0 -1
  207. package/dist/interface/assets/Settings-gGRBRVST.js +0 -1
  208. package/dist/interface/assets/System-ZDrcLNk0.js +0 -1
  209. package/dist/interface/assets/User-D4vEhhzi.js +0 -1
  210. package/dist/interface/assets/VConfigEditor.vue_vue_type_script_setup_true_lang-CXFI-IeE.js +0 -2
  211. package/dist/interface/assets/VConsole-BHo3xprq.js +0 -1
  212. package/dist/interface/assets/VConsole-f-nUkOuD.css +0 -1
  213. package/dist/interface/assets/VPluginCard-BJYMuCLk.css +0 -1
  214. package/dist/interface/assets/encode-utf8-Cn5aGd7v.js +0 -1
  215. package/dist/interface/assets/main-C4rYiRNz.js +0 -2
  216. package/dist/interface/assets/qrcode-CGiDONbL.js +0 -8
  217. package/dist/interface/assets/vuetify-_-Oqac3B.js +0 -5
  218. package/dist/server/src/decoder/ffmpeg.d.ts +0 -2
  219. package/dist/server/src/decoder/ffmpeg.js.map +0 -1
  220. package/dist/server/src/nats/proxy/index.d.ts +0 -2
  221. package/dist/server/src/nats/proxy/index.js +0 -3
  222. package/dist/server/src/nats/proxy/index.js.map +0 -1
  223. package/dist/server/src/polyglot/node/decoder/reader.js.map +0 -1
  224. package/dist/server/src/polyglot/node/plugins/api.js +0 -34
  225. package/dist/server/src/polyglot/node/plugins/api.js.map +0 -1
  226. package/dist/server/src/polyglot/node/plugins/config.js.map +0 -1
  227. package/dist/server/src/polyglot/node/plugins/logger.js +0 -128
  228. package/dist/server/src/polyglot/node/plugins/logger.js.map +0 -1
  229. package/dist/server/src/polyglot/node/plugins/proxy/index.d.ts +0 -2
  230. package/dist/server/src/polyglot/node/plugins/proxy/index.js +0 -3
  231. package/dist/server/src/polyglot/node/plugins/proxy/index.js.map +0 -1
  232. package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.d.ts +0 -20
  233. package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.js +0 -152
  234. package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.js.map +0 -1
  235. /package/dist/server/src/polyglot/node/plugins/{config.d.ts → configService.d.ts} +0 -0
  236. /package/dist/server/src/polyglot/python/plugins/{logger.py → plugin_logger.py} +0 -0
  237. /package/dist/server/src/{polyglot/node/decoder → utils}/reader.d.ts +0 -0
  238. /package/dist/server/src/{polyglot/node/decoder → utils}/reader.js +0 -0
@@ -9,7 +9,6 @@ from typing import Any, Optional, Union, cast
9
9
  from uuid import uuid4
10
10
 
11
11
  import aiohttp
12
- import nats
13
12
  from cachetools import LRUCache, cached
14
13
  from camera.polygon import are_motion_detections_valid, are_object_detections_valid
15
14
  from camera.video_frame import MotionFrame, VideoFrame
@@ -55,13 +54,12 @@ from camera_ui_types import (
55
54
  StateNames,
56
55
  StateValue,
57
56
  )
58
- from decoder.typings import PingMessage, PongMessage, SignalingRequest, SignalingResponse
57
+ from decoder.typings import AuthConfig, PingMessage, PongMessage, SignalingRequest, SignalingResponse
59
58
  from deepdiff import DeepDiff
60
- from logger import PluginLogger
61
- from nats.aio.client import Client as NatsConnection
59
+ from message_queue import MessageQueue
62
60
  from nats.aio.msg import Msg
63
- from nats.aio.subscription import Subscription
64
61
  from plugin_api import PluginAPI
62
+ from plugin_logger import PluginLogger
65
63
  from reactivex import Observable
66
64
  from reactivex import operators as ops
67
65
  from reactivex.subject.behaviorsubject import BehaviorSubject
@@ -74,11 +72,11 @@ from typings import (
74
72
  PluginInfo,
75
73
  ProxyMessageStructure,
76
74
  )
75
+ from utilities.connection import ProxyConnection
77
76
  from utilities.packer import pack, unpack
77
+ from utilities.subscriptions import ProxySubscription
78
78
  from utilities.task import TaskSet
79
79
 
80
- from .message_queue import ClientMessageQueue
81
-
82
80
 
83
81
  class CameraSource:
84
82
  def __init__(self, source: CameraInput, parent: Any):
@@ -110,7 +108,7 @@ class CameraDeviceProxy:
110
108
  camera: Camera,
111
109
  plugin: PluginInfo,
112
110
  proxy_endpoints: list[str],
113
- auth: dict[str, str],
111
+ auth: AuthConfig,
114
112
  ):
115
113
  self.snapshot_cache = LRUCache(maxsize=100)
116
114
  self.camera_subject = BehaviorSubject(camera)
@@ -172,8 +170,8 @@ class CameraDeviceProxy:
172
170
  from camera.interfaces.ptz import CameraPTZInterface
173
171
 
174
172
  self.cameraDelegate = CameraInterface(self, logger)
175
- self.prebufferDelegate = CameraPrebufferInterface(self, logger)
176
173
  self.ptzDelegate = CameraPTZInterface(self, logger)
174
+ self.prebufferDelegate = CameraPrebufferInterface(self, logger)
177
175
 
178
176
  self.subject = f"{self.plugin['id']}.camera.{self.id}"
179
177
  self.camera_subscriber_subject = f"{self.id}.camera"
@@ -183,21 +181,21 @@ class CameraDeviceProxy:
183
181
  self.signaling_subject = f"{self.plugin['id']}.camera.{self.id}.signaling"
184
182
  self.signaling_target_subject = f"{self.id}.frameGenerator.signaling"
185
183
 
186
- self.publisher: Optional[NatsConnection] = None
187
- self.camera_publisher: Optional[NatsConnection] = None
188
- self.frame_publisher: Optional[NatsConnection] = None
189
- self.motion_frame_publisher: Optional[NatsConnection] = None
190
- self.signaling_publisher: Optional[NatsConnection] = None
184
+ self.publisher: Optional[ProxyConnection] = None
185
+ self.camera_publisher: Optional[ProxyConnection] = None
186
+ self.frame_publisher: Optional[ProxyConnection] = None
187
+ self.motion_frame_publisher: Optional[ProxyConnection] = None
188
+ self.signaling_publisher: Optional[ProxyConnection] = None
191
189
 
192
- self.subscriber: Optional[Subscription] = None
193
- self.camera_subscriber: Optional[Subscription] = None
194
- self.camera_plugin_subscriber: Optional[Subscription] = None
195
- self.signaling_subscriber: Optional[Subscription] = None
196
- self.frame_subscriber: Optional[Subscription] = None
197
- self.motion_frame_subscriber: Optional[Subscription] = None
190
+ self.subscriber: Optional[ProxySubscription] = None
191
+ self.camera_subscriber: Optional[ProxySubscription] = None
192
+ self.camera_plugin_subscriber: Optional[ProxySubscription] = None
193
+ self.signaling_subscriber: Optional[ProxySubscription] = None
194
+ self.frame_subscriber: Optional[ProxySubscription] = None
195
+ self.motion_frame_subscriber: Optional[ProxySubscription] = None
198
196
 
199
197
  self.tasks: TaskSet = TaskSet(f"{self.plugin['name']} - {self.name} - CameraDeviceProxy")
200
- self.message_queue: Optional[ClientMessageQueue] = None
198
+ self.message_queue: Optional[MessageQueue] = None
201
199
  self.active_requests: set[str] = set()
202
200
  self.active_motion_requests = 0
203
201
 
@@ -321,98 +319,53 @@ class CameraDeviceProxy:
321
319
  def low_resolution_source(self) -> Optional[CameraSource]:
322
320
  return next(source for source in self.sources if "low-resolution" in source.roles)
323
321
 
322
+ @property
323
+ def ptz(self) -> CameraPTZDelegate:
324
+ return self.ptzDelegate
325
+
324
326
  async def init(self):
325
327
  if self.initialized:
326
328
  return
327
329
 
328
330
  self.initialized = True
329
331
 
330
- async def ignore_cb(e: Optional[Any] = None):
331
- pass
332
+ self.publisher = ProxyConnection(self.subject, self.proxy_endpoints, self.auth)
333
+ await self.publisher.connect()
332
334
 
333
- self.publisher = await nats.connect(
334
- servers=[endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")],
335
- name=self.subject,
336
- user=self.auth["user"],
337
- password=self.auth["pass"],
338
- max_reconnect_attempts=-1,
339
- error_cb=ignore_cb,
340
- disconnected_cb=ignore_cb,
341
- closed_cb=ignore_cb,
342
- reconnected_cb=ignore_cb,
343
- discovered_server_cb=ignore_cb,
335
+ self.camera_publisher = ProxyConnection(
336
+ self.camera_subscriber_subject, self.proxy_endpoints, self.auth
344
337
  )
338
+ await self.camera_publisher.connect()
345
339
 
346
- self.camera_publisher = await nats.connect(
347
- servers=[endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")],
348
- name=self.camera_subscriber_subject,
349
- user=self.auth["user"],
350
- password=self.auth["pass"],
351
- max_reconnect_attempts=-1,
352
- error_cb=ignore_cb,
353
- disconnected_cb=ignore_cb,
354
- closed_cb=ignore_cb,
355
- reconnected_cb=ignore_cb,
356
- discovered_server_cb=ignore_cb,
357
- )
340
+ self.signaling_publisher = ProxyConnection(self.signaling_subject, self.proxy_endpoints, self.auth)
341
+ await self.signaling_publisher.connect()
358
342
 
359
- self.signaling_publisher = await nats.connect(
360
- servers=[endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")],
361
- name=self.signaling_subject,
362
- user=self.auth["user"],
363
- password=self.auth["pass"],
364
- max_reconnect_attempts=-1,
365
- error_cb=ignore_cb,
366
- disconnected_cb=ignore_cb,
367
- closed_cb=ignore_cb,
368
- reconnected_cb=ignore_cb,
369
- discovered_server_cb=ignore_cb,
370
- )
343
+ self.frame_publisher = ProxyConnection(self.frame_subject, self.proxy_endpoints, self.auth)
344
+ await self.frame_publisher.connect()
371
345
 
372
- self.frame_publisher = await nats.connect(
373
- servers=[endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")],
374
- name=self.frame_subject,
375
- user=self.auth["user"],
376
- password=self.auth["pass"],
377
- max_reconnect_attempts=-1,
378
- error_cb=ignore_cb,
379
- disconnected_cb=ignore_cb,
380
- closed_cb=ignore_cb,
381
- reconnected_cb=ignore_cb,
382
- discovered_server_cb=ignore_cb,
383
- )
384
-
385
- self.motion_frame_publisher = await nats.connect(
386
- servers=[endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")],
387
- name=self.motion_frame_subject,
388
- user=self.auth["user"],
389
- password=self.auth["pass"],
390
- max_reconnect_attempts=-1,
391
- error_cb=ignore_cb,
392
- disconnected_cb=ignore_cb,
393
- closed_cb=ignore_cb,
394
- reconnected_cb=ignore_cb,
395
- discovered_server_cb=ignore_cb,
346
+ self.motion_frame_publisher = ProxyConnection(
347
+ self.motion_frame_subject, self.proxy_endpoints, self.auth
396
348
  )
349
+ await self.motion_frame_publisher.connect()
397
350
 
398
351
  self.subscriber = await self.publisher.subscribe(subject=self.subject)
399
- self.signaling_subscriber = await self.signaling_publisher.subscribe(subject=self.signaling_subject)
400
- self.camera_subscriber = await self.camera_publisher.subscribe(subject=self.camera_subscriber_subject)
401
- self.camera_plugin_subscriber = await self.camera_publisher.subscribe(
402
- subject=self.camera_plugin_subscriber_subject
403
- )
404
-
405
- self.message_queue = ClientMessageQueue(
352
+ self.message_queue = MessageQueue(
406
353
  self.logger,
407
354
  self.publisher,
408
355
  self.subscriber,
409
356
  self.__request_handler,
410
357
  )
411
358
 
412
- self.tasks.add(self.message_queue.start())
413
- self.tasks.add(self.__listen_to_messages(self.camera_subscriber))
414
- self.tasks.add(self.__listen_to_messages(self.camera_plugin_subscriber))
415
- self.tasks.add(self.__listen_to_signaling_messages())
359
+ self.signaling_subscriber = await self.signaling_publisher.subscribe(subject=self.signaling_subject)
360
+ self.signaling_subscriber.on("message", self.__on_signaling_message)
361
+
362
+ self.camera_subscriber = await self.camera_publisher.subscribe(subject=self.camera_subscriber_subject)
363
+ self.camera_subscriber.on("message", self.__on_proxy_message)
364
+
365
+ self.camera_plugin_subscriber = await self.camera_publisher.subscribe(
366
+ subject=self.camera_plugin_subscriber_subject
367
+ )
368
+ self.camera_plugin_subscriber.on("message", self.__on_proxy_message)
416
369
 
417
370
  await self.refresh_states()
418
371
 
@@ -483,7 +436,7 @@ class CameraDeviceProxy:
483
436
  if not self.frame_subscriber:
484
437
  self.frame_subscriber = await self.frame_publisher.subscribe(self.frame_subject)
485
438
 
486
- async for msg in self.frame_subscriber.messages:
439
+ async for msg in self.frame_subscriber.subscriber.messages:
487
440
  try:
488
441
  if (
489
442
  not self.initialized
@@ -524,7 +477,7 @@ class CameraDeviceProxy:
524
477
  self.motion_frame_subject
525
478
  )
526
479
 
527
- async for msg in self.motion_frame_subscriber.messages:
480
+ async for msg in self.motion_frame_subscriber.subscriber.messages:
528
481
  try:
529
482
  if not self.initialized or self.active_motion_requests <= 0:
530
483
  break
@@ -885,10 +838,7 @@ class CameraDeviceProxy:
885
838
  if not self.frame_publisher:
886
839
  return
887
840
 
888
- await self.frame_publisher.publish(
889
- self.motion_frame_subject,
890
- pack(frame),
891
- )
841
+ await self.frame_publisher.publish(self.motion_frame_subject, frame)
892
842
 
893
843
  @overload
894
844
  def __check_state_internal(
@@ -1454,10 +1404,7 @@ class CameraDeviceProxy:
1454
1404
  "pluginId": self.plugin["id"],
1455
1405
  }
1456
1406
 
1457
- await self.signaling_publisher.publish(
1458
- self.signaling_target_subject,
1459
- pack(message),
1460
- )
1407
+ await self.signaling_publisher.publish(self.signaling_target_subject, message)
1461
1408
 
1462
1409
  self.active_requests.add(request_id)
1463
1410
 
@@ -1480,13 +1427,12 @@ class CameraDeviceProxy:
1480
1427
  "pluginId": self.plugin["id"],
1481
1428
  }
1482
1429
 
1483
- metadata_msg = await self.signaling_publisher.request(
1430
+ metadata_response: SignalingResponse = await self.signaling_publisher.request(
1484
1431
  self.signaling_target_subject,
1485
- pack(metadata_request),
1432
+ metadata_request,
1486
1433
  timeout=timeout,
1487
1434
  )
1488
1435
 
1489
- metadata_response: SignalingResponse = unpack(metadata_msg.data)
1490
1436
  metadata = metadata_response.get("metadata")
1491
1437
 
1492
1438
  return metadata
@@ -1500,9 +1446,6 @@ class CameraDeviceProxy:
1500
1446
  if not self.signaling_publisher:
1501
1447
  raise Exception("Signaling Publisher not initialized")
1502
1448
 
1503
- if self.signaling_publisher.is_closed:
1504
- return
1505
-
1506
1449
  message: SignalingRequest = {
1507
1450
  "type": "disconnect",
1508
1451
  "requestId": request_id,
@@ -1510,18 +1453,18 @@ class CameraDeviceProxy:
1510
1453
  "pluginId": self.plugin["id"],
1511
1454
  }
1512
1455
 
1513
- await self.signaling_publisher.publish(self.signaling_target_subject, pack(message))
1456
+ await self.signaling_publisher.publish(self.signaling_target_subject, message)
1514
1457
 
1515
1458
  async def __close_frame_subscriber(self) -> None:
1516
1459
  with suppress(Exception):
1517
1460
  if self.frame_subscriber:
1518
- await self.frame_subscriber.unsubscribe()
1461
+ await self.frame_subscriber.close()
1519
1462
  self.frame_subscriber = None
1520
1463
 
1521
1464
  async def __close_motion_frame_subscriber(self) -> None:
1522
1465
  if self.motion_frame_subscriber:
1523
1466
  with suppress(Exception):
1524
- await self.motion_frame_subscriber.unsubscribe()
1467
+ await self.motion_frame_subscriber.close()
1525
1468
 
1526
1469
  self.motion_frame_subscriber = None
1527
1470
 
@@ -1581,74 +1524,48 @@ class CameraDeviceProxy:
1581
1524
 
1582
1525
  await self.message_queue.enqueue({**message, "type": "reply", "error": deserialized_error})
1583
1526
 
1584
- async def __listen_to_messages(self, camera_subscriber: Subscription) -> None:
1585
- async for msg in camera_subscriber.messages:
1586
- try:
1587
- if not self.initialized:
1588
- break
1589
-
1590
- if len(msg.data) == 0:
1591
- continue
1592
-
1593
- message = unpack(msg.data)
1594
-
1595
- if "type" in message:
1596
- type = message["type"]
1597
- if type == "removed":
1598
- await self.cleanup()
1599
- elif type == "updated":
1600
- self.update_camera(message["data"])
1601
- elif type == "cameraState":
1602
- self.update_camera_state(message["data"])
1603
- elif type == "prebufferState":
1604
- self.update_prebuffer(
1605
- message["data"]["sourceId"],
1606
- message["data"]["container"],
1607
- message["data"]["state"],
1608
- )
1609
-
1610
- continue
1611
-
1612
- state_name = message["stateName"]
1613
- new_data = message["data"]["newEvent"]
1614
-
1615
- self.__update_state_internal(state_name, new_data, True)
1616
-
1617
- except Exception as e:
1618
- if self.initialized:
1619
- self.logger.error("Error while processing camera device message:", e)
1620
- else:
1621
- break
1527
+ async def __on_proxy_message(self, msg: Msg) -> None:
1528
+ if not self.initialized:
1529
+ return
1622
1530
 
1623
- async def __listen_to_signaling_messages(self) -> None:
1624
- if not self.signaling_subscriber:
1625
- raise Exception("Subscriber not initialized")
1531
+ message = unpack(msg.data)
1532
+
1533
+ if "type" in message:
1534
+ type = message["type"]
1535
+ if type == "removed":
1536
+ await self.cleanup()
1537
+ elif type == "updated":
1538
+ self.update_camera(message["data"])
1539
+ elif type == "cameraState":
1540
+ self.update_camera_state(message["data"])
1541
+ elif type == "prebufferState":
1542
+ self.update_prebuffer(
1543
+ message["data"]["sourceId"],
1544
+ message["data"]["container"],
1545
+ message["data"]["state"],
1546
+ )
1547
+ else:
1548
+ state_name = message["stateName"]
1549
+ new_data = message["data"]["newEvent"]
1626
1550
 
1627
- async for msg in self.signaling_subscriber.messages:
1628
- try:
1629
- if not self.initialized:
1630
- break
1551
+ self.__update_state_internal(state_name, new_data, True)
1631
1552
 
1632
- if len(msg.data) == 0:
1633
- continue
1553
+ async def __on_signaling_message(self, msg: Msg) -> None:
1554
+ if not self.initialized:
1555
+ return
1634
1556
 
1635
- message: Union[SignalingResponse, PingMessage] = unpack(msg.data)
1557
+ message: Union[SignalingResponse, PingMessage] = unpack(msg.data)
1636
1558
 
1637
- if message["type"] == "ping":
1638
- if message["requestId"] in self.active_requests:
1639
- self.tasks.add(self.__respond_to_signaling_message(msg, message))
1559
+ if message["type"] == "ping":
1560
+ if message["requestId"] in self.active_requests:
1561
+ self.tasks.add(self.__respond_to_signaling_message(msg, message))
1640
1562
 
1641
- elif message["type"] == "disconnect":
1642
- if message["requestId"] in self.active_requests:
1643
- self.active_requests.remove(message["requestId"])
1563
+ elif message["type"] == "disconnect":
1564
+ if message["requestId"] in self.active_requests:
1565
+ self.active_requests.remove(message["requestId"])
1644
1566
 
1645
- if len(self.active_requests) == 0:
1646
- self.tasks.add(self.__close_frame_subscriber())
1647
- except Exception as e:
1648
- if self.initialized:
1649
- self.logger.error("Error while processing ping/pong message:", e)
1650
- else:
1651
- break
1567
+ if len(self.active_requests) == 0:
1568
+ self.tasks.add(self.__close_frame_subscriber())
1652
1569
 
1653
1570
  async def __respond_to_signaling_message(self, msg: Msg, message: PingMessage) -> None:
1654
1571
  try:
@@ -3,20 +3,20 @@ from datetime import datetime
3
3
  from typing import Any, Optional, Union, cast
4
4
  from uuid import uuid4
5
5
 
6
- import nats
7
6
  from camera_ui_types import Camera, CameraConfig
8
- from logger import PluginLogger
9
- from nats.aio.client import Client as NatsConnection
7
+ from decoder.typings import AuthConfig
8
+ from message_queue import MessageQueue
10
9
  from nats.aio.msg import Msg
11
- from nats.aio.subscription import Subscription
12
10
  from plugin_api import PluginAPI
11
+ from plugin_logger import PluginLogger
13
12
  from pyeecui.asyncio import AsyncIOEventEmitter
14
13
  from typings import PluginInfo, ProxyMessageStructure
14
+ from utilities.connection import ProxyConnection
15
15
  from utilities.packer import unpack
16
+ from utilities.subscriptions import ProxySubscription
16
17
  from utilities.task import TaskSet
17
18
 
18
19
  from .camera_device import CameraDeviceProxy
19
- from .message_queue import ClientMessageQueue
20
20
 
21
21
 
22
22
  class DeviceManager(AsyncIOEventEmitter):
@@ -26,7 +26,7 @@ class DeviceManager(AsyncIOEventEmitter):
26
26
  logger: PluginLogger,
27
27
  plugin: PluginInfo,
28
28
  proxy_endpoints: list[str],
29
- auth: dict[str, str],
29
+ auth: AuthConfig,
30
30
  ):
31
31
  super().__init__()
32
32
 
@@ -44,14 +44,14 @@ class DeviceManager(AsyncIOEventEmitter):
44
44
  self.subject = f"{self.plugin['id']}.deviceManager"
45
45
  self.dm_subject = f"{self.plugin['id']}.deviceManager.subscriber"
46
46
 
47
- self.publisher: Optional[NatsConnection] = None
48
- self.dm_publisher: Optional[NatsConnection] = None
47
+ self.publisher: Optional[ProxyConnection] = None
48
+ self.dm_publisher: Optional[ProxyConnection] = None
49
49
 
50
- self.subscriber: Optional[Subscription] = None
51
- self.dm_subscriber: Optional[Subscription] = None
50
+ self.subscriber: Optional[ProxySubscription] = None
51
+ self.dm_subscriber: Optional[ProxySubscription] = None
52
52
 
53
53
  self.tasks: TaskSet = TaskSet(f"{self.plugin['name']} DeviceManager")
54
- self.message_queue: Optional[ClientMessageQueue] = None
54
+ self.message_queue: Optional[MessageQueue] = None
55
55
 
56
56
  # print("DeviceManager", self.plugin["name"], self.dealer_id, self.subscriber_ids)
57
57
 
@@ -63,47 +63,24 @@ class DeviceManager(AsyncIOEventEmitter):
63
63
 
64
64
  self.initialized = True
65
65
 
66
- async def ignore_cb(e: Optional[Any] = None):
67
- pass
68
-
69
- self.publisher = await nats.connect(
70
- servers=[endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")],
71
- name=self.subject,
72
- user=self.auth["user"],
73
- password=self.auth["pass"],
74
- max_reconnect_attempts=-1,
75
- error_cb=ignore_cb,
76
- disconnected_cb=ignore_cb,
77
- closed_cb=ignore_cb,
78
- reconnected_cb=ignore_cb,
79
- discovered_server_cb=ignore_cb,
80
- )
66
+ servers = [endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")]
81
67
 
82
- self.dm_publisher = await nats.connect(
83
- servers=[endpoint for endpoint in self.proxy_endpoints if endpoint.startswith("nats://")],
84
- name=self.dm_subject,
85
- user=self.auth["user"],
86
- password=self.auth["pass"],
87
- max_reconnect_attempts=-1,
88
- error_cb=ignore_cb,
89
- disconnected_cb=ignore_cb,
90
- closed_cb=ignore_cb,
91
- reconnected_cb=ignore_cb,
92
- discovered_server_cb=ignore_cb,
93
- )
68
+ self.publisher = ProxyConnection(self.subject, servers, self.auth)
69
+ await self.publisher.connect()
94
70
 
95
- self.subscriber = await self.publisher.subscribe(subject=self.subject)
96
- self.dm_subscriber = await self.dm_publisher.subscribe(subject=self.dm_subject)
71
+ self.dm_publisher = ProxyConnection(self.dm_subject, servers, self.auth)
72
+ await self.dm_publisher.connect()
97
73
 
98
- self.message_queue = ClientMessageQueue(
74
+ self.subscriber = await self.publisher.subscribe(subject=self.subject)
75
+ self.message_queue = MessageQueue(
99
76
  self.logger,
100
77
  self.publisher,
101
78
  self.subscriber,
102
79
  self.__request_handler,
103
80
  )
104
81
 
105
- self.tasks.add(self.message_queue.start())
106
- self.tasks.add(self.__listen_to_messages())
82
+ self.dm_subscriber = await self.dm_publisher.subscribe(subject=self.dm_subject)
83
+ self.dm_subscriber.on("message", self.__on_proxy_message)
107
84
 
108
85
  async def get_camera_by_id(self, id: str) -> Optional[CameraDeviceProxy]:
109
86
  camera_device = await self.__add_or_get_camera(id)
@@ -175,27 +152,11 @@ class DeviceManager(AsyncIOEventEmitter):
175
152
 
176
153
  super().emit(type, camera["_id"], extension)
177
154
 
178
- async def __listen_to_messages(self) -> None:
179
- if not self.dm_subscriber:
180
- raise Exception("Subscriber is not initialized")
181
-
182
- async for msg in self.dm_subscriber.messages:
183
- try:
184
- if not self.initialized:
185
- break
186
-
187
- if len(msg.data) == 0:
188
- continue
189
-
190
- self.tasks.add(self.__emit_event(msg))
191
- except Exception as e:
192
- if self.initialized:
193
- self.logger.error(
194
- "Error while listening to device manager messages from server:",
195
- e,
196
- )
197
- else:
198
- break
155
+ async def __on_proxy_message(self, msg: Msg) -> None:
156
+ if not self.initialized:
157
+ return
158
+
159
+ self.tasks.add(self.__emit_event(msg))
199
160
 
200
161
  async def __on_request(self, fn: str, args: list[Any] = []) -> Any:
201
162
  if not self.message_queue:
@@ -2,13 +2,11 @@ from typing import Any, Optional
2
2
 
3
3
  from camera_storage import CameraStorage
4
4
  from camera_ui_types import PluginJsonSchemaForm
5
- from logger import PluginLogger
6
5
  from plugin_api import PluginAPI
7
6
 
8
7
 
9
8
  class StorageController:
10
- def __init__(self, api: PluginAPI, logger: PluginLogger) -> None:
11
- self.__logger = logger
9
+ def __init__(self, api: PluginAPI) -> None:
12
10
  self.__api = api
13
11
  self.__camera_storages: dict[str, CameraStorage] = {}
14
12
 
@@ -28,8 +26,9 @@ class StorageController:
28
26
  """
29
27
  if schema is None:
30
28
  schema = {}
29
+
31
30
  camera_storage = self.__camera_storages.get(camera_id) or CameraStorage(
32
- self.__api, self.__logger, instance, camera_id, schema
31
+ self.__api, instance, camera_id, schema
33
32
  )
34
33
 
35
34
  camera_storage.initialize_storage()
@@ -0,0 +1,86 @@
1
+ from typing import Any, Optional
2
+
3
+ import nats
4
+ from decoder.typings import AuthConfig
5
+ from nats.aio.client import Client as NatsConnection
6
+
7
+ from .packer import pack, unpack
8
+ from .subscriptions import ProxySubscription
9
+ from .task import TaskSet
10
+
11
+
12
+ class ProxyConnection:
13
+ def __init__(self, name: str, servers: list[str], auth: AuthConfig) -> None:
14
+ self.name = name
15
+ self.servers = servers
16
+ self.auth = auth
17
+
18
+ self.tasks: TaskSet = TaskSet(f"{self.name} NatsSubscriber")
19
+ self.publisher: Optional[NatsConnection] = None
20
+ self.subscribers: list[ProxySubscription] = []
21
+
22
+ self.closed = False
23
+
24
+ async def connect(self) -> NatsConnection:
25
+ async def ignore_cb(e: Optional[Any] = None):
26
+ pass
27
+
28
+ self.publisher = await nats.connect(
29
+ servers=self.servers,
30
+ name=self.name,
31
+ user=self.auth["user"],
32
+ password=self.auth["password"],
33
+ max_reconnect_attempts=-1,
34
+ error_cb=ignore_cb,
35
+ disconnected_cb=ignore_cb,
36
+ closed_cb=ignore_cb,
37
+ reconnected_cb=ignore_cb,
38
+ discovered_server_cb=ignore_cb,
39
+ )
40
+
41
+ return self.publisher
42
+
43
+ async def subscribe(self, subject: str, skip_listening: bool = False) -> ProxySubscription:
44
+ if not self.publisher:
45
+ raise Exception("Connection not established")
46
+
47
+ subscriber = ProxySubscription(await self.publisher.subscribe(subject))
48
+
49
+ if not skip_listening:
50
+ self.tasks.add(subscriber.listen())
51
+
52
+ self.subscribers.append(subscriber)
53
+
54
+ return subscriber
55
+
56
+ async def publish(self, subject: str, message: Any) -> None:
57
+ if self.closed:
58
+ return
59
+
60
+ if not self.publisher:
61
+ raise Exception("Connection not established")
62
+
63
+ await self.publisher.publish(subject, pack(message))
64
+
65
+ async def request(self, subject: str, message: Any, timeout: float) -> Any:
66
+ if self.closed:
67
+ return
68
+
69
+ if not self.publisher:
70
+ raise Exception("Connection not established")
71
+
72
+ msg = await self.publisher.request(subject, pack(message), timeout)
73
+ response = unpack(msg.data)
74
+
75
+ return response
76
+
77
+ async def close(self) -> None:
78
+ self.closed = True
79
+
80
+ for subscriber in self.subscribers:
81
+ await subscriber.close()
82
+
83
+ if self.publisher:
84
+ await self.publisher.close()
85
+
86
+ self.tasks.remove_all()