@camera.ui/server 0.0.1

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 (652) hide show
  1. package/dist/interface/assets/@babel-l0sNRNKZ.js +1 -0
  2. package/dist/interface/assets/@camera.ui-2NVnv26v.js +8 -0
  3. package/dist/interface/assets/@intlify-Ck2ZoCVz.js +15 -0
  4. package/dist/interface/assets/@mdi-C-QA1nE3.js +1 -0
  5. package/dist/interface/assets/@popperjs-BQBsAJpH.js +1 -0
  6. package/dist/interface/assets/@react-dnd-CcwRs9xb.js +1 -0
  7. package/dist/interface/assets/@socket.io-Dkula2eQ.js +1 -0
  8. package/dist/interface/assets/@tanstack-BqH4GyO-.js +1 -0
  9. package/dist/interface/assets/@vee-validate-DCBdnGo-.js +5 -0
  10. package/dist/interface/assets/@vue-C7-KaDG4.js +17 -0
  11. package/dist/interface/assets/@vueform-arggO0eF.js +1 -0
  12. package/dist/interface/assets/@vueform-h7tNX9p6.css +1 -0
  13. package/dist/interface/assets/@vueuse-C3WMTDqL.js +1 -0
  14. package/dist/interface/assets/@xterm-B4Ga69iL.js +9 -0
  15. package/dist/interface/assets/@xterm-CGrrDQr5.css +32 -0
  16. package/dist/interface/assets/Account-B_tHnXoX.css +1 -0
  17. package/dist/interface/assets/Account-gJpkf0nE.js +1 -0
  18. package/dist/interface/assets/Adminpanel-B_SY1GJM.css +0 -0
  19. package/dist/interface/assets/Adminpanel-Bge9nu5N.js +1 -0
  20. package/dist/interface/assets/Appearance-D22q-X_I.js +1 -0
  21. package/dist/interface/assets/Backup-DBv9xFPh.css +1 -0
  22. package/dist/interface/assets/Backup-pJm6s10G.js +1 -0
  23. package/dist/interface/assets/Camera-BgO2yRjb.js +1 -0
  24. package/dist/interface/assets/Camera-CWiLco3W.css +1 -0
  25. package/dist/interface/assets/Cameras-BM3vSM_R.css +1 -0
  26. package/dist/interface/assets/Cameras-DjeKruR_.js +1 -0
  27. package/dist/interface/assets/Camview-DfzlprzN.js +1 -0
  28. package/dist/interface/assets/Camview-vUAs5YHU.css +1 -0
  29. package/dist/interface/assets/Config-BKIOIkjC.js +1 -0
  30. package/dist/interface/assets/Config-DAiKsG7W.css +1 -0
  31. package/dist/interface/assets/Console-BsyX2S3R.css +1 -0
  32. package/dist/interface/assets/Console-Caz7y-T0.js +4 -0
  33. package/dist/interface/assets/FirstSteps-DNHhyDSw.css +1 -0
  34. package/dist/interface/assets/FirstSteps-mQK4XFTs.js +1 -0
  35. package/dist/interface/assets/NewCamera-B9t-0NCc.js +448 -0
  36. package/dist/interface/assets/NewCamera-CHMgUDbC.css +1 -0
  37. package/dist/interface/assets/Plugin-BSHKKjrl.css +1 -0
  38. package/dist/interface/assets/Plugin-Di_bBsg-.js +1 -0
  39. package/dist/interface/assets/Plugins-BsMITags.css +1 -0
  40. package/dist/interface/assets/Plugins-DhmzMNuO.js +1 -0
  41. package/dist/interface/assets/Recordings-Bu53bSBp.js +1 -0
  42. package/dist/interface/assets/Recordings-XY20w8yp.js +1 -0
  43. package/dist/interface/assets/Settings-JES2wb8p.css +1 -0
  44. package/dist/interface/assets/Settings-gGRBRVST.js +1 -0
  45. package/dist/interface/assets/System-ZDrcLNk0.js +1 -0
  46. package/dist/interface/assets/User-BXColIbU.css +1 -0
  47. package/dist/interface/assets/User-D4vEhhzi.js +1 -0
  48. package/dist/interface/assets/VConfigEditor.vue_vue_type_script_setup_true_lang-CXFI-IeE.js +2 -0
  49. package/dist/interface/assets/VConsole-BHo3xprq.js +1 -0
  50. package/dist/interface/assets/VConsole-f-nUkOuD.css +1 -0
  51. package/dist/interface/assets/VPlayer-D3KhRfx-.css +1 -0
  52. package/dist/interface/assets/VPlayer-YdRn97Bs.js +1 -0
  53. package/dist/interface/assets/VPluginCard--3bx6UJb.js +4 -0
  54. package/dist/interface/assets/VPluginCard-BJYMuCLk.css +1 -0
  55. package/dist/interface/assets/ace-builds-CigWTak4.js +956 -0
  56. package/dist/interface/assets/axios--Jv2L996.js +6 -0
  57. package/dist/interface/assets/dijkstrajs-D_NXgYpA.js +1 -0
  58. package/dist/interface/assets/dnd-core-SnWOpY0X.js +1 -0
  59. package/dist/interface/assets/draggabilly-Arakw9Dk.js +6 -0
  60. package/dist/interface/assets/encode-utf8-Cn5aGd7v.js +1 -0
  61. package/dist/interface/assets/engine.io-client-DBBxzneW.js +1 -0
  62. package/dist/interface/assets/engine.io-parser-BiEtp6m2.js +1 -0
  63. package/dist/interface/assets/entities-C20TfXL6.js +1 -0
  64. package/dist/interface/assets/ev-emitter-CXYwG0eJ.js +1 -0
  65. package/dist/interface/assets/fast-deep-equal-5pvsDbwX.js +1 -0
  66. package/dist/interface/assets/get-size-D1dS-IaP.js +5 -0
  67. package/dist/interface/assets/highlight-DgoK_Xib.css +1 -0
  68. package/dist/interface/assets/highlight.js-TxRCSjhv.js +2 -0
  69. package/dist/interface/assets/linkify-it-DmNjr4Kv.js +1 -0
  70. package/dist/interface/assets/logo-256-BCQk9H1-.png +0 -0
  71. package/dist/interface/assets/logo-512-DLKVOU2S.png +0 -0
  72. package/dist/interface/assets/logo-DmEiRk0z.png +0 -0
  73. package/dist/interface/assets/main-B3IVLctZ.css +1 -0
  74. package/dist/interface/assets/main-C4rYiRNz.js +2 -0
  75. package/dist/interface/assets/markdown-it-DI8MEbma.js +15 -0
  76. package/dist/interface/assets/mdurl-k9Sl0PQj.js +2 -0
  77. package/dist/interface/assets/mode-json-Br7xisR1.js +275 -0
  78. package/dist/interface/assets/mode-yaml-CIYL8U3d.js +395 -0
  79. package/dist/interface/assets/nprogress-DSyAi0LF.js +2 -0
  80. package/dist/interface/assets/pinia-D8MtiGcH.js +5 -0
  81. package/dist/interface/assets/plugins-Bf03y242.js +1 -0
  82. package/dist/interface/assets/punycode.js-Dj65hjkv.js +1 -0
  83. package/dist/interface/assets/qrcode-CGiDONbL.js +8 -0
  84. package/dist/interface/assets/react-dnd-html5-backend-1HQjlkwI.js +2 -0
  85. package/dist/interface/assets/react-dnd-touch-backend-NgACaG8W.js +1 -0
  86. package/dist/interface/assets/redux-CuxFRhX_.js +1 -0
  87. package/dist/interface/assets/rxjs-B53o3e_J.js +3 -0
  88. package/dist/interface/assets/socket.io-client-Bq_SHkin.js +1 -0
  89. package/dist/interface/assets/socket.io-parser-BBkuslX-.js +1 -0
  90. package/dist/interface/assets/system-BONnDA4y.js +1 -0
  91. package/dist/interface/assets/tslib-9k7AwCpt.js +1 -0
  92. package/dist/interface/assets/uc.micro-kMc2yuuw.js +1 -0
  93. package/dist/interface/assets/ui-CNpIJotI.js +1 -0
  94. package/dist/interface/assets/unidragger-BYtqgAQ0.js +5 -0
  95. package/dist/interface/assets/utils-BvINh1mj.js +1 -0
  96. package/dist/interface/assets/uuid-DvF23Exx.js +1 -0
  97. package/dist/interface/assets/v-calendar-CtSuDYZU.css +1 -0
  98. package/dist/interface/assets/v-calendar-uh0aTGqP.js +1 -0
  99. package/dist/interface/assets/vee-validate-D3FqbChK.js +5 -0
  100. package/dist/interface/assets/vue-i18n-1AU8MPys.js +5 -0
  101. package/dist/interface/assets/vue-inline-svg-2DDwYW6V.js +1 -0
  102. package/dist/interface/assets/vue-l0sNRNKZ.js +1 -0
  103. package/dist/interface/assets/vue-router-DfeQ8s4I.js +5 -0
  104. package/dist/interface/assets/vue3-dnd-BwxcSU9Z.js +1 -0
  105. package/dist/interface/assets/vue3-toastify-DTY1DMRs.css +1 -0
  106. package/dist/interface/assets/vue3-toastify-Ul-rf53I.js +1 -0
  107. package/dist/interface/assets/vuetify-B__3Y-at.css +5 -0
  108. package/dist/interface/assets/vuetify-_-Oqac3B.js +5 -0
  109. package/dist/interface/assets/zod-BaF2dDCd.js +1 -0
  110. package/dist/interface/browserconfig.xml +11 -0
  111. package/dist/interface/fonts/Inter/Inter-Regular.ttf +0 -0
  112. package/dist/interface/index.html +377 -0
  113. package/dist/interface/manifest.webmanifest +1 -0
  114. package/dist/interface/pwa/apple-splash-landscape-dark-1136x640.png +0 -0
  115. package/dist/interface/pwa/apple-splash-landscape-dark-1334x750.png +0 -0
  116. package/dist/interface/pwa/apple-splash-landscape-dark-1792x828.png +0 -0
  117. package/dist/interface/pwa/apple-splash-landscape-dark-2048x1536.png +0 -0
  118. package/dist/interface/pwa/apple-splash-landscape-dark-2160x1620.png +0 -0
  119. package/dist/interface/pwa/apple-splash-landscape-dark-2208x1242.png +0 -0
  120. package/dist/interface/pwa/apple-splash-landscape-dark-2224x1668.png +0 -0
  121. package/dist/interface/pwa/apple-splash-landscape-dark-2388x1668.png +0 -0
  122. package/dist/interface/pwa/apple-splash-landscape-dark-2436x1125.png +0 -0
  123. package/dist/interface/pwa/apple-splash-landscape-dark-2532x1170.png +0 -0
  124. package/dist/interface/pwa/apple-splash-landscape-dark-2556x1179.png +0 -0
  125. package/dist/interface/pwa/apple-splash-landscape-dark-2688x1242.png +0 -0
  126. package/dist/interface/pwa/apple-splash-landscape-dark-2732x2048.png +0 -0
  127. package/dist/interface/pwa/apple-splash-landscape-dark-2778x1284.png +0 -0
  128. package/dist/interface/pwa/apple-splash-landscape-dark-2796x1290.png +0 -0
  129. package/dist/interface/pwa/apple-splash-landscape-light-1136x640.png +0 -0
  130. package/dist/interface/pwa/apple-splash-landscape-light-1334x750.png +0 -0
  131. package/dist/interface/pwa/apple-splash-landscape-light-1792x828.png +0 -0
  132. package/dist/interface/pwa/apple-splash-landscape-light-2048x1536.png +0 -0
  133. package/dist/interface/pwa/apple-splash-landscape-light-2160x1620.png +0 -0
  134. package/dist/interface/pwa/apple-splash-landscape-light-2208x1242.png +0 -0
  135. package/dist/interface/pwa/apple-splash-landscape-light-2224x1668.png +0 -0
  136. package/dist/interface/pwa/apple-splash-landscape-light-2388x1668.png +0 -0
  137. package/dist/interface/pwa/apple-splash-landscape-light-2436x1125.png +0 -0
  138. package/dist/interface/pwa/apple-splash-landscape-light-2532x1170.png +0 -0
  139. package/dist/interface/pwa/apple-splash-landscape-light-2556x1179.png +0 -0
  140. package/dist/interface/pwa/apple-splash-landscape-light-2688x1242.png +0 -0
  141. package/dist/interface/pwa/apple-splash-landscape-light-2732x2048.png +0 -0
  142. package/dist/interface/pwa/apple-splash-landscape-light-2778x1284.png +0 -0
  143. package/dist/interface/pwa/apple-splash-landscape-light-2796x1290.png +0 -0
  144. package/dist/interface/pwa/apple-splash-portrait-dark-1125x2436.png +0 -0
  145. package/dist/interface/pwa/apple-splash-portrait-dark-1170x2532.png +0 -0
  146. package/dist/interface/pwa/apple-splash-portrait-dark-1179x2556.png +0 -0
  147. package/dist/interface/pwa/apple-splash-portrait-dark-1242x2208.png +0 -0
  148. package/dist/interface/pwa/apple-splash-portrait-dark-1242x2688.png +0 -0
  149. package/dist/interface/pwa/apple-splash-portrait-dark-1284x2778.png +0 -0
  150. package/dist/interface/pwa/apple-splash-portrait-dark-1290x2796.png +0 -0
  151. package/dist/interface/pwa/apple-splash-portrait-dark-1536x2048.png +0 -0
  152. package/dist/interface/pwa/apple-splash-portrait-dark-1620x2160.png +0 -0
  153. package/dist/interface/pwa/apple-splash-portrait-dark-1668x2224.png +0 -0
  154. package/dist/interface/pwa/apple-splash-portrait-dark-1668x2388.png +0 -0
  155. package/dist/interface/pwa/apple-splash-portrait-dark-2048x2732.png +0 -0
  156. package/dist/interface/pwa/apple-splash-portrait-dark-640x1136.png +0 -0
  157. package/dist/interface/pwa/apple-splash-portrait-dark-750x1334.png +0 -0
  158. package/dist/interface/pwa/apple-splash-portrait-dark-828x1792.png +0 -0
  159. package/dist/interface/pwa/apple-splash-portrait-light-1125x2436.png +0 -0
  160. package/dist/interface/pwa/apple-splash-portrait-light-1170x2532.png +0 -0
  161. package/dist/interface/pwa/apple-splash-portrait-light-1179x2556.png +0 -0
  162. package/dist/interface/pwa/apple-splash-portrait-light-1242x2208.png +0 -0
  163. package/dist/interface/pwa/apple-splash-portrait-light-1242x2688.png +0 -0
  164. package/dist/interface/pwa/apple-splash-portrait-light-1284x2778.png +0 -0
  165. package/dist/interface/pwa/apple-splash-portrait-light-1290x2796.png +0 -0
  166. package/dist/interface/pwa/apple-splash-portrait-light-1536x2048.png +0 -0
  167. package/dist/interface/pwa/apple-splash-portrait-light-1620x2160.png +0 -0
  168. package/dist/interface/pwa/apple-splash-portrait-light-1668x2224.png +0 -0
  169. package/dist/interface/pwa/apple-splash-portrait-light-1668x2388.png +0 -0
  170. package/dist/interface/pwa/apple-splash-portrait-light-2048x2732.png +0 -0
  171. package/dist/interface/pwa/apple-splash-portrait-light-640x1136.png +0 -0
  172. package/dist/interface/pwa/apple-splash-portrait-light-750x1334.png +0 -0
  173. package/dist/interface/pwa/apple-splash-portrait-light-828x1792.png +0 -0
  174. package/dist/interface/pwa/apple-touch-icon-180x180.png +0 -0
  175. package/dist/interface/pwa/favicon-16.ico +0 -0
  176. package/dist/interface/pwa/favicon-32.ico +0 -0
  177. package/dist/interface/pwa/favicon-48.ico +0 -0
  178. package/dist/interface/pwa/favicon-64.ico +0 -0
  179. package/dist/interface/pwa/logo.svg +1 -0
  180. package/dist/interface/pwa/maskable-icon-1240x600.png +0 -0
  181. package/dist/interface/pwa/maskable-icon-512x512.png +0 -0
  182. package/dist/interface/pwa/maskable-icon-620x300.png +0 -0
  183. package/dist/interface/pwa/pwa-1024x1024.png +0 -0
  184. package/dist/interface/pwa/pwa-120x120.png +0 -0
  185. package/dist/interface/pwa/pwa-144x144.png +0 -0
  186. package/dist/interface/pwa/pwa-152x152.png +0 -0
  187. package/dist/interface/pwa/pwa-167x167.png +0 -0
  188. package/dist/interface/pwa/pwa-180x180.png +0 -0
  189. package/dist/interface/pwa/pwa-192x192.png +0 -0
  190. package/dist/interface/pwa/pwa-24x24.png +0 -0
  191. package/dist/interface/pwa/pwa-300x300.png +0 -0
  192. package/dist/interface/pwa/pwa-36x36.png +0 -0
  193. package/dist/interface/pwa/pwa-48x48.png +0 -0
  194. package/dist/interface/pwa/pwa-50x50.png +0 -0
  195. package/dist/interface/pwa/pwa-64x64.png +0 -0
  196. package/dist/interface/pwa/pwa-72x72.png +0 -0
  197. package/dist/interface/pwa/pwa-88x88.png +0 -0
  198. package/dist/interface/pwa/pwa-96x96.png +0 -0
  199. package/dist/interface/registerSW.js +1 -0
  200. package/dist/interface/robots.txt +2 -0
  201. package/dist/interface/sw.js +1 -0
  202. package/dist/interface/workbox-3e911b1d.js +1 -0
  203. package/dist/server/bin/cui-service.d.ts +43 -0
  204. package/dist/server/bin/cui-service.js +472 -0
  205. package/dist/server/bin/cui-service.js.map +1 -0
  206. package/dist/server/bin/cui.d.ts +2 -0
  207. package/dist/server/bin/cui.js +8 -0
  208. package/dist/server/bin/cui.js.map +1 -0
  209. package/dist/server/bin/installer/base.d.ts +16 -0
  210. package/dist/server/bin/installer/base.js +41 -0
  211. package/dist/server/bin/installer/base.js.map +1 -0
  212. package/dist/server/bin/installer/darwin.d.ts +49 -0
  213. package/dist/server/bin/installer/darwin.js +200 -0
  214. package/dist/server/bin/installer/darwin.js.map +1 -0
  215. package/dist/server/bin/installer/freebsd.d.ts +61 -0
  216. package/dist/server/bin/installer/freebsd.js +252 -0
  217. package/dist/server/bin/installer/freebsd.js.map +1 -0
  218. package/dist/server/bin/installer/linux.d.ts +92 -0
  219. package/dist/server/bin/installer/linux.js +386 -0
  220. package/dist/server/bin/installer/linux.js.map +1 -0
  221. package/dist/server/bin/installer/win32.d.ts +37 -0
  222. package/dist/server/bin/installer/win32.js +158 -0
  223. package/dist/server/bin/installer/win32.js.map +1 -0
  224. package/dist/server/package.json +142 -0
  225. package/dist/server/requirements.txt +13 -0
  226. package/dist/server/src/api/controllers/api.controller.d.ts +6 -0
  227. package/dist/server/src/api/controllers/api.controller.js +11 -0
  228. package/dist/server/src/api/controllers/api.controller.js.map +1 -0
  229. package/dist/server/src/api/controllers/auth.controller.d.ts +20 -0
  230. package/dist/server/src/api/controllers/auth.controller.js +263 -0
  231. package/dist/server/src/api/controllers/auth.controller.js.map +1 -0
  232. package/dist/server/src/api/controllers/backup.controller.d.ts +10 -0
  233. package/dist/server/src/api/controllers/backup.controller.js +52 -0
  234. package/dist/server/src/api/controllers/backup.controller.js.map +1 -0
  235. package/dist/server/src/api/controllers/cameras.controller.d.ts +34 -0
  236. package/dist/server/src/api/controllers/cameras.controller.js +522 -0
  237. package/dist/server/src/api/controllers/cameras.controller.js.map +1 -0
  238. package/dist/server/src/api/controllers/config.controller.d.ts +14 -0
  239. package/dist/server/src/api/controllers/config.controller.js +89 -0
  240. package/dist/server/src/api/controllers/config.controller.js.map +1 -0
  241. package/dist/server/src/api/controllers/files.controller.d.ts +8 -0
  242. package/dist/server/src/api/controllers/files.controller.js +28 -0
  243. package/dist/server/src/api/controllers/files.controller.js.map +1 -0
  244. package/dist/server/src/api/controllers/frameWorkers.controller.d.ts +16 -0
  245. package/dist/server/src/api/controllers/frameWorkers.controller.js +85 -0
  246. package/dist/server/src/api/controllers/frameWorkers.controller.js.map +1 -0
  247. package/dist/server/src/api/controllers/plugins.controller.d.ts +59 -0
  248. package/dist/server/src/api/controllers/plugins.controller.js +1178 -0
  249. package/dist/server/src/api/controllers/plugins.controller.js.map +1 -0
  250. package/dist/server/src/api/controllers/system.controller.d.ts +14 -0
  251. package/dist/server/src/api/controllers/system.controller.js +149 -0
  252. package/dist/server/src/api/controllers/system.controller.js.map +1 -0
  253. package/dist/server/src/api/controllers/users.controller.d.ts +28 -0
  254. package/dist/server/src/api/controllers/users.controller.js +463 -0
  255. package/dist/server/src/api/controllers/users.controller.js.map +1 -0
  256. package/dist/server/src/api/database/index.d.ts +34 -0
  257. package/dist/server/src/api/database/index.js +185 -0
  258. package/dist/server/src/api/database/index.js.map +1 -0
  259. package/dist/server/src/api/database/migration.d.ts +12 -0
  260. package/dist/server/src/api/database/migration.js +47 -0
  261. package/dist/server/src/api/database/migration.js.map +1 -0
  262. package/dist/server/src/api/database/types.d.ts +209 -0
  263. package/dist/server/src/api/database/types.js +2 -0
  264. package/dist/server/src/api/database/types.js.map +1 -0
  265. package/dist/server/src/api/go2rtc/api/application.d.ts +9 -0
  266. package/dist/server/src/api/go2rtc/api/application.js +38 -0
  267. package/dist/server/src/api/go2rtc/api/application.js.map +1 -0
  268. package/dist/server/src/api/go2rtc/api/config.d.ts +8 -0
  269. package/dist/server/src/api/go2rtc/api/config.js +44 -0
  270. package/dist/server/src/api/go2rtc/api/config.js.map +1 -0
  271. package/dist/server/src/api/go2rtc/api/index.d.ts +1 -0
  272. package/dist/server/src/api/go2rtc/api/index.js +28 -0
  273. package/dist/server/src/api/go2rtc/api/index.js.map +1 -0
  274. package/dist/server/src/api/go2rtc/api/snapshot.d.ts +8 -0
  275. package/dist/server/src/api/go2rtc/api/snapshot.js +34 -0
  276. package/dist/server/src/api/go2rtc/api/snapshot.js.map +1 -0
  277. package/dist/server/src/api/go2rtc/api/streams.d.ts +10 -0
  278. package/dist/server/src/api/go2rtc/api/streams.js +67 -0
  279. package/dist/server/src/api/go2rtc/api/streams.js.map +1 -0
  280. package/dist/server/src/api/go2rtc/index.d.ts +13 -0
  281. package/dist/server/src/api/go2rtc/index.js +25 -0
  282. package/dist/server/src/api/go2rtc/index.js.map +1 -0
  283. package/dist/server/src/api/go2rtc/queue.d.ts +10 -0
  284. package/dist/server/src/api/go2rtc/queue.js +38 -0
  285. package/dist/server/src/api/go2rtc/queue.js.map +1 -0
  286. package/dist/server/src/api/go2rtc/types.d.ts +60 -0
  287. package/dist/server/src/api/go2rtc/types.js +2 -0
  288. package/dist/server/src/api/go2rtc/types.js.map +1 -0
  289. package/dist/server/src/api/index.d.ts +20 -0
  290. package/dist/server/src/api/index.js +233 -0
  291. package/dist/server/src/api/index.js.map +1 -0
  292. package/dist/server/src/api/middlewares/authPermission.middleware.d.ts +5 -0
  293. package/dist/server/src/api/middlewares/authPermission.middleware.js +28 -0
  294. package/dist/server/src/api/middlewares/authPermission.middleware.js.map +1 -0
  295. package/dist/server/src/api/middlewares/authValidation.middleware.d.ts +4 -0
  296. package/dist/server/src/api/middlewares/authValidation.middleware.js +129 -0
  297. package/dist/server/src/api/middlewares/authValidation.middleware.js.map +1 -0
  298. package/dist/server/src/api/middlewares/pagination.middleware.d.ts +3 -0
  299. package/dist/server/src/api/middlewares/pagination.middleware.js +65 -0
  300. package/dist/server/src/api/middlewares/pagination.middleware.js.map +1 -0
  301. package/dist/server/src/api/middlewares/socketAuth.middleware.d.ts +41 -0
  302. package/dist/server/src/api/middlewares/socketAuth.middleware.js +81 -0
  303. package/dist/server/src/api/middlewares/socketAuth.middleware.js.map +1 -0
  304. package/dist/server/src/api/plugins/cameraui.plugin.d.ts +11 -0
  305. package/dist/server/src/api/plugins/cameraui.plugin.js +6 -0
  306. package/dist/server/src/api/plugins/cameraui.plugin.js.map +1 -0
  307. package/dist/server/src/api/plugins/database.plugin.d.ts +11 -0
  308. package/dist/server/src/api/plugins/database.plugin.js +12 -0
  309. package/dist/server/src/api/plugins/database.plugin.js.map +1 -0
  310. package/dist/server/src/api/plugins/go2rtc.plugin.d.ts +11 -0
  311. package/dist/server/src/api/plugins/go2rtc.plugin.js +11 -0
  312. package/dist/server/src/api/plugins/go2rtc.plugin.js.map +1 -0
  313. package/dist/server/src/api/plugins/logger.plugin.d.ts +7 -0
  314. package/dist/server/src/api/plugins/logger.plugin.js +29 -0
  315. package/dist/server/src/api/plugins/logger.plugin.js.map +1 -0
  316. package/dist/server/src/api/plugins/socket.plugin.d.ts +11 -0
  317. package/dist/server/src/api/plugins/socket.plugin.js +12 -0
  318. package/dist/server/src/api/plugins/socket.plugin.js.map +1 -0
  319. package/dist/server/src/api/plugins/system.plugin.d.ts +21 -0
  320. package/dist/server/src/api/plugins/system.plugin.js +33 -0
  321. package/dist/server/src/api/plugins/system.plugin.js.map +1 -0
  322. package/dist/server/src/api/plugins/useragent.plugin.d.ts +8 -0
  323. package/dist/server/src/api/plugins/useragent.plugin.js +10 -0
  324. package/dist/server/src/api/plugins/useragent.plugin.js.map +1 -0
  325. package/dist/server/src/api/routes/api.routes.d.ts +2 -0
  326. package/dist/server/src/api/routes/api.routes.js +6 -0
  327. package/dist/server/src/api/routes/api.routes.js.map +1 -0
  328. package/dist/server/src/api/routes/auth.routes.d.ts +2 -0
  329. package/dist/server/src/api/routes/auth.routes.js +47 -0
  330. package/dist/server/src/api/routes/auth.routes.js.map +1 -0
  331. package/dist/server/src/api/routes/backup.routes.d.ts +2 -0
  332. package/dist/server/src/api/routes/backup.routes.js +23 -0
  333. package/dist/server/src/api/routes/backup.routes.js.map +1 -0
  334. package/dist/server/src/api/routes/cameras.routes.d.ts +2 -0
  335. package/dist/server/src/api/routes/cameras.routes.js +181 -0
  336. package/dist/server/src/api/routes/cameras.routes.js.map +1 -0
  337. package/dist/server/src/api/routes/config.routes.d.ts +2 -0
  338. package/dist/server/src/api/routes/config.routes.js +55 -0
  339. package/dist/server/src/api/routes/config.routes.js.map +1 -0
  340. package/dist/server/src/api/routes/files.routes.d.ts +2 -0
  341. package/dist/server/src/api/routes/files.routes.js +12 -0
  342. package/dist/server/src/api/routes/files.routes.js.map +1 -0
  343. package/dist/server/src/api/routes/frameWorkers.routes.d.ts +2 -0
  344. package/dist/server/src/api/routes/frameWorkers.routes.js +33 -0
  345. package/dist/server/src/api/routes/frameWorkers.routes.js.map +1 -0
  346. package/dist/server/src/api/routes/index.d.ts +6 -0
  347. package/dist/server/src/api/routes/index.js +32 -0
  348. package/dist/server/src/api/routes/index.js.map +1 -0
  349. package/dist/server/src/api/routes/plugins.routes.d.ts +2 -0
  350. package/dist/server/src/api/routes/plugins.routes.js +339 -0
  351. package/dist/server/src/api/routes/plugins.routes.js.map +1 -0
  352. package/dist/server/src/api/routes/system.routes.d.ts +2 -0
  353. package/dist/server/src/api/routes/system.routes.js +43 -0
  354. package/dist/server/src/api/routes/system.routes.js.map +1 -0
  355. package/dist/server/src/api/routes/users.routes.d.ts +2 -0
  356. package/dist/server/src/api/routes/users.routes.js +139 -0
  357. package/dist/server/src/api/routes/users.routes.js.map +1 -0
  358. package/dist/server/src/api/schemas/backup.schema.d.ts +118 -0
  359. package/dist/server/src/api/schemas/backup.schema.js +75 -0
  360. package/dist/server/src/api/schemas/backup.schema.js.map +1 -0
  361. package/dist/server/src/api/schemas/cameras.schema.d.ts +932 -0
  362. package/dist/server/src/api/schemas/cameras.schema.js +271 -0
  363. package/dist/server/src/api/schemas/cameras.schema.js.map +1 -0
  364. package/dist/server/src/api/schemas/config.schema.d.ts +202 -0
  365. package/dist/server/src/api/schemas/config.schema.js +68 -0
  366. package/dist/server/src/api/schemas/config.schema.js.map +1 -0
  367. package/dist/server/src/api/schemas/go2rtc.schema.d.ts +703 -0
  368. package/dist/server/src/api/schemas/go2rtc.schema.js +188 -0
  369. package/dist/server/src/api/schemas/go2rtc.schema.js.map +1 -0
  370. package/dist/server/src/api/schemas/plugins.schema.d.ts +72 -0
  371. package/dist/server/src/api/schemas/plugins.schema.js +103 -0
  372. package/dist/server/src/api/schemas/plugins.schema.js.map +1 -0
  373. package/dist/server/src/api/schemas/users.schema.d.ts +1008 -0
  374. package/dist/server/src/api/schemas/users.schema.js +151 -0
  375. package/dist/server/src/api/schemas/users.schema.js.map +1 -0
  376. package/dist/server/src/api/services/auth.service.d.ts +19 -0
  377. package/dist/server/src/api/services/auth.service.js +115 -0
  378. package/dist/server/src/api/services/auth.service.js.map +1 -0
  379. package/dist/server/src/api/services/backup.service.d.ts +11 -0
  380. package/dist/server/src/api/services/backup.service.js +108 -0
  381. package/dist/server/src/api/services/backup.service.js.map +1 -0
  382. package/dist/server/src/api/services/cameras.service.d.ts +55 -0
  383. package/dist/server/src/api/services/cameras.service.js +700 -0
  384. package/dist/server/src/api/services/cameras.service.js.map +1 -0
  385. package/dist/server/src/api/services/plugins.service.d.ts +25 -0
  386. package/dist/server/src/api/services/plugins.service.js +145 -0
  387. package/dist/server/src/api/services/plugins.service.js.map +1 -0
  388. package/dist/server/src/api/services/users.service.d.ts +25 -0
  389. package/dist/server/src/api/services/users.service.js +197 -0
  390. package/dist/server/src/api/services/users.service.js.map +1 -0
  391. package/dist/server/src/api/types/index.d.ts +580 -0
  392. package/dist/server/src/api/types/index.js +9 -0
  393. package/dist/server/src/api/types/index.js.map +1 -0
  394. package/dist/server/src/api/utils/cert.d.ts +11 -0
  395. package/dist/server/src/api/utils/cert.js +411 -0
  396. package/dist/server/src/api/utils/cert.js.map +1 -0
  397. package/dist/server/src/api/utils/constants.d.ts +15 -0
  398. package/dist/server/src/api/utils/constants.js +17 -0
  399. package/dist/server/src/api/utils/constants.js.map +1 -0
  400. package/dist/server/src/api/utils/fetch.d.ts +2 -0
  401. package/dist/server/src/api/utils/fetch.js +24 -0
  402. package/dist/server/src/api/utils/fetch.js.map +1 -0
  403. package/dist/server/src/api/utils/moveFiles.d.ts +1 -0
  404. package/dist/server/src/api/utils/moveFiles.js +38 -0
  405. package/dist/server/src/api/utils/moveFiles.js.map +1 -0
  406. package/dist/server/src/api/utils/parse.d.ts +2 -0
  407. package/dist/server/src/api/utils/parse.js +12 -0
  408. package/dist/server/src/api/utils/parse.js.map +1 -0
  409. package/dist/server/src/api/websocket/index.d.ts +15 -0
  410. package/dist/server/src/api/websocket/index.js +69 -0
  411. package/dist/server/src/api/websocket/index.js.map +1 -0
  412. package/dist/server/src/api/websocket/nsp/frameWorker.d.ts +13 -0
  413. package/dist/server/src/api/websocket/nsp/frameWorker.js +29 -0
  414. package/dist/server/src/api/websocket/nsp/frameWorker.js.map +1 -0
  415. package/dist/server/src/api/websocket/nsp/logs.d.ts +11 -0
  416. package/dist/server/src/api/websocket/nsp/logs.js +113 -0
  417. package/dist/server/src/api/websocket/nsp/logs.js.map +1 -0
  418. package/dist/server/src/api/websocket/nsp/metrics.d.ts +38 -0
  419. package/dist/server/src/api/websocket/nsp/metrics.js +266 -0
  420. package/dist/server/src/api/websocket/nsp/metrics.js.map +1 -0
  421. package/dist/server/src/api/websocket/nsp/notifications.d.ts +11 -0
  422. package/dist/server/src/api/websocket/nsp/notifications.js +35 -0
  423. package/dist/server/src/api/websocket/nsp/notifications.js.map +1 -0
  424. package/dist/server/src/api/websocket/nsp/plugins.d.ts +13 -0
  425. package/dist/server/src/api/websocket/nsp/plugins.js +29 -0
  426. package/dist/server/src/api/websocket/nsp/plugins.js.map +1 -0
  427. package/dist/server/src/api/websocket/nsp/server.d.ts +9 -0
  428. package/dist/server/src/api/websocket/nsp/server.js +48 -0
  429. package/dist/server/src/api/websocket/nsp/server.js.map +1 -0
  430. package/dist/server/src/api/websocket/nsp/status.d.ts +26 -0
  431. package/dist/server/src/api/websocket/nsp/status.js +59 -0
  432. package/dist/server/src/api/websocket/nsp/status.js.map +1 -0
  433. package/dist/server/src/api/websocket/types.d.ts +86 -0
  434. package/dist/server/src/api/websocket/types.js +2 -0
  435. package/dist/server/src/api/websocket/types.js.map +1 -0
  436. package/dist/server/src/api.d.ts +43 -0
  437. package/dist/server/src/api.js +90 -0
  438. package/dist/server/src/api.js.map +1 -0
  439. package/dist/server/src/camera/controller.d.ts +41 -0
  440. package/dist/server/src/camera/controller.js +220 -0
  441. package/dist/server/src/camera/controller.js.map +1 -0
  442. package/dist/server/src/camera/device.d.ts +18 -0
  443. package/dist/server/src/camera/device.js +21 -0
  444. package/dist/server/src/camera/device.js.map +1 -0
  445. package/dist/server/src/camera/index.d.ts +121 -0
  446. package/dist/server/src/camera/index.js +643 -0
  447. package/dist/server/src/camera/index.js.map +1 -0
  448. package/dist/server/src/camera/interfaces/camera.d.ts +11 -0
  449. package/dist/server/src/camera/interfaces/camera.js +31 -0
  450. package/dist/server/src/camera/interfaces/camera.js.map +1 -0
  451. package/dist/server/src/camera/interfaces/prebuffer.d.ts +11 -0
  452. package/dist/server/src/camera/interfaces/prebuffer.js +26 -0
  453. package/dist/server/src/camera/interfaces/prebuffer.js.map +1 -0
  454. package/dist/server/src/camera/interfaces/ptz.d.ts +13 -0
  455. package/dist/server/src/camera/interfaces/ptz.js +47 -0
  456. package/dist/server/src/camera/interfaces/ptz.js.map +1 -0
  457. package/dist/server/src/camera/polygon.d.ts +6 -0
  458. package/dist/server/src/camera/polygon.js +151 -0
  459. package/dist/server/src/camera/polygon.js.map +1 -0
  460. package/dist/server/src/camera/streaming/peer-connection.d.ts +46 -0
  461. package/dist/server/src/camera/streaming/peer-connection.js +150 -0
  462. package/dist/server/src/camera/streaming/peer-connection.js.map +1 -0
  463. package/dist/server/src/camera/streaming/webrtc-connection.d.ts +34 -0
  464. package/dist/server/src/camera/streaming/webrtc-connection.js +152 -0
  465. package/dist/server/src/camera/streaming/webrtc-connection.js.map +1 -0
  466. package/dist/server/src/camera/streaming/werift-session.d.ts +31 -0
  467. package/dist/server/src/camera/streaming/werift-session.js +168 -0
  468. package/dist/server/src/camera/streaming/werift-session.js.map +1 -0
  469. package/dist/server/src/camera/types.d.ts +202 -0
  470. package/dist/server/src/camera/types.js +7 -0
  471. package/dist/server/src/camera/types.js.map +1 -0
  472. package/dist/server/src/camera/videoFrame.d.ts +24 -0
  473. package/dist/server/src/camera/videoFrame.js +105 -0
  474. package/dist/server/src/camera/videoFrame.js.map +1 -0
  475. package/dist/server/src/decoder/ffmpeg.d.ts +2 -0
  476. package/dist/server/src/decoder/ffmpeg.js +61 -0
  477. package/dist/server/src/decoder/ffmpeg.js.map +1 -0
  478. package/dist/server/src/decoder/index.d.ts +11 -0
  479. package/dist/server/src/decoder/index.js +32 -0
  480. package/dist/server/src/decoder/index.js.map +1 -0
  481. package/dist/server/src/decoder/types.d.ts +156 -0
  482. package/dist/server/src/decoder/types.js +2 -0
  483. package/dist/server/src/decoder/types.js.map +1 -0
  484. package/dist/server/src/decoder/worker.d.ts +42 -0
  485. package/dist/server/src/decoder/worker.js +273 -0
  486. package/dist/server/src/decoder/worker.js.map +1 -0
  487. package/dist/server/src/go2rtc/index.d.ts +25 -0
  488. package/dist/server/src/go2rtc/index.js +211 -0
  489. package/dist/server/src/go2rtc/index.js.map +1 -0
  490. package/dist/server/src/go2rtc/types.d.ts +14 -0
  491. package/dist/server/src/go2rtc/types.js +73 -0
  492. package/dist/server/src/go2rtc/types.js.map +1 -0
  493. package/dist/server/src/index.d.ts +16 -0
  494. package/dist/server/src/index.js +5 -0
  495. package/dist/server/src/index.js.map +1 -0
  496. package/dist/server/src/main.d.ts +18 -0
  497. package/dist/server/src/main.js +118 -0
  498. package/dist/server/src/main.js.map +1 -0
  499. package/dist/server/src/nats/constants.d.ts +1 -0
  500. package/dist/server/src/nats/constants.js +2 -0
  501. package/dist/server/src/nats/constants.js.map +1 -0
  502. package/dist/server/src/nats/index.d.ts +35 -0
  503. package/dist/server/src/nats/index.js +150 -0
  504. package/dist/server/src/nats/index.js.map +1 -0
  505. package/dist/server/src/nats/messageQueue.d.ts +17 -0
  506. package/dist/server/src/nats/messageQueue.js +148 -0
  507. package/dist/server/src/nats/messageQueue.js.map +1 -0
  508. package/dist/server/src/nats/proxy/cameraDevice.d.ts +30 -0
  509. package/dist/server/src/nats/proxy/cameraDevice.js +252 -0
  510. package/dist/server/src/nats/proxy/cameraDevice.js.map +1 -0
  511. package/dist/server/src/nats/proxy/deviceManager.d.ts +16 -0
  512. package/dist/server/src/nats/proxy/deviceManager.js +110 -0
  513. package/dist/server/src/nats/proxy/deviceManager.js.map +1 -0
  514. package/dist/server/src/nats/proxy/index.d.ts +2 -0
  515. package/dist/server/src/nats/proxy/index.js +3 -0
  516. package/dist/server/src/nats/proxy/index.js.map +1 -0
  517. package/dist/server/src/nats/server.d.ts +38 -0
  518. package/dist/server/src/nats/server.js +325 -0
  519. package/dist/server/src/nats/server.js.map +1 -0
  520. package/dist/server/src/nats/types.d.ts +125 -0
  521. package/dist/server/src/nats/types.js +11 -0
  522. package/dist/server/src/nats/types.js.map +1 -0
  523. package/dist/server/src/nats/utils.d.ts +4 -0
  524. package/dist/server/src/nats/utils.js +12 -0
  525. package/dist/server/src/nats/utils.js.map +1 -0
  526. package/dist/server/src/nats/websocket.d.ts +27 -0
  527. package/dist/server/src/nats/websocket.js +214 -0
  528. package/dist/server/src/nats/websocket.js.map +1 -0
  529. package/dist/server/src/plugins/index.d.ts +32 -0
  530. package/dist/server/src/plugins/index.js +326 -0
  531. package/dist/server/src/plugins/index.js.map +1 -0
  532. package/dist/server/src/plugins/interfaces/audioDetection.d.ts +7 -0
  533. package/dist/server/src/plugins/interfaces/audioDetection.js +4 -0
  534. package/dist/server/src/plugins/interfaces/audioDetection.js.map +1 -0
  535. package/dist/server/src/plugins/interfaces/base.d.ts +6 -0
  536. package/dist/server/src/plugins/interfaces/base.js +3 -0
  537. package/dist/server/src/plugins/interfaces/base.js.map +1 -0
  538. package/dist/server/src/plugins/interfaces/motionDetection.d.ts +6 -0
  539. package/dist/server/src/plugins/interfaces/motionDetection.js +4 -0
  540. package/dist/server/src/plugins/interfaces/motionDetection.js.map +1 -0
  541. package/dist/server/src/plugins/interfaces/objectDetection.d.ts +7 -0
  542. package/dist/server/src/plugins/interfaces/objectDetection.js +4 -0
  543. package/dist/server/src/plugins/interfaces/objectDetection.js.map +1 -0
  544. package/dist/server/src/plugins/plugin.d.ts +42 -0
  545. package/dist/server/src/plugins/plugin.js +207 -0
  546. package/dist/server/src/plugins/plugin.js.map +1 -0
  547. package/dist/server/src/plugins/types.d.ts +181 -0
  548. package/dist/server/src/plugins/types.js +18 -0
  549. package/dist/server/src/plugins/types.js.map +1 -0
  550. package/dist/server/src/plugins/worker.d.ts +35 -0
  551. package/dist/server/src/plugins/worker.js +309 -0
  552. package/dist/server/src/plugins/worker.js.map +1 -0
  553. package/dist/server/src/polyglot/node/decoder/child.d.ts +1 -0
  554. package/dist/server/src/polyglot/node/decoder/child.js +703 -0
  555. package/dist/server/src/polyglot/node/decoder/child.js.map +1 -0
  556. package/dist/server/src/polyglot/node/decoder/imageUtils.d.ts +24 -0
  557. package/dist/server/src/polyglot/node/decoder/imageUtils.js +203 -0
  558. package/dist/server/src/polyglot/node/decoder/imageUtils.js.map +1 -0
  559. package/dist/server/src/polyglot/node/decoder/reader.d.ts +5 -0
  560. package/dist/server/src/polyglot/node/decoder/reader.js +41 -0
  561. package/dist/server/src/polyglot/node/decoder/reader.js.map +1 -0
  562. package/dist/server/src/polyglot/node/decoder/wasm/build/decoder.d.ts +144 -0
  563. package/dist/server/src/polyglot/node/decoder/wasm/build/decoder.js +65 -0
  564. package/dist/server/src/polyglot/node/decoder/wasm/build/decoder.wasm +0 -0
  565. package/dist/server/src/polyglot/node/decoder/wasm/test/imageUtils.py +106 -0
  566. package/dist/server/src/polyglot/node/plugins/api.d.ts +37 -0
  567. package/dist/server/src/polyglot/node/plugins/api.js +34 -0
  568. package/dist/server/src/polyglot/node/plugins/api.js.map +1 -0
  569. package/dist/server/src/polyglot/node/plugins/cameraStorage.d.ts +108 -0
  570. package/dist/server/src/polyglot/node/plugins/cameraStorage.js +310 -0
  571. package/dist/server/src/polyglot/node/plugins/cameraStorage.js.map +1 -0
  572. package/dist/server/src/polyglot/node/plugins/child.d.ts +25 -0
  573. package/dist/server/src/polyglot/node/plugins/child.js +206 -0
  574. package/dist/server/src/polyglot/node/plugins/child.js.map +1 -0
  575. package/dist/server/src/polyglot/node/plugins/config.d.ts +104 -0
  576. package/dist/server/src/polyglot/node/plugins/config.js +213 -0
  577. package/dist/server/src/polyglot/node/plugins/config.js.map +1 -0
  578. package/dist/server/src/polyglot/node/plugins/logger.d.ts +16 -0
  579. package/dist/server/src/polyglot/node/plugins/logger.js +128 -0
  580. package/dist/server/src/polyglot/node/plugins/logger.js.map +1 -0
  581. package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.d.ts +75 -0
  582. package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js +474 -0
  583. package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js.map +1 -0
  584. package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.d.ts +49 -0
  585. package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.js +194 -0
  586. package/dist/server/src/polyglot/node/plugins/proxy/deviceManager.js.map +1 -0
  587. package/dist/server/src/polyglot/node/plugins/proxy/index.d.ts +2 -0
  588. package/dist/server/src/polyglot/node/plugins/proxy/index.js +3 -0
  589. package/dist/server/src/polyglot/node/plugins/proxy/index.js.map +1 -0
  590. package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.d.ts +20 -0
  591. package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.js +152 -0
  592. package/dist/server/src/polyglot/node/plugins/proxy/messageQueue.js.map +1 -0
  593. package/dist/server/src/polyglot/node/plugins/schema.d.ts +280 -0
  594. package/dist/server/src/polyglot/node/plugins/schema.js +719 -0
  595. package/dist/server/src/polyglot/node/plugins/schema.js.map +1 -0
  596. package/dist/server/src/polyglot/node/plugins/storageController.d.ts +28 -0
  597. package/dist/server/src/polyglot/node/plugins/storageController.js +38 -0
  598. package/dist/server/src/polyglot/node/plugins/storageController.js.map +1 -0
  599. package/dist/server/src/polyglot/python/camera/interfaces/camera.py +26 -0
  600. package/dist/server/src/polyglot/python/camera/interfaces/prebuffer.py +25 -0
  601. package/dist/server/src/polyglot/python/camera/interfaces/ptz.py +38 -0
  602. package/dist/server/src/polyglot/python/camera/polygon.py +173 -0
  603. package/dist/server/src/polyglot/python/camera/video_frame.py +196 -0
  604. package/dist/server/src/polyglot/python/camera_ui_types/__init__.py +1221 -0
  605. package/dist/server/src/polyglot/python/decoder/child.py +922 -0
  606. package/dist/server/src/polyglot/python/decoder/image_utils.py +149 -0
  607. package/dist/server/src/polyglot/python/decoder/typings.py +99 -0
  608. package/dist/server/src/polyglot/python/plugins/camera_storage.py +459 -0
  609. package/dist/server/src/polyglot/python/plugins/child.py +267 -0
  610. package/dist/server/src/polyglot/python/plugins/config_service.py +180 -0
  611. package/dist/server/src/polyglot/python/plugins/constants.py +2 -0
  612. package/dist/server/src/polyglot/python/plugins/logger.py +111 -0
  613. package/dist/server/src/polyglot/python/plugins/plugin_api.py +114 -0
  614. package/dist/server/src/polyglot/python/plugins/proxy/camera_device.py +1722 -0
  615. package/dist/server/src/polyglot/python/plugins/proxy/device_manager.py +265 -0
  616. package/dist/server/src/polyglot/python/plugins/proxy/message_queue.py +213 -0
  617. package/dist/server/src/polyglot/python/plugins/schema.py +392 -0
  618. package/dist/server/src/polyglot/python/plugins/storage_controller.py +57 -0
  619. package/dist/server/src/polyglot/python/plugins/typings.py +248 -0
  620. package/dist/server/src/polyglot/python/utilities/object_path.py +187 -0
  621. package/dist/server/src/polyglot/python/utilities/packer.py +11 -0
  622. package/dist/server/src/polyglot/python/utilities/task.py +25 -0
  623. package/dist/server/src/polyglot/python/utilities/thread.py +10 -0
  624. package/dist/server/src/polyglot/python/utilities/utils.py +48 -0
  625. package/dist/server/src/services/config/constants.d.ts +4 -0
  626. package/dist/server/src/services/config/constants.js +58 -0
  627. package/dist/server/src/services/config/constants.js.map +1 -0
  628. package/dist/server/src/services/config/index.d.ts +54 -0
  629. package/dist/server/src/services/config/index.js +288 -0
  630. package/dist/server/src/services/config/index.js.map +1 -0
  631. package/dist/server/src/services/config/types.d.ts +162 -0
  632. package/dist/server/src/services/config/types.js +11 -0
  633. package/dist/server/src/services/config/types.js.map +1 -0
  634. package/dist/server/src/services/logger/index.d.ts +30 -0
  635. package/dist/server/src/services/logger/index.js +179 -0
  636. package/dist/server/src/services/logger/index.js.map +1 -0
  637. package/dist/server/src/types.d.ts +4 -0
  638. package/dist/server/src/types.js +2 -0
  639. package/dist/server/src/types.js.map +1 -0
  640. package/dist/server/src/utils/packer.d.ts +2 -0
  641. package/dist/server/src/utils/packer.js +17 -0
  642. package/dist/server/src/utils/packer.js.map +1 -0
  643. package/dist/server/src/utils/pythonInstaller.d.ts +48 -0
  644. package/dist/server/src/utils/pythonInstaller.js +465 -0
  645. package/dist/server/src/utils/pythonInstaller.js.map +1 -0
  646. package/dist/server/src/utils/subscribed.d.ts +9 -0
  647. package/dist/server/src/utils/subscribed.js +17 -0
  648. package/dist/server/src/utils/subscribed.js.map +1 -0
  649. package/dist/server/src/utils/utils.d.ts +10 -0
  650. package/dist/server/src/utils/utils.js +165 -0
  651. package/dist/server/src/utils/utils.js.map +1 -0
  652. package/package.json +142 -0
@@ -0,0 +1,1722 @@
1
+ import asyncio
2
+ import inspect
3
+ import traceback
4
+ from collections.abc import AsyncGenerator
5
+ from contextlib import suppress
6
+ from copy import deepcopy
7
+ from datetime import datetime
8
+ from typing import Any, Optional, Union, cast
9
+ from uuid import uuid4
10
+
11
+ import aiohttp
12
+ import nats
13
+ from cachetools import LRUCache, cached
14
+ from camera.polygon import are_motion_detections_valid, are_object_detections_valid
15
+ from camera.video_frame import MotionFrame, VideoFrame
16
+ from camera_ui_types import (
17
+ AudioSetEvent,
18
+ AudioState,
19
+ BatterySetEvent,
20
+ BatteryState,
21
+ Camera,
22
+ CameraActivitySettings,
23
+ CameraConfigInputSettings,
24
+ CameraConfigInputSettingsPartial,
25
+ CameraDelegate,
26
+ CameraDelegateMethodNames,
27
+ CameraFrameWorkerSettings,
28
+ CameraInformation,
29
+ CameraInput,
30
+ CameraPrebufferDelegate,
31
+ CameraPrebufferDelegateMethodNames,
32
+ CameraPropertyObservableObject,
33
+ CameraPTZDelegate,
34
+ CameraPTZDelegateMethodNames,
35
+ CameraPublicProperties,
36
+ CameraType,
37
+ Container,
38
+ DetectionZone,
39
+ DoorbellSetEvent,
40
+ DoorbellState,
41
+ FrameData,
42
+ FrameMetadata,
43
+ FrameState,
44
+ IceServer,
45
+ LightSetEvent,
46
+ LightState,
47
+ MotionSetEvent,
48
+ MotionState,
49
+ ObjectSetEvent,
50
+ ObjectState,
51
+ PrebufferState,
52
+ SetValue,
53
+ SirenSetEvent,
54
+ SirenState,
55
+ StateNames,
56
+ StateValue,
57
+ )
58
+ from decoder.typings import PingMessage, PongMessage, SignalingRequest, SignalingResponse
59
+ from deepdiff import DeepDiff
60
+ from logger import PluginLogger
61
+ from nats.aio.client import Client as NatsConnection
62
+ from nats.aio.msg import Msg
63
+ from nats.aio.subscription import Subscription
64
+ from plugin_api import PluginAPI
65
+ from reactivex import Observable
66
+ from reactivex import operators as ops
67
+ from reactivex.subject.behaviorsubject import BehaviorSubject
68
+ from typing_extensions import Literal, overload
69
+ from typings import (
70
+ CameraDeviceProxyMethodNames,
71
+ ClientType,
72
+ Delegates,
73
+ DeserializedError,
74
+ PluginInfo,
75
+ ProxyMessageStructure,
76
+ )
77
+ from utilities.packer import pack, unpack
78
+ from utilities.task import TaskSet
79
+
80
+ from .message_queue import ClientMessageQueue
81
+
82
+
83
+ class CameraSource:
84
+ def __init__(self, source: CameraInput, parent: Any):
85
+ self.__parent: CameraDeviceProxy = parent
86
+
87
+ self.id = source["_id"]
88
+ self.name = source["name"]
89
+ self.roles = source["roles"]
90
+ self.urls = source["urls"]
91
+
92
+ async def update_prebuffer_state(self, container: Container, state: PrebufferState) -> None:
93
+ return await self.__parent.prebufferDelegate.updatePrebufferState(self.id, container, state)
94
+
95
+ def get_prebuffering_state(self, container: Container) -> PrebufferState:
96
+ return self.__parent.camera_source_prebuffer_state(self.id, container)
97
+
98
+ def on_prebuffering(self, container: Container) -> Observable[PrebufferState]:
99
+ return self.__parent.create_prebuffer_state_observable(self.id, container)
100
+
101
+ async def get_stream_info(self):
102
+ return await self.__parent.prebufferDelegate.getStreamInfo(self.id)
103
+
104
+
105
+ class CameraDeviceProxy:
106
+ def __init__(
107
+ self,
108
+ api: PluginAPI,
109
+ logger: PluginLogger,
110
+ camera: Camera,
111
+ plugin: PluginInfo,
112
+ proxy_endpoints: list[str],
113
+ auth: dict[str, str],
114
+ ):
115
+ self.snapshot_cache = LRUCache(maxsize=100)
116
+ self.camera_subject = BehaviorSubject(camera)
117
+
118
+ self.camera_state = BehaviorSubject[bool](False)
119
+ self.light_state = BehaviorSubject[LightState](self.__get_light_state({"state": False}, True))
120
+ self.motion_state = BehaviorSubject[MotionState](
121
+ self.__get_motion_state({"detections": [], "state": False}, True)
122
+ )
123
+ self.audio_state = BehaviorSubject[AudioState](
124
+ self.__get_audio_state({"state": False, "db": 0}, True)
125
+ )
126
+ self.object_state = BehaviorSubject[ObjectState](self.__get_object_state({"detections": []}, True))
127
+ self.doorbell_state = BehaviorSubject[DoorbellState](
128
+ self.__get_doorbell_state({"state": False}, True)
129
+ )
130
+ self.siren_state = BehaviorSubject[SirenState](
131
+ self.__get_siren_state({"state": False, "level": 0}, True)
132
+ )
133
+ self.battery_state = BehaviorSubject[BatteryState](
134
+ self.__get_battery_state({"level": 100, "charging": False, "lowBattery": False}, True)
135
+ )
136
+ self.__frame_state = BehaviorSubject[FrameState](
137
+ {
138
+ "timestamp": int(datetime.now().timestamp() * 1000),
139
+ "detections": [],
140
+ "frameData": cast(FrameData, {}),
141
+ "metadata": cast(FrameMetadata, {}),
142
+ },
143
+ )
144
+ self.prebuffer_state_subjects: dict[str, dict[str, BehaviorSubject[PrebufferState]]] = {}
145
+
146
+ self.on_connected: Observable[bool] = self.__create_state_observable(self.camera_state)
147
+ self.on_light_switched: Observable[LightState] = self.__create_state_observable(self.light_state)
148
+ self.on_motion_detected: Observable[MotionState] = self.__create_state_observable(self.motion_state)
149
+ self.on_audio_detected: Observable[AudioState] = self.__create_state_observable(self.audio_state)
150
+ self.on_object_detected: Observable[ObjectState] = self.__create_state_observable(self.object_state)
151
+ self.on_doorbell_pressed: Observable[DoorbellState] = self.__create_state_observable(
152
+ self.doorbell_state
153
+ )
154
+ self.on_siren_detected: Observable[SirenState] = self.__create_state_observable(self.siren_state)
155
+ self.on_battery_changed: Observable[BatteryState] = self.__create_state_observable(self.battery_state)
156
+ self.__on_frame: Observable[FrameState] = self.__create_motion_frame_observable()
157
+
158
+ if camera["pluginId"] == "native":
159
+ self.camera_state.on_next(True)
160
+
161
+ self.initialized = False
162
+
163
+ self.api = api
164
+ self.logger = logger
165
+
166
+ self.auth = auth
167
+ self.proxy_endpoints = proxy_endpoints
168
+ self.plugin = plugin
169
+
170
+ from camera.interfaces.camera import CameraInterface
171
+ from camera.interfaces.prebuffer import CameraPrebufferInterface
172
+ from camera.interfaces.ptz import CameraPTZInterface
173
+
174
+ self.cameraDelegate = CameraInterface(self, logger)
175
+ self.prebufferDelegate = CameraPrebufferInterface(self, logger)
176
+ self.ptzDelegate = CameraPTZInterface(self, logger)
177
+
178
+ self.subject = f"{self.plugin['id']}.camera.{self.id}"
179
+ self.camera_subscriber_subject = f"{self.id}.camera"
180
+ self.camera_plugin_subscriber_subject = f"{self.id}.camera.{self.plugin['id']}"
181
+ self.frame_subject = f"{self.id}.frameReceiver"
182
+ self.motion_frame_subject = f"{self.id}.frameGenerator.motionFrame"
183
+ self.signaling_subject = f"{self.plugin['id']}.camera.{self.id}.signaling"
184
+ self.signaling_target_subject = f"{self.id}.frameGenerator.signaling"
185
+
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
191
+
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
198
+
199
+ self.tasks: TaskSet = TaskSet(f"{self.plugin['name']} - {self.name} - CameraDeviceProxy")
200
+ self.message_queue: Optional[ClientMessageQueue] = None
201
+ self.active_requests: set[str] = set()
202
+ self.active_motion_requests = 0
203
+
204
+ # print(("INIT camera device with clientSubject", self.subject))
205
+
206
+ self.__on_frame.subscribe(self.__on_motion_frame)
207
+
208
+ self.api.once("shutdown", self.cleanup)
209
+
210
+ @property
211
+ def camera_object(self) -> Camera:
212
+ return deepcopy(self.camera_subject.value)
213
+
214
+ @property
215
+ def id(self) -> str:
216
+ return self.camera_subject.value.get("_id")
217
+
218
+ @property
219
+ def native_id(self) -> Optional[str]:
220
+ return self.camera_subject.value.get("nativeId")
221
+
222
+ @property
223
+ def plugin_id(self) -> str:
224
+ return self.camera_subject.value.get("pluginId")
225
+
226
+ @property
227
+ def connected(self) -> bool:
228
+ return self.camera_state.value or False
229
+
230
+ @property
231
+ def disabled(self) -> bool:
232
+ return self.camera_subject.value.get("disabled")
233
+
234
+ @property
235
+ def name(self) -> str:
236
+ return self.camera_subject.value.get("name")
237
+
238
+ @property
239
+ def type(self) -> CameraType:
240
+ return self.camera_subject.value.get("type")
241
+
242
+ @property
243
+ def info(self) -> CameraInformation:
244
+ return deepcopy(self.camera_subject.value.get("info"))
245
+
246
+ @property
247
+ def is_cloud_camera(self) -> bool:
248
+ return self.camera_subject.value.get("isCloud")
249
+
250
+ @property
251
+ def has_light(self) -> bool:
252
+ return self.camera_subject.value.get("hasLight")
253
+
254
+ @property
255
+ def has_siren(self) -> bool:
256
+ return self.camera_subject.value.get("hasSiren")
257
+
258
+ @property
259
+ def has_binary_sensor(self) -> bool:
260
+ return self.camera_subject.value.get("hasBinarySensor")
261
+
262
+ @property
263
+ def has_battery(self) -> bool:
264
+ return self.camera_subject.value.get("hasBattery")
265
+
266
+ @property
267
+ def has_motion_detector(self) -> bool:
268
+ return self.camera_subject.value.get("hasMotionDetector")
269
+
270
+ @property
271
+ def has_audio_detector(self) -> bool:
272
+ return self.camera_subject.value.get("hasAudioDetector")
273
+
274
+ @property
275
+ def has_object_detector(self) -> bool:
276
+ return self.camera_subject.value.get("hasObjectDetector")
277
+
278
+ @property
279
+ def has_ptz(self) -> bool:
280
+ return self.camera_subject.value.get("hasPtz")
281
+
282
+ @property
283
+ def has_prebuffer(self) -> bool:
284
+ return self.camera_subject.value.get("hasPrebuffer")
285
+
286
+ @property
287
+ def activity_zones(self) -> list[DetectionZone]:
288
+ return deepcopy(self.camera_subject.value.get("activityZones"))
289
+
290
+ @property
291
+ def activity_settings(self) -> CameraActivitySettings:
292
+ return deepcopy(self.camera_subject.value.get("activitySettings"))
293
+
294
+ @property
295
+ def frameworker_settings(self) -> CameraFrameWorkerSettings:
296
+ return deepcopy(self.camera_subject.value.get("frameWorkerSettings"))
297
+
298
+ @property
299
+ def sources(self) -> list[CameraSource]:
300
+ sources = deepcopy(self.camera_subject.value.get("sources"))
301
+ return [CameraSource(source, self) for source in sources]
302
+
303
+ @property
304
+ def stream_source(self) -> CameraSource:
305
+ source = self.high_resolution_source or self.mid_resolution_source or self.low_resolution_source
306
+ return cast(CameraSource, source)
307
+
308
+ @property
309
+ def snapshot_source(self) -> Optional[CameraSource]:
310
+ return next(source for source in self.sources if "snapshot" in source.roles)
311
+
312
+ @property
313
+ def high_resolution_source(self) -> Optional[CameraSource]:
314
+ return next(source for source in self.sources if "high-resolution" in source.roles)
315
+
316
+ @property
317
+ def mid_resolution_source(self) -> Optional[CameraSource]:
318
+ return next(source for source in self.sources if "mid-resolution" in source.roles)
319
+
320
+ @property
321
+ def low_resolution_source(self) -> Optional[CameraSource]:
322
+ return next(source for source in self.sources if "low-resolution" in source.roles)
323
+
324
+ async def init(self):
325
+ if self.initialized:
326
+ return
327
+
328
+ self.initialized = True
329
+
330
+ async def ignore_cb(e: Optional[Any] = None):
331
+ pass
332
+
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,
344
+ )
345
+
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
+ )
358
+
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
+ )
371
+
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,
396
+ )
397
+
398
+ 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(
406
+ self.logger,
407
+ self.publisher,
408
+ self.subscriber,
409
+ self.__request_handler,
410
+ )
411
+
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())
416
+
417
+ await self.refresh_states()
418
+
419
+ @overload
420
+ def set_delegate(self, name: Literal["cameraDelegate"], delegate: CameraDelegate) -> None: ...
421
+ @overload
422
+ def set_delegate(self, name: Literal["prebufferDelegate"], delegate: CameraPrebufferDelegate) -> None: ...
423
+ @overload
424
+ def set_delegate(self, name: Literal["ptzDelegate"], delegate: CameraPTZDelegate) -> None: ...
425
+ def set_delegate(self, name: Delegates, delegate: Any) -> None:
426
+ delegate = getattr(self, name, None)
427
+
428
+ if delegate:
429
+ delegate.delegate = delegate
430
+
431
+ async def connect(self) -> None:
432
+ return await self.on_request("cameraFn", "connect")
433
+
434
+ async def disconnect(self) -> None:
435
+ return await self.on_request("cameraFn", "disconnect")
436
+
437
+ @cached(cache=lambda self: self.snapshot_cache) # type: ignore
438
+ async def snapshot(self, force_new: Optional[bool] = None) -> bytes:
439
+ source = self.snapshot_source or self.stream_source
440
+ cache_key = source.id
441
+
442
+ snapshot_url = source.urls["www"]["jpegSnapshot"]
443
+ from_cache: Any = self.snapshot_cache.get(snapshot_url) if cache_key in self.snapshot_cache else None
444
+
445
+ if from_cache and not force_new:
446
+ return from_cache
447
+
448
+ if "snapshot" not in source.roles and self.camera_object["pluginId"] != "native":
449
+ snapshot = await self.cameraDelegate.snapshot()
450
+
451
+ if len(snapshot) > 0:
452
+ self.snapshot_cache[cache_key] = snapshot
453
+
454
+ return snapshot
455
+
456
+ async with aiohttp.ClientSession() as session, session.get(snapshot_url) as response:
457
+ if response.status != 200:
458
+ raise Exception(f"Status Code: {response.status}")
459
+
460
+ snapshot = await response.read()
461
+
462
+ if len(snapshot) > 0:
463
+ self.snapshot_cache[cache_key] = snapshot
464
+
465
+ return snapshot
466
+
467
+ async def get_frames(self, prebuffer_duration: int = 0) -> AsyncGenerator[VideoFrame, None]:
468
+ if not self.frame_publisher:
469
+ raise Exception("Frame Publisher is not initialized")
470
+
471
+ request_type: Literal["frame", "prebuffer"] = "frame"
472
+ prebuffer_duration = abs(prebuffer_duration)
473
+
474
+ if prebuffer_duration > 0:
475
+ request_type = "prebuffer"
476
+ prebuffer_duration = 5 if prebuffer_duration > 5 else prebuffer_duration
477
+
478
+ request_id = f"{str(uuid4())}-{request_type}"
479
+
480
+ try:
481
+ metadata = await self.__connect_to_decoder(request_id)
482
+
483
+ if not self.frame_subscriber:
484
+ self.frame_subscriber = await self.frame_publisher.subscribe(self.frame_subject)
485
+
486
+ async for msg in self.frame_subscriber.messages:
487
+ try:
488
+ if (
489
+ not self.initialized
490
+ or len(self.active_requests) == 0
491
+ or request_id not in self.active_requests
492
+ ):
493
+ break
494
+
495
+ if len(msg.data) == 0:
496
+ continue
497
+
498
+ frame_data: FrameData = unpack(msg.data)
499
+
500
+ yield VideoFrame(self.id, self.frame_publisher, frame_data, metadata, prebuffer_duration)
501
+ except Exception as e:
502
+ if self.initialized:
503
+ self.logger.error("Error while processing frame:", e)
504
+ else:
505
+ break
506
+
507
+ except asyncio.CancelledError:
508
+ pass
509
+ except Exception as e:
510
+ if self.initialized:
511
+ self.logger.error("Error while generating frames:", e)
512
+ finally:
513
+ self.tasks.add(self.__disconnect_from_decoder(request_id))
514
+
515
+ async def get_motion_frames(self) -> AsyncGenerator[MotionFrame, None]:
516
+ if not self.motion_frame_publisher:
517
+ raise Exception("Motion Frame Publisher is not initialized")
518
+
519
+ self.active_motion_requests += 1
520
+
521
+ try:
522
+ if not self.motion_frame_subscriber:
523
+ self.motion_frame_subscriber = await self.motion_frame_publisher.subscribe(
524
+ self.motion_frame_subject
525
+ )
526
+
527
+ async for msg in self.motion_frame_subscriber.messages:
528
+ try:
529
+ if not self.initialized or self.active_motion_requests <= 0:
530
+ break
531
+
532
+ if not msg or not msg.data or len(msg.data) == 0:
533
+ continue
534
+
535
+ motion_frame: FrameState = unpack(msg.data)
536
+ motion_state: MotionState = {
537
+ "timestamp": motion_frame["timestamp"],
538
+ "detections": motion_frame["detections"],
539
+ "lastEvent": motion_frame.get("lastEvent", None),
540
+ "state": motion_frame.get("state", False),
541
+ }
542
+
543
+ yield MotionFrame(
544
+ self.id,
545
+ self.motion_frame_publisher,
546
+ motion_frame["frameData"],
547
+ motion_state,
548
+ motion_frame["metadata"],
549
+ )
550
+ except Exception as e:
551
+ if self.initialized:
552
+ self.logger.error("Error while processing motion frame:", e)
553
+ else:
554
+ break
555
+
556
+ except asyncio.CancelledError:
557
+ pass
558
+ except Exception as e:
559
+ if self.initialized:
560
+ self.logger.error("Error while generating motion frames:", e)
561
+ finally:
562
+ self.active_motion_requests -= 1
563
+
564
+ if self.active_motion_requests <= 0:
565
+ self.tasks.add(self.__close_motion_frame_subscriber())
566
+
567
+ async def get_ffmpeg_path(self) -> str:
568
+ return await self.on_request("cameraFn", "getFfmpegPath")
569
+
570
+ async def get_ice_servers(self) -> list[IceServer]:
571
+ return await self.on_request("cameraFn", "getIceServers")
572
+
573
+ @overload
574
+ def get_value(self, state_name: Literal["light"]) -> LightState: ...
575
+ @overload
576
+ def get_value(self, state_name: Literal["motion"]) -> MotionState: ...
577
+ @overload
578
+ def get_value(self, state_name: Literal["audio"]) -> AudioState: ...
579
+ @overload
580
+ def get_value(self, state_name: Literal["object"]) -> ObjectState: ...
581
+ @overload
582
+ def get_value(self, state_name: Literal["doorbell"]) -> DoorbellState: ...
583
+ @overload
584
+ def get_value(self, state_name: Literal["siren"]) -> SirenState: ...
585
+ @overload
586
+ def get_value(self, state_name: Literal["battery"]) -> BatteryState: ...
587
+ def get_value(
588
+ self, state_name: str
589
+ ) -> Union[
590
+ LightState,
591
+ MotionState,
592
+ AudioState,
593
+ ObjectState,
594
+ DoorbellState,
595
+ SirenState,
596
+ BatteryState,
597
+ ]:
598
+ if state_name == "light":
599
+ return deepcopy(self.light_state.value)
600
+ elif state_name == "motion":
601
+ return deepcopy(self.motion_state.value)
602
+ elif state_name == "audio":
603
+ return deepcopy(self.audio_state.value)
604
+ elif state_name == "object":
605
+ return deepcopy(self.object_state.value)
606
+ elif state_name == "doorbell":
607
+ return deepcopy(self.doorbell_state.value)
608
+ elif state_name == "siren":
609
+ return deepcopy(self.siren_state.value)
610
+ elif state_name == "battery":
611
+ return deepcopy(self.battery_state.value)
612
+ else:
613
+ raise Exception(f"Unknown state: {state_name}")
614
+
615
+ @overload
616
+ async def update_state(
617
+ self,
618
+ state_name: Literal["light"],
619
+ event_data: LightSetEvent,
620
+ ) -> None: ...
621
+ @overload
622
+ async def update_state(
623
+ self,
624
+ state_name: Literal["motion"],
625
+ event_data: MotionSetEvent,
626
+ frame: Optional[VideoFrame] = None,
627
+ ) -> None: ...
628
+ @overload
629
+ async def update_state(
630
+ self,
631
+ state_name: Literal["audio"],
632
+ event_data: AudioSetEvent,
633
+ ) -> None: ...
634
+ @overload
635
+ async def update_state(
636
+ self,
637
+ state_name: Literal["object"],
638
+ event_data: ObjectSetEvent,
639
+ ) -> None: ...
640
+ @overload
641
+ async def update_state(
642
+ self,
643
+ state_name: Literal["doorbell"],
644
+ event_data: DoorbellSetEvent,
645
+ ) -> None: ...
646
+ @overload
647
+ async def update_state(
648
+ self,
649
+ state_name: Literal["siren"],
650
+ event_data: SirenSetEvent,
651
+ ) -> None: ...
652
+ @overload
653
+ async def update_state(
654
+ self,
655
+ state_name: Literal["battery"],
656
+ event_data: BatterySetEvent,
657
+ ) -> None: ...
658
+ async def update_state(
659
+ self,
660
+ state_name: Literal["light", "motion", "audio", "object", "doorbell", "siren", "battery"],
661
+ event_data: Union[
662
+ LightSetEvent,
663
+ MotionSetEvent,
664
+ AudioSetEvent,
665
+ ObjectSetEvent,
666
+ DoorbellSetEvent,
667
+ SirenSetEvent,
668
+ BatterySetEvent,
669
+ ],
670
+ frame: Optional[VideoFrame] = None,
671
+ ) -> None:
672
+ changed, event = cast(
673
+ tuple[
674
+ bool,
675
+ Union[
676
+ LightSetEvent,
677
+ MotionSetEvent,
678
+ AudioSetEvent,
679
+ ObjectSetEvent,
680
+ DoorbellSetEvent,
681
+ SirenSetEvent,
682
+ BatterySetEvent,
683
+ ],
684
+ ],
685
+ self.__check_state_internal(cast(Any, state_name), cast(Any, event_data)),
686
+ )
687
+
688
+ if not changed:
689
+ return
690
+
691
+ if state_name == "motion" and frame:
692
+ motion_event = cast(MotionState, event)
693
+ self.__frame_state.on_next(
694
+ {**motion_event, "frameData": frame.frame_data, "metadata": frame.metadata}
695
+ )
696
+
697
+ self.__update_state_internal(cast(Any, state_name), cast(Any, event), True)
698
+ await self.on_request("cameraFn", "updateState", [state_name, event], 0)
699
+
700
+ async def add_camera_source(self, source: CameraConfigInputSettings) -> None:
701
+ return await self.on_request("cameraFn", "addCameraSource", [source])
702
+
703
+ async def update_camera_source(self, source_id: str, source: CameraConfigInputSettingsPartial) -> None:
704
+ return await self.on_request("cameraFn", "updateCameraSource", [source_id, source])
705
+
706
+ async def remove_camera_source(self, source_id: str) -> None:
707
+ return await self.on_request("cameraFn", "removeCameraSource", [source_id])
708
+
709
+ async def refresh_states(self) -> None:
710
+ response = await self.on_request("cameraFn", "refreshStates")
711
+
712
+ self.update_camera(response["camera"])
713
+ self.update_camera_state(response["cameraState"])
714
+
715
+ for key, value in response["states"].items():
716
+ self.__update_state_internal(key, value, True)
717
+
718
+ def update_camera(self, camera: Camera) -> None:
719
+ self.camera_subject.on_next(camera)
720
+ self.update_camera_sources_state()
721
+
722
+ def update_prebuffer(self, source_id: str, container: Container, state: PrebufferState) -> None:
723
+ if (
724
+ source_id in self.prebuffer_state_subjects
725
+ and container in self.prebuffer_state_subjects[source_id]
726
+ ):
727
+ prebuffer_state: PrebufferState = {
728
+ "state": state["state"],
729
+ "url": state.get("url", None),
730
+ "duration": state["duration"],
731
+ }
732
+
733
+ self.prebuffer_state_subjects[source_id][container].on_next(prebuffer_state)
734
+
735
+ def update_camera_state(self, state: bool) -> None:
736
+ self.camera_state.on_next(state)
737
+
738
+ def update_camera_sources_state(self) -> None:
739
+ sources = self.camera_subject.value.get("sources")
740
+ source_ids_to_remove: list[str] = []
741
+
742
+ for source_id in self.prebuffer_state_subjects:
743
+ if not any(source["_id"] == source_id for source in sources):
744
+ for container in self.prebuffer_state_subjects[source_id]:
745
+ self.prebuffer_state_subjects[source_id][container].on_completed()
746
+
747
+ source_ids_to_remove.append(source_id)
748
+
749
+ for source_id in source_ids_to_remove:
750
+ del self.prebuffer_state_subjects[source_id]
751
+
752
+ def camera_source_prebuffer_state(self, source_id: str, container: Container) -> PrebufferState:
753
+ prebuffer_state: PrebufferState = {"state": False, "duration": 0}
754
+
755
+ if (
756
+ source_id in self.prebuffer_state_subjects
757
+ and container in self.prebuffer_state_subjects[source_id]
758
+ ):
759
+ prebuffer_state = self.prebuffer_state_subjects[source_id][container].value
760
+
761
+ return prebuffer_state
762
+
763
+ def remove_all_listeners(self) -> None:
764
+ self.__frame_state.on_completed()
765
+ self.light_state.on_completed()
766
+ self.motion_state.on_completed()
767
+ self.audio_state.on_completed()
768
+ self.object_state.on_completed()
769
+ self.doorbell_state.on_completed()
770
+ self.siren_state.on_completed()
771
+ self.battery_state.on_completed()
772
+ self.camera_subject.on_completed()
773
+ self.camera_state.on_completed()
774
+
775
+ async def cleanup(self) -> None:
776
+ self.initialized = False
777
+ self.remove_all_listeners()
778
+ self.api.remove_listener("shutdown", self.cleanup)
779
+ self.active_requests.clear()
780
+
781
+ if self.message_queue:
782
+ self.message_queue.abort_queue()
783
+
784
+ with suppress(Exception):
785
+ if self.publisher:
786
+ await self.publisher.close()
787
+
788
+ if self.camera_publisher:
789
+ await self.camera_publisher.close()
790
+
791
+ if self.signaling_publisher:
792
+ await self.signaling_publisher.close()
793
+
794
+ if self.frame_publisher:
795
+ await self.frame_publisher.close()
796
+
797
+ if self.motion_frame_publisher:
798
+ await self.motion_frame_publisher.close()
799
+
800
+ @overload
801
+ def on_state_change(self, state_name: Literal["light"]) -> Observable[tuple[LightState, LightState]]: ...
802
+ @overload
803
+ def on_state_change(
804
+ self, state_name: Literal["motion"]
805
+ ) -> Observable[tuple[MotionState, MotionState]]: ...
806
+ @overload
807
+ def on_state_change(self, state_name: Literal["audio"]) -> Observable[tuple[AudioState, AudioState]]: ...
808
+ @overload
809
+ def on_state_change(
810
+ self, state_name: Literal["doorbell"]
811
+ ) -> Observable[tuple[DoorbellState, DoorbellState]]: ...
812
+ @overload
813
+ def on_state_change(self, state_name: Literal["siren"]) -> Observable[tuple[SirenState, SirenState]]: ...
814
+ @overload
815
+ def on_state_change(
816
+ self, state_name: Literal["battery"]
817
+ ) -> Observable[tuple[BatteryState, BatteryState]]: ...
818
+ @overload
819
+ def on_state_change(
820
+ self, state_name: Literal["object"]
821
+ ) -> Observable[tuple[ObjectState, ObjectState]]: ...
822
+ def on_state_change(self, state_name: StateNames) -> Observable[tuple[StateValue, StateValue]]:
823
+ state: Union[BehaviorSubject[StateValue], None] = getattr(self, f"{state_name}_state", None)
824
+
825
+ if not state:
826
+ raise Exception(f"{state_name}_state not found")
827
+
828
+ def filter_fn(states: tuple[StateValue, StateValue]) -> bool:
829
+ old_state = states[0]
830
+ new_state = states[1]
831
+
832
+ if isinstance(old_state, bool) or isinstance(new_state, bool):
833
+ return old_state != new_state
834
+ else:
835
+ return self.__state_changed(old_state, new_state, state_name)
836
+
837
+ return state.pipe(
838
+ ops.pairwise(),
839
+ ops.filter(filter_fn),
840
+ ops.share(),
841
+ )
842
+
843
+ def on_property_change(
844
+ self, property: Union[CameraPublicProperties, list[CameraPublicProperties]]
845
+ ) -> Observable[CameraPropertyObservableObject]:
846
+ def map_fn(
847
+ cameras: tuple[Camera, Camera],
848
+ ) -> list[Any]:
849
+ properties = property if isinstance(property, list) else [property]
850
+ return [
851
+ {
852
+ "property": prop,
853
+ "old_state": cameras[0].get(prop),
854
+ "new_state": cameras[1].get(prop),
855
+ }
856
+ for prop in properties
857
+ ]
858
+
859
+ def filter_fn(
860
+ cameras: tuple[CameraPropertyObservableObject, CameraPropertyObservableObject],
861
+ ) -> bool:
862
+ return (
863
+ DeepDiff(
864
+ cameras[0]["old_state"],
865
+ cameras[1]["new_state"],
866
+ ignore_order=True,
867
+ )
868
+ != {}
869
+ )
870
+
871
+ return self.camera_subject.pipe(
872
+ ops.pairwise(),
873
+ ops.flat_map(map_fn),
874
+ ops.filter(filter_fn),
875
+ ops.share(),
876
+ )
877
+
878
+ def __on_motion_frame(self, motion_frame: FrameState) -> None:
879
+ if not self.frame_publisher:
880
+ return
881
+
882
+ self.tasks.add(self.__send_motion_frame(motion_frame))
883
+
884
+ async def __send_motion_frame(self, frame: FrameState) -> None:
885
+ if not self.frame_publisher:
886
+ return
887
+
888
+ await self.frame_publisher.publish(
889
+ self.motion_frame_subject,
890
+ pack(frame),
891
+ )
892
+
893
+ @overload
894
+ def __check_state_internal(
895
+ self, state_name: Literal["light"], event_data: LightSetEvent
896
+ ) -> tuple[bool, LightState]: ...
897
+ @overload
898
+ def __check_state_internal(
899
+ self, state_name: Literal["motion"], event_data: MotionSetEvent
900
+ ) -> tuple[bool, MotionState]: ...
901
+ @overload
902
+ def __check_state_internal(
903
+ self, state_name: Literal["audio"], event_data: AudioSetEvent
904
+ ) -> tuple[bool, AudioState]: ...
905
+ @overload
906
+ def __check_state_internal(
907
+ self, state_name: Literal["object"], event_data: ObjectSetEvent
908
+ ) -> tuple[bool, ObjectState]: ...
909
+ @overload
910
+ def __check_state_internal(
911
+ self, state_name: Literal["doorbell"], event_data: DoorbellSetEvent
912
+ ) -> tuple[bool, DoorbellState]: ...
913
+ @overload
914
+ def __check_state_internal(
915
+ self, state_name: Literal["siren"], event_data: SirenSetEvent
916
+ ) -> tuple[bool, SirenState]: ...
917
+ @overload
918
+ def __check_state_internal(
919
+ self, state_name: Literal["battery"], event_data: BatterySetEvent
920
+ ) -> tuple[bool, BatteryState]: ...
921
+ def __check_state_internal(
922
+ self,
923
+ state_name: Literal["light", "motion", "audio", "object", "doorbell", "siren", "battery"],
924
+ event_data: Union[
925
+ LightSetEvent,
926
+ MotionSetEvent,
927
+ AudioSetEvent,
928
+ ObjectSetEvent,
929
+ DoorbellSetEvent,
930
+ SirenSetEvent,
931
+ BatterySetEvent,
932
+ ],
933
+ ) -> tuple[
934
+ bool,
935
+ Union[
936
+ LightState,
937
+ MotionState,
938
+ AudioState,
939
+ ObjectState,
940
+ DoorbellState,
941
+ SirenState,
942
+ BatteryState,
943
+ ],
944
+ ]:
945
+ changed = False
946
+ target_state = None
947
+
948
+ if state_name == "audio":
949
+ audio_event = cast(AudioSetEvent, event_data)
950
+ target_state = self.__get_audio_state(audio_event)
951
+ changed = self.__state_changed(self.get_value("audio"), target_state, "audio")
952
+
953
+ elif state_name == "light":
954
+ light_event = cast(LightSetEvent, event_data)
955
+ target_state = self.__get_light_state(light_event)
956
+ changed = self.__state_changed(self.get_value("light"), target_state, "light")
957
+
958
+ elif state_name == "motion":
959
+ motion_event = cast(MotionSetEvent, event_data)
960
+
961
+ if motion_event.get("state", None) is not None:
962
+ motion_event["detections"] = []
963
+
964
+ # fix bounding box type to to tuple, do we need?
965
+ for det in motion_event["detections"]:
966
+ det["boundingBox"] = cast(tuple[int, int, int, int], tuple(det["boundingBox"]))
967
+ det["confidence"] = float(det["confidence"])
968
+
969
+ motion_event["detections"] = are_motion_detections_valid(
970
+ motion_event["detections"], self.activity_zones, self.activity_settings
971
+ )
972
+
973
+ target_state = self.__get_motion_state(motion_event)
974
+ changed = self.__state_changed(self.get_value("motion"), target_state, "motion")
975
+
976
+ elif state_name == "object":
977
+ object_event = cast(ObjectSetEvent, event_data)
978
+
979
+ # fix bounding box type to to tuple
980
+ for det in object_event["detections"]:
981
+ det["boundingBox"] = tuple(det["boundingBox"]) # type: ignore
982
+ det["confidence"] = float(det["confidence"])
983
+
984
+ object_event["detections"] = are_object_detections_valid(
985
+ object_event["detections"], self.activity_zones, self.activity_settings
986
+ )
987
+
988
+ target_state = self.__get_object_state(object_event)
989
+ changed = self.__state_changed(self.get_value("object"), target_state, "object")
990
+
991
+ elif state_name == "doorbell":
992
+ doorbell_event = cast(DoorbellSetEvent, event_data)
993
+ target_state = self.__get_doorbell_state(doorbell_event)
994
+ changed = self.__state_changed(self.get_value("doorbell"), target_state, "doorbell")
995
+
996
+ elif state_name == "siren":
997
+ siren_event = cast(SirenSetEvent, event_data)
998
+ target_state = self.__get_siren_state(siren_event)
999
+ changed = self.__state_changed(self.get_value("siren"), target_state, "siren")
1000
+
1001
+ elif state_name == "battery":
1002
+ battery_event = cast(BatterySetEvent, event_data)
1003
+ target_state = self.__get_battery_state(battery_event)
1004
+ changed = self.__state_changed(self.get_value("battery"), target_state, "battery")
1005
+
1006
+ else:
1007
+ raise Exception(f"Unknown state: {state_name}")
1008
+
1009
+ return changed, target_state
1010
+
1011
+ @overload
1012
+ def __update_state_internal(
1013
+ self, state_name: Literal["light"], event_data: LightSetEvent, skip_check: Optional[bool] = None
1014
+ ) -> None: ...
1015
+ @overload
1016
+ def __update_state_internal(
1017
+ self, state_name: Literal["motion"], event_data: MotionSetEvent, skip_check: Optional[bool] = None
1018
+ ) -> None: ...
1019
+ @overload
1020
+ def __update_state_internal(
1021
+ self, state_name: Literal["audio"], event_data: AudioSetEvent, skip_check: Optional[bool] = None
1022
+ ) -> None: ...
1023
+ @overload
1024
+ def __update_state_internal(
1025
+ self, state_name: Literal["object"], event_data: ObjectSetEvent, skip_check: Optional[bool] = None
1026
+ ) -> None: ...
1027
+ @overload
1028
+ def __update_state_internal(
1029
+ self, state_name: Literal["doorbell"], event_data: DoorbellSetEvent, skip_check: Optional[bool] = None
1030
+ ) -> None: ...
1031
+ @overload
1032
+ def __update_state_internal(
1033
+ self, state_name: Literal["siren"], event_data: SirenSetEvent, skip_check: Optional[bool] = None
1034
+ ) -> None: ...
1035
+ @overload
1036
+ def __update_state_internal(
1037
+ self, state_name: Literal["battery"], event_data: BatterySetEvent, skip_check: Optional[bool] = None
1038
+ ) -> None: ...
1039
+ def __update_state_internal(
1040
+ self,
1041
+ state_name: Literal["light", "motion", "audio", "object", "doorbell", "siren", "battery"],
1042
+ event_data: Union[
1043
+ LightSetEvent,
1044
+ MotionSetEvent,
1045
+ AudioSetEvent,
1046
+ ObjectSetEvent,
1047
+ DoorbellSetEvent,
1048
+ SirenSetEvent,
1049
+ BatterySetEvent,
1050
+ ],
1051
+ skip_check: Optional[bool] = None,
1052
+ ) -> None:
1053
+ if skip_check:
1054
+ changed = True
1055
+ event = event_data
1056
+ else:
1057
+ changed, event = cast(
1058
+ tuple[
1059
+ bool,
1060
+ Union[
1061
+ LightSetEvent,
1062
+ MotionSetEvent,
1063
+ AudioSetEvent,
1064
+ ObjectSetEvent,
1065
+ DoorbellSetEvent,
1066
+ SirenSetEvent,
1067
+ BatterySetEvent,
1068
+ ],
1069
+ ],
1070
+ self.__check_state_internal(cast(Any, state_name), cast(Any, event_data)),
1071
+ )
1072
+
1073
+ if not changed:
1074
+ return
1075
+
1076
+ if state_name == "light":
1077
+ self.light_state.on_next(self.__get_light_state(cast(LightSetEvent, event)))
1078
+ elif state_name == "motion":
1079
+ self.motion_state.on_next(self.__get_motion_state(cast(MotionSetEvent, event)))
1080
+ elif state_name == "audio":
1081
+ self.audio_state.on_next(self.__get_audio_state(cast(AudioSetEvent, event)))
1082
+ elif state_name == "object":
1083
+ self.object_state.on_next(self.__get_object_state(cast(ObjectSetEvent, event)))
1084
+ elif state_name == "doorbell":
1085
+ self.doorbell_state.on_next(self.__get_doorbell_state(cast(DoorbellSetEvent, event)))
1086
+ elif state_name == "siren":
1087
+ self.siren_state.on_next(self.__get_siren_state(cast(SirenSetEvent, event)))
1088
+ elif state_name == "battery" and self.has_battery:
1089
+ self.battery_state.on_next(self.__get_battery_state(cast(BatterySetEvent, event)))
1090
+
1091
+ def __create_motion_frame_observable(self) -> Observable[FrameState]:
1092
+ return self.__frame_state.pipe(ops.share())
1093
+
1094
+ def __create_state_observable(self, state_subject: BehaviorSubject[Any]) -> Observable[Any]:
1095
+ return state_subject.pipe(ops.share())
1096
+
1097
+ def __state_changed(
1098
+ self,
1099
+ old_state: Optional[SetValue],
1100
+ new_state: Optional[SetValue],
1101
+ type: Optional[StateNames],
1102
+ ) -> bool:
1103
+ if not old_state or not new_state or not type:
1104
+ return False
1105
+
1106
+ if type == "audio":
1107
+ if not self.has_audio_detector:
1108
+ return False
1109
+
1110
+ old_state = cast(AudioSetEvent, old_state)
1111
+ new_state = cast(AudioSetEvent, new_state)
1112
+
1113
+ return old_state["state"] != new_state["state"] or old_state.get("db") != new_state.get("db")
1114
+ elif type == "motion":
1115
+ if not self.has_motion_detector:
1116
+ return False
1117
+
1118
+ old_state = cast(MotionSetEvent, old_state)
1119
+ new_state = cast(MotionSetEvent, new_state)
1120
+
1121
+ if new_state.get("state", None) is not None:
1122
+ return old_state.get("state", False) != new_state.get("state", False)
1123
+
1124
+ # if len(new_state["detections"]) == 0:
1125
+ # return False
1126
+
1127
+ return (
1128
+ DeepDiff(
1129
+ old_state["detections"],
1130
+ new_state["detections"],
1131
+ ignore_order=True,
1132
+ )
1133
+ != {}
1134
+ )
1135
+ elif type == "object":
1136
+ if not self.has_object_detector:
1137
+ return False
1138
+
1139
+ old_state = cast(ObjectSetEvent, old_state)
1140
+ new_state = cast(ObjectSetEvent, new_state)
1141
+
1142
+ # if len(new_state["detections"]) == 0:
1143
+ # return False
1144
+
1145
+ return (
1146
+ DeepDiff(
1147
+ old_state["detections"],
1148
+ new_state["detections"],
1149
+ ignore_order=True,
1150
+ )
1151
+ != {}
1152
+ )
1153
+ elif type == "siren":
1154
+ if not self.has_siren:
1155
+ return False
1156
+
1157
+ old_state = cast(SirenSetEvent, old_state)
1158
+ new_state = cast(SirenSetEvent, new_state)
1159
+
1160
+ return old_state["state"] != new_state["state"] or old_state.get("level") != new_state.get(
1161
+ "level"
1162
+ )
1163
+ elif type == "battery":
1164
+ if not self.has_battery:
1165
+ return False
1166
+
1167
+ old_state = cast(BatterySetEvent, old_state)
1168
+ new_state = cast(BatterySetEvent, new_state)
1169
+
1170
+ return (
1171
+ old_state["level"] != new_state["level"]
1172
+ or old_state.get("lowBattery") != new_state.get("lowBattery")
1173
+ or old_state.get("charging") != new_state.get("charging")
1174
+ )
1175
+ elif type == "doorbell":
1176
+ if not self.has_binary_sensor:
1177
+ return False
1178
+
1179
+ old_state = cast(DoorbellSetEvent, old_state)
1180
+ new_state = cast(DoorbellSetEvent, new_state)
1181
+
1182
+ return old_state["state"] != new_state["state"]
1183
+ elif type == "light":
1184
+ if not self.has_light:
1185
+ return False
1186
+
1187
+ old_state = cast(LightSetEvent, old_state)
1188
+ new_state = cast(LightSetEvent, new_state)
1189
+
1190
+ return old_state["state"] != new_state["state"]
1191
+ else:
1192
+ return False
1193
+
1194
+ def create_prebuffer_state_observable(
1195
+ self, source_id: str, container: Container
1196
+ ) -> Observable[PrebufferState]:
1197
+ if source_id not in self.prebuffer_state_subjects:
1198
+ self.prebuffer_state_subjects[source_id] = {}
1199
+
1200
+ if container not in self.prebuffer_state_subjects[source_id]:
1201
+ self.prebuffer_state_subjects[source_id][container] = BehaviorSubject(
1202
+ {"state": False, "duration": 0}
1203
+ )
1204
+
1205
+ return self.prebuffer_state_subjects[source_id][container].pipe(
1206
+ ops.distinct_until_changed(comparer=self.__prebuffer_state_comperator),
1207
+ ops.share(),
1208
+ )
1209
+
1210
+ def __prebuffer_state_comperator(
1211
+ self, previous_state: PrebufferState, current_state: PrebufferState
1212
+ ) -> bool:
1213
+ return previous_state["state"] == current_state["state"] and previous_state.get(
1214
+ "url"
1215
+ ) == current_state.get("url")
1216
+
1217
+ def __get_audio_state(self, event: AudioSetEvent, ignore_last_event: bool = False) -> AudioState:
1218
+ last_event: Optional[AudioState] = None
1219
+
1220
+ if ignore_last_event is False:
1221
+ last_state = self.get_value("audio")
1222
+
1223
+ if last_state["state"]:
1224
+ last_event = last_state
1225
+ elif "lastEvent" in last_state and last_state["lastEvent"] and last_state["lastEvent"]["state"]:
1226
+ last_event = last_state["lastEvent"] # type: ignore
1227
+
1228
+ if last_event and "lastEvent" in last_event:
1229
+ del last_event["lastEvent"]
1230
+
1231
+ new_state: AudioState
1232
+
1233
+ if "timestamp" in event:
1234
+ new_state = event
1235
+ else:
1236
+ state = cast(AudioState, event).copy()
1237
+ state["timestamp"] = int(datetime.now().timestamp() * 1000)
1238
+
1239
+ new_state = {
1240
+ "state": event["state"],
1241
+ "db": event.get("db", None) or last_event.get("db", None) if last_event else 0,
1242
+ "timestamp": int(datetime.now().timestamp() * 1000),
1243
+ "lastEvent": last_event if last_event else state if state["state"] else None,
1244
+ }
1245
+
1246
+ return new_state
1247
+
1248
+ def __get_motion_state(self, event: MotionSetEvent, ignore_last_event: bool = False) -> MotionState:
1249
+ last_event: Optional[MotionState] = None
1250
+
1251
+ if ignore_last_event is False:
1252
+ last_state = self.get_value("motion")
1253
+
1254
+ if len(last_state["detections"]) > 0:
1255
+ last_event = last_state
1256
+ elif (
1257
+ "lastEvent" in last_state
1258
+ and last_state["lastEvent"] is not None
1259
+ and len(last_state["lastEvent"]["detections"]) > 0
1260
+ ):
1261
+ last_event = last_state["lastEvent"] # type: ignore
1262
+
1263
+ if last_event and "lastEvent" in last_event:
1264
+ del last_event["lastEvent"]
1265
+
1266
+ new_state: MotionState
1267
+
1268
+ if "timestamp" in event:
1269
+ new_state = event
1270
+ else:
1271
+ state = cast(MotionState, event).copy()
1272
+ state["timestamp"] = int(datetime.now().timestamp() * 1000)
1273
+
1274
+ new_state = {
1275
+ "detections": event["detections"],
1276
+ "timestamp": int(datetime.now().timestamp() * 1000),
1277
+ "lastEvent": last_event if last_event else state if len(state["detections"]) > 0 else None,
1278
+ }
1279
+
1280
+ return new_state
1281
+
1282
+ def __get_object_state(self, event: ObjectSetEvent, ignore_last_event: bool = False) -> ObjectState:
1283
+ last_event: Optional[ObjectState] = None
1284
+
1285
+ if ignore_last_event is False:
1286
+ last_state = self.get_value("object")
1287
+
1288
+ if len(last_state["detections"]) > 0:
1289
+ last_event = last_state
1290
+ elif (
1291
+ "lastEvent" in last_state
1292
+ and last_state["lastEvent"]
1293
+ and len(last_state["lastEvent"]["detections"]) > 0
1294
+ ):
1295
+ last_event = last_state["lastEvent"] # type: ignore
1296
+
1297
+ if last_event and "lastEvent" in last_event:
1298
+ del last_event["lastEvent"]
1299
+
1300
+ new_state: ObjectState
1301
+
1302
+ if "timestamp" in event:
1303
+ new_state = event
1304
+ else:
1305
+ state = cast(ObjectState, event).copy()
1306
+ state["timestamp"] = int(datetime.now().timestamp() * 1000)
1307
+
1308
+ new_state = {
1309
+ "detections": event["detections"],
1310
+ "timestamp": int(datetime.now().timestamp() * 1000),
1311
+ "lastEvent": last_event if last_event else state if len(state["detections"]) > 0 else None,
1312
+ }
1313
+
1314
+ return new_state
1315
+
1316
+ def __get_doorbell_state(self, event: DoorbellSetEvent, ignore_last_event: bool = False) -> DoorbellState:
1317
+ last_event: Optional[DoorbellState] = None
1318
+
1319
+ if ignore_last_event is False:
1320
+ last_state = self.get_value("doorbell")
1321
+
1322
+ if last_state["state"]:
1323
+ last_event = last_state
1324
+ elif "lastEvent" in last_state and last_state["lastEvent"] and last_state["lastEvent"]["state"]:
1325
+ last_event = last_state["lastEvent"] # type: ignore
1326
+
1327
+ if last_event and "lastEvent" in last_event:
1328
+ del last_event["lastEvent"]
1329
+
1330
+ new_state: DoorbellState
1331
+
1332
+ if "timestamp" in event:
1333
+ new_state = event
1334
+ else:
1335
+ state = cast(DoorbellState, event).copy()
1336
+ state["timestamp"] = int(datetime.now().timestamp() * 1000)
1337
+
1338
+ new_state = {
1339
+ "state": event["state"],
1340
+ "timestamp": int(datetime.now().timestamp() * 1000),
1341
+ "lastEvent": last_event if last_event else state if state["state"] else None,
1342
+ }
1343
+
1344
+ return new_state
1345
+
1346
+ def __get_light_state(self, event: LightSetEvent, ignore_last_event: bool = False) -> LightState:
1347
+ last_event: Optional[LightState] = None
1348
+
1349
+ if ignore_last_event is False:
1350
+ last_state = self.get_value("light")
1351
+
1352
+ if last_state["state"]:
1353
+ last_event = last_state
1354
+ elif "lastEvent" in last_state and last_state["lastEvent"] and last_state["lastEvent"]["state"]:
1355
+ last_event = last_state["lastEvent"] # type: ignore
1356
+
1357
+ if last_event and "lastEvent" in last_event:
1358
+ del last_event["lastEvent"]
1359
+
1360
+ new_state: LightState
1361
+
1362
+ if "timestamp" in event:
1363
+ new_state = event
1364
+ else:
1365
+ state = cast(LightState, event).copy()
1366
+ state["timestamp"] = int(datetime.now().timestamp() * 1000)
1367
+
1368
+ new_state = {
1369
+ **state,
1370
+ "lastEvent": last_event if last_event else state if state["state"] else None,
1371
+ }
1372
+
1373
+ return new_state
1374
+
1375
+ def __get_siren_state(self, event: SirenSetEvent, ignore_last_event: bool = False) -> SirenState:
1376
+ last_event: Optional[SirenState] = None
1377
+
1378
+ if ignore_last_event is False:
1379
+ last_state = self.get_value("siren")
1380
+
1381
+ if last_state["state"]:
1382
+ last_event = last_state
1383
+ elif "lastEvent" in last_state and last_state["lastEvent"] and last_state["lastEvent"]["state"]:
1384
+ last_event = last_state["lastEvent"] # type: ignore
1385
+
1386
+ if last_event and "lastEvent" in last_event:
1387
+ del last_event["lastEvent"]
1388
+
1389
+ new_state: SirenState
1390
+
1391
+ if "timestamp" in event:
1392
+ new_state = event
1393
+ else:
1394
+ state = cast(SirenState, event).copy()
1395
+ state["timestamp"] = int(datetime.now().timestamp() * 1000)
1396
+
1397
+ new_state = {
1398
+ "state": event["state"],
1399
+ "level": event.get("level", None) or last_event.get("level", None) if last_event else 0,
1400
+ "timestamp": int(datetime.now().timestamp() * 1000),
1401
+ "lastEvent": last_event if last_event else state if state["state"] else None,
1402
+ }
1403
+
1404
+ return new_state
1405
+
1406
+ def __get_battery_state(self, event: BatterySetEvent, ignore_last_event: bool = False) -> BatteryState:
1407
+ last_event: Optional[BatteryState] = None
1408
+
1409
+ if ignore_last_event is False:
1410
+ last_state = self.get_value("battery")
1411
+
1412
+ if self.__state_changed(last_state, event, "battery"):
1413
+ last_event = last_state
1414
+ elif (
1415
+ "lastEvent" in last_state
1416
+ and last_state["lastEvent"]
1417
+ and self.__state_changed(last_state["lastEvent"], event, "battery")
1418
+ ):
1419
+ last_event = last_state["lastEvent"] # type: ignore
1420
+
1421
+ if last_event and "lastEvent" in last_event:
1422
+ del last_event["lastEvent"]
1423
+
1424
+ new_state: BatteryState
1425
+
1426
+ if "timestamp" in event:
1427
+ new_state = event
1428
+ else:
1429
+ state = cast(BatteryState, event).copy()
1430
+ state["timestamp"] = int(datetime.now().timestamp() * 1000)
1431
+
1432
+ new_state = {
1433
+ "level": event["level"],
1434
+ "charging": event.get("charging", None) or last_event.get("charging", None)
1435
+ if last_event
1436
+ else False,
1437
+ "lowBattery": event.get("lowBattery", None) or last_event.get("lowBattery", None)
1438
+ if last_event
1439
+ else False,
1440
+ "timestamp": int(datetime.now().timestamp() * 1000),
1441
+ "lastEvent": last_event if last_event else state,
1442
+ }
1443
+
1444
+ return new_state
1445
+
1446
+ async def __connect_to_decoder(self, request_id: str) -> FrameMetadata:
1447
+ if not self.signaling_publisher:
1448
+ raise Exception("Signaling Publisher not initialized")
1449
+
1450
+ message: SignalingRequest = {
1451
+ "type": "connect",
1452
+ "requestId": request_id,
1453
+ "cameraId": self.id,
1454
+ "pluginId": self.plugin["id"],
1455
+ }
1456
+
1457
+ await self.signaling_publisher.publish(
1458
+ self.signaling_target_subject,
1459
+ pack(message),
1460
+ )
1461
+
1462
+ self.active_requests.add(request_id)
1463
+
1464
+ metadata = await self.__get_metadata(request_id, 60)
1465
+
1466
+ if not metadata:
1467
+ raise Exception("Invalid metadata response")
1468
+
1469
+ return metadata
1470
+
1471
+ async def __get_metadata(self, request_id: str, timeout: int) -> Union[FrameMetadata, None]:
1472
+ if not self.signaling_publisher:
1473
+ raise Exception("Signaling Publisher not initialized")
1474
+
1475
+ try:
1476
+ metadata_request: SignalingRequest = {
1477
+ "type": "metadata",
1478
+ "requestId": request_id,
1479
+ "cameraId": self.id,
1480
+ "pluginId": self.plugin["id"],
1481
+ }
1482
+
1483
+ metadata_msg = await self.signaling_publisher.request(
1484
+ self.signaling_target_subject,
1485
+ pack(metadata_request),
1486
+ timeout=timeout,
1487
+ )
1488
+
1489
+ metadata_response: SignalingResponse = unpack(metadata_msg.data)
1490
+ metadata = metadata_response.get("metadata")
1491
+
1492
+ return metadata
1493
+ except: # noqa: E722
1494
+ self.logger.error("Failed to get metadata! Frame Worker FFmpeg process might not be running")
1495
+
1496
+ async def __disconnect_from_decoder(self, request_id: str) -> None:
1497
+ if request_id in self.active_requests:
1498
+ self.active_requests.remove(request_id)
1499
+
1500
+ if not self.signaling_publisher:
1501
+ raise Exception("Signaling Publisher not initialized")
1502
+
1503
+ if self.signaling_publisher.is_closed:
1504
+ return
1505
+
1506
+ message: SignalingRequest = {
1507
+ "type": "disconnect",
1508
+ "requestId": request_id,
1509
+ "cameraId": self.id,
1510
+ "pluginId": self.plugin["id"],
1511
+ }
1512
+
1513
+ await self.signaling_publisher.publish(self.signaling_target_subject, pack(message))
1514
+
1515
+ async def __close_frame_subscriber(self) -> None:
1516
+ with suppress(Exception):
1517
+ if self.frame_subscriber:
1518
+ await self.frame_subscriber.unsubscribe()
1519
+ self.frame_subscriber = None
1520
+
1521
+ async def __close_motion_frame_subscriber(self) -> None:
1522
+ if self.motion_frame_subscriber:
1523
+ with suppress(Exception):
1524
+ await self.motion_frame_subscriber.unsubscribe()
1525
+
1526
+ self.motion_frame_subscriber = None
1527
+
1528
+ async def __request_handler(self, message: ProxyMessageStructure) -> None:
1529
+ if not self.message_queue:
1530
+ raise Exception("Message queue not initialized")
1531
+
1532
+ try:
1533
+ if (
1534
+ message["client"] == "cameraDelegate"
1535
+ or message["client"] == "prebufferDelegate"
1536
+ or message["client"] == "ptzDelegate"
1537
+ ):
1538
+ delegate = getattr(self, message["client"], None)
1539
+
1540
+ if not delegate:
1541
+ raise Exception(f"Delegate not set: {message['client']}")
1542
+
1543
+ fn: Any = message.get("fn")
1544
+ args = message.get("args", [])
1545
+
1546
+ if not hasattr(delegate, fn) and not callable(getattr(delegate, fn)):
1547
+ raise Exception(f"Unknown delegate function: {message['client']} ({fn})")
1548
+
1549
+ method_to_call = getattr(delegate, fn)
1550
+
1551
+ if inspect.iscoroutinefunction(method_to_call):
1552
+ response = await method_to_call(*args)
1553
+ else:
1554
+ response = method_to_call(*args)
1555
+
1556
+ await self.message_queue.enqueue({**message, "type": "reply", "response": response})
1557
+ elif message.get("client") == "cameraFn":
1558
+ fn: Any = message.get("fn")
1559
+ args = message.get("args", [])
1560
+
1561
+ if not hasattr(self, fn) and not callable(getattr(self, fn)):
1562
+ raise Exception(f"Unknown camera function: {fn}")
1563
+
1564
+ method_to_call = getattr(self, fn)
1565
+
1566
+ if inspect.iscoroutinefunction(method_to_call):
1567
+ response = await method_to_call(*args)
1568
+ else:
1569
+ response = method_to_call(*args)
1570
+
1571
+ await self.message_queue.enqueue({**message, "type": "reply", "response": response})
1572
+ else:
1573
+ await self.message_queue.enqueue({**message, "type": "reply"})
1574
+
1575
+ except Exception as e:
1576
+ deserialized_error: DeserializedError = {
1577
+ "name": type(e).__name__,
1578
+ "message": str(e),
1579
+ "stack": traceback.format_exc(),
1580
+ }
1581
+
1582
+ await self.message_queue.enqueue({**message, "type": "reply", "error": deserialized_error})
1583
+
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
1622
+
1623
+ async def __listen_to_signaling_messages(self) -> None:
1624
+ if not self.signaling_subscriber:
1625
+ raise Exception("Subscriber not initialized")
1626
+
1627
+ async for msg in self.signaling_subscriber.messages:
1628
+ try:
1629
+ if not self.initialized:
1630
+ break
1631
+
1632
+ if len(msg.data) == 0:
1633
+ continue
1634
+
1635
+ message: Union[SignalingResponse, PingMessage] = unpack(msg.data)
1636
+
1637
+ if message["type"] == "ping":
1638
+ if message["requestId"] in self.active_requests:
1639
+ self.tasks.add(self.__respond_to_signaling_message(msg, message))
1640
+
1641
+ elif message["type"] == "disconnect":
1642
+ if message["requestId"] in self.active_requests:
1643
+ self.active_requests.remove(message["requestId"])
1644
+
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
1652
+
1653
+ async def __respond_to_signaling_message(self, msg: Msg, message: PingMessage) -> None:
1654
+ try:
1655
+ pong_message: PongMessage = {
1656
+ "type": "pong",
1657
+ "requestId": message["requestId"],
1658
+ }
1659
+
1660
+ await msg.respond(pack(pong_message))
1661
+ except Exception as e:
1662
+ if self.initialized:
1663
+ self.logger.error("Error while processing singaling respond:", e)
1664
+
1665
+ @overload
1666
+ async def on_request(
1667
+ self,
1668
+ client: Literal["cameraFn"],
1669
+ fn: CameraDeviceProxyMethodNames,
1670
+ args: list[Any] = [],
1671
+ timeout: int = 5000,
1672
+ ) -> Any: ...
1673
+ @overload
1674
+ async def on_request(
1675
+ self,
1676
+ client: Literal["cameraDelegate"],
1677
+ fn: CameraDelegateMethodNames,
1678
+ args: list[Any] = [],
1679
+ timeout: int = 5000,
1680
+ ) -> Any: ...
1681
+ @overload
1682
+ async def on_request(
1683
+ self,
1684
+ client: Literal["prebufferDelegate"],
1685
+ fn: CameraPrebufferDelegateMethodNames,
1686
+ args: list[Any] = [],
1687
+ timeout: int = 5000,
1688
+ ) -> Any: ...
1689
+ @overload
1690
+ async def on_request(
1691
+ self,
1692
+ client: Literal["ptzDelegate"],
1693
+ fn: CameraPTZDelegateMethodNames,
1694
+ args: list[Any] = [],
1695
+ timeout: int = 5000,
1696
+ ) -> Any: ...
1697
+ async def on_request(
1698
+ self,
1699
+ client: ClientType,
1700
+ fn: Any,
1701
+ args: list[Any] = [],
1702
+ timeout: int = 5000,
1703
+ ) -> Any:
1704
+ if not self.message_queue:
1705
+ raise Exception("Message queue not initialized")
1706
+
1707
+ message: ProxyMessageStructure = {
1708
+ "requestId": str(uuid4()),
1709
+ "targetId": self.subject,
1710
+ "targetName": self.name,
1711
+ "pluginId": self.plugin["id"],
1712
+ "cameraId": self.id,
1713
+ "type": "request",
1714
+ "proxy": "camera",
1715
+ "client": "cameraFn",
1716
+ "fn": fn,
1717
+ "args": args,
1718
+ "timestamp": int(datetime.now().timestamp() * 1000),
1719
+ "timeout": timeout,
1720
+ }
1721
+
1722
+ return await self.message_queue.enqueue(message)