@camera.ui/server 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/interface/{@tanstack.B2I9xtA-.0.0.15.js → @tanstack.Y8LHKTFF.0.0.17.js} +1 -1
- package/dist/interface/{@vee-validate.DWN48z-b.0.0.15.js → @vee-validate.BcG8e5-Z.0.0.17.js} +1 -1
- package/dist/interface/{@vueform.DKPuos4k.0.0.15.js → @vueform.Cnqje5-g.0.0.17.js} +1 -1
- package/dist/interface/{@vueuse.Co4EnWOQ.0.0.15.js → @vueuse.CxdA24o0.0.0.17.js} +1 -1
- package/dist/interface/Account.K0D29-KE.0.0.17.js +1 -0
- package/dist/interface/{Adminpanel.BhbCmzrT.0.0.15.js → Adminpanel.CaLBYPHc.0.0.17.js} +2 -2
- package/dist/interface/{Appearance.CwONb7W2.0.0.15.js → Appearance.-L_mn_-o.0.0.17.js} +1 -1
- package/dist/interface/{Backup.yqywczET.0.0.15.js → Backup.DjU1SUNp.0.0.17.js} +1 -1
- package/dist/interface/{Camera.rR0r1OyZ.0.0.15.js → Camera.BgoyeEmQ.0.0.17.js} +1 -1
- package/dist/interface/Cameras.CTzvFhZB.0.0.17.js +1 -0
- package/dist/interface/{Camview.BatKTHU_.0.0.15.js → Camview.AIHZOcpe.0.0.17.js} +1 -1
- package/dist/interface/Config.Dwreik6Q.0.0.17.js +1 -0
- package/dist/interface/{Console.B2cDWN7X.0.0.15.js → Console.65ILbQYd.0.0.17.js} +1 -1
- package/dist/interface/FirstSteps.CLRJ9qAX.0.0.17.js +1 -0
- package/dist/interface/{NewCamera.DLnkhjgo.0.0.15.js → NewCamera.C3vbU4C7.0.0.17.js} +1 -1
- package/dist/interface/Plugin.B5hYYBYQ.0.0.17.js +1 -0
- package/dist/interface/{Plugins.Bf_8zTwV.0.0.15.js → Plugins.CfRQtEq_.0.0.17.js} +1 -1
- package/dist/interface/Recordings.BbFFnSvi.0.0.17.js +1 -0
- package/dist/interface/Recordings.BfuhtdIj.0.0.17.js +1 -0
- package/dist/interface/{Settings.D72CuJ6O.0.0.15.js → Settings.BdOXqaEX.0.0.17.js} +1 -1
- package/dist/interface/System.ysu799BZ.0.0.17.js +4 -0
- package/dist/interface/User.D7asFmwE.0.0.17.js +1 -0
- package/dist/interface/{VConfigEditor.vue_vue_type_script_setup_true_lang.ZwQQjICd.0.0.15.js → VConfigEditor.vue_vue_type_script_setup_true_lang.BAxsYS8n.0.0.17.js} +2 -2
- package/dist/interface/{VConsole.DDTNhqOU.0.0.15.js → VConsole.C7xGb1ES.0.0.17.js} +1 -1
- package/dist/interface/VPlayer.Dhm7j4pg.0.0.17.js +1 -0
- package/dist/interface/{VPluginCard.CB7NkPU_.0.0.15.js → VPluginCard.Drmi3fPn.0.0.17.js} +1 -1
- package/dist/interface/{ace-builds.A-C6i9nQ.0.0.15.js → ace-builds.BwzeyovQ.0.0.17.js} +1 -1
- package/dist/interface/assets/{Account.0.0.15.2KfYXKTQ.css → Account.0.0.17.BCEftDNE.css} +1 -1
- package/dist/interface/assets/{Cameras.0.0.15.D7bnvH42.css → Cameras.0.0.17.Djx0F2MM.css} +1 -1
- package/dist/interface/assets/{Camview.0.0.15.cgjDTjXy.css → Camview.0.0.17.Ce_V-Nxj.css} +1 -1
- package/dist/interface/assets/{Config.0.0.15.BQJF6s_V.css → Config.0.0.17.k4QpWumg.css} +1 -1
- package/dist/interface/assets/FirstSteps.0.0.17.27JF_jaE.css +1 -0
- package/dist/interface/assets/{Plugin.0.0.15.BGZE7hpr.css → Plugin.0.0.17.CY2rlLw0.css} +1 -1
- package/dist/interface/assets/User.0.0.17.DAaNwzw2.css +1 -0
- package/dist/interface/assets/{VPlayer.0.0.15.CzZme_fu.css → VPlayer.0.0.17.CY8lPcC-.css} +1 -1
- package/dist/interface/assets/{main.0.0.15.DYbE3rQA.css → main.0.0.17.CkZIZCwa.css} +1 -1
- package/dist/interface/axios.CpM4fnec.0.0.17.js +6 -0
- package/dist/interface/{dnd-core.B8stXCD4.0.0.15.js → dnd-core.BE3BG1Ef.0.0.17.js} +1 -1
- package/dist/interface/{draggabilly.ev1pKJ7p.0.0.15.js → draggabilly.lOopoogm.0.0.17.js} +1 -1
- package/dist/interface/{engine.io-client.0boOmuXx.0.0.15.js → engine.io-client.D9WQML-S.0.0.17.js} +1 -1
- package/dist/interface/{ev-emitter.CyasprkB.0.0.15.js → ev-emitter.DS-zFO5E.0.0.17.js} +1 -1
- package/dist/interface/{fast-deep-equal.AHTVU8UN.0.0.15.js → fast-deep-equal.BEv36PJS.0.0.17.js} +1 -1
- package/dist/interface/{highlight.js.DHnzQuqA.0.0.15.js → highlight.js.7wLgKNe8.0.0.17.js} +1 -1
- package/dist/interface/index.html +33 -33
- package/dist/interface/{linkify-it.BRUkUrZL.0.0.15.js → linkify-it.D8o-3IGu.0.0.17.js} +1 -1
- package/dist/interface/main.tEGILaMo.0.0.17.js +9 -0
- package/dist/interface/manifest.webmanifest +1 -1
- package/dist/interface/{markdown-it.2TL-gV6o.0.0.15.js → markdown-it.B4HcXc4c.0.0.17.js} +1 -1
- package/dist/interface/{nprogress.jtDdNYD4.0.0.15.js → nprogress.YYjE43ko.0.0.17.js} +1 -1
- package/dist/interface/{pinia.CJpkm-vG.0.0.15.js → pinia.BN10dGtz.0.0.17.js} +1 -1
- package/dist/interface/{plugins.C0VE3BWq.0.0.15.js → plugins.DGem6WnK.0.0.17.js} +1 -1
- package/dist/interface/{qrcode.lWedcgdn.0.0.15.js → qrcode.D-tn4nkj.0.0.17.js} +1 -1
- package/dist/interface/{react-dnd-touch-backend.CcgNHwJq.0.0.15.js → react-dnd-touch-backend.BYa4rNzf.0.0.17.js} +1 -1
- package/dist/interface/{rxjs.Cl-cCUwx.0.0.15.js → rxjs.DfibtzOq.0.0.17.js} +1 -1
- package/dist/interface/{socket.io-client.BC7T0S5P.0.0.15.js → socket.io-client.C_uPgwFs.0.0.17.js} +1 -1
- package/dist/interface/{socket.io-parser.DXZBuaSn.0.0.15.js → socket.io-parser.BCv62i4g.0.0.17.js} +1 -1
- package/dist/interface/sw.js +1 -1
- package/dist/interface/system.QcA_yDW7.0.0.17.js +1 -0
- package/dist/interface/{ui.DfPZU-TI.0.0.15.js → ui.CsoNsn0g.0.0.17.js} +1 -1
- package/dist/interface/{unidragger.DUKIdJYW.0.0.15.js → unidragger.CE1ihPjj.0.0.17.js} +1 -1
- package/dist/interface/{v-calendar.BRsEtqcH.0.0.15.js → v-calendar.uhLzWnBK.0.0.17.js} +1 -1
- package/dist/interface/{vee-validate.BA6ddPlX.0.0.15.js → vee-validate.Dks-nw4k.0.0.17.js} +1 -1
- package/dist/interface/{vue-i18n.CSqZ9DAQ.0.0.15.js → vue-i18n.C41_xexi.0.0.17.js} +1 -1
- package/dist/interface/{vue-inline-svg.Cvue3xa2.0.0.15.js → vue-inline-svg.BKM1fqUr.0.0.17.js} +1 -1
- package/dist/interface/{vue-router.B-YJWOHm.0.0.15.js → vue-router.BPduPoYE.0.0.17.js} +1 -1
- package/dist/interface/{vue3-apexcharts.DMh8wxia.0.0.15.js → vue3-apexcharts.CUMFs3zS.0.0.17.js} +1 -1
- package/dist/interface/{vue3-dnd.C47AfXqJ.0.0.15.js → vue3-dnd.BNLgSXFo.0.0.17.js} +1 -1
- package/dist/interface/{vue3-toastify.CeXovHOf.0.0.15.js → vue3-toastify.D4rGDrYT.0.0.17.js} +1 -1
- package/dist/interface/{vuetify.CBWGmYdo.0.0.15.js → vuetify.C_gaTn8T.0.0.17.js} +1 -1
- package/dist/server/bin/cameraui.d.ts +4 -0
- package/dist/server/bin/cameraui.js +47 -33
- package/dist/server/bin/cameraui.js.map +1 -1
- package/dist/server/bin/installer/darwin.d.ts +4 -0
- package/dist/server/bin/installer/darwin.js +37 -29
- package/dist/server/bin/installer/darwin.js.map +1 -1
- package/dist/server/bin/installer/freebsd.d.ts +4 -5
- package/dist/server/bin/installer/freebsd.js +23 -33
- package/dist/server/bin/installer/freebsd.js.map +1 -1
- package/dist/server/bin/installer/linux.d.ts +7 -0
- package/dist/server/bin/installer/linux.js +53 -27
- package/dist/server/bin/installer/linux.js.map +1 -1
- package/dist/server/bin/installer/win32.d.ts +4 -0
- package/dist/server/bin/installer/win32.js +21 -14
- package/dist/server/bin/installer/win32.js.map +1 -1
- package/dist/server/package.json +4 -4
- package/dist/server/src/api/controllers/backup.controller.js +2 -2
- package/dist/server/src/api/controllers/backup.controller.js.map +1 -1
- package/dist/server/src/api/controllers/plugins.controller.js +42 -40
- package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
- package/dist/server/src/api/controllers/system.controller.d.ts +3 -2
- package/dist/server/src/api/controllers/system.controller.js +19 -21
- package/dist/server/src/api/controllers/system.controller.js.map +1 -1
- package/dist/server/src/api/controllers/users.controller.js +12 -1
- package/dist/server/src/api/controllers/users.controller.js.map +1 -1
- package/dist/server/src/api/database/index.d.ts +0 -2
- package/dist/server/src/api/database/index.js +5 -14
- package/dist/server/src/api/database/index.js.map +1 -1
- package/dist/server/src/api/database/types.d.ts +7 -2
- package/dist/server/src/api/plugins/system.plugin.js +1 -4
- package/dist/server/src/api/plugins/system.plugin.js.map +1 -1
- package/dist/server/src/api/routes/system.routes.js +2 -2
- package/dist/server/src/api/routes/system.routes.js.map +1 -1
- package/dist/server/src/api/schemas/cameras.schema.d.ts +15 -15
- package/dist/server/src/api/schemas/cameras.schema.js +2 -2
- package/dist/server/src/api/schemas/cameras.schema.js.map +1 -1
- package/dist/server/src/api/schemas/go2rtc.schema.d.ts +14 -14
- package/dist/server/src/api/schemas/users.schema.d.ts +2 -2
- package/dist/server/src/api/schemas/users.schema.js +4 -15
- package/dist/server/src/api/schemas/users.schema.js.map +1 -1
- package/dist/server/src/api/services/backup.service.js +16 -15
- package/dist/server/src/api/services/backup.service.js.map +1 -1
- package/dist/server/src/api/services/cameras.service.js +10 -2
- package/dist/server/src/api/services/cameras.service.js.map +1 -1
- package/dist/server/src/api/utils/cert.d.ts +1 -1
- package/dist/server/src/api/utils/cert.js +14 -14
- package/dist/server/src/api/utils/cert.js.map +1 -1
- package/dist/server/src/api/utils/moveFiles.js +6 -5
- package/dist/server/src/api/utils/moveFiles.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/logs.js +5 -4
- package/dist/server/src/api/websocket/nsp/logs.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/server.js +3 -2
- package/dist/server/src/api/websocket/nsp/server.js.map +1 -1
- package/dist/server/src/camera/index.js +2 -0
- package/dist/server/src/camera/index.js.map +1 -1
- package/dist/server/src/camera/iou.d.ts +2 -0
- package/dist/server/src/camera/iou.js +53 -0
- package/dist/server/src/camera/iou.js.map +1 -0
- package/dist/server/src/camera/streaming/peer-connection.d.ts +3 -1
- package/dist/server/src/camera/streaming/peer-connection.js +12 -7
- package/dist/server/src/camera/streaming/peer-connection.js.map +1 -1
- package/dist/server/src/camera/streaming/webrtc-connection.d.ts +2 -0
- package/dist/server/src/camera/streaming/webrtc-connection.js +28 -10
- package/dist/server/src/camera/streaming/webrtc-connection.js.map +1 -1
- package/dist/server/src/camera/types.d.ts +2 -1
- package/dist/server/src/camera/types.js.map +1 -1
- package/dist/server/src/main.js +8 -4
- package/dist/server/src/main.js.map +1 -1
- package/dist/server/src/nats/server.js +4 -3
- package/dist/server/src/nats/server.js.map +1 -1
- package/dist/server/src/plugins/index.js +12 -11
- package/dist/server/src/plugins/index.js.map +1 -1
- package/dist/server/src/plugins/plugin.js +6 -4
- package/dist/server/src/plugins/plugin.js.map +1 -1
- package/dist/server/src/plugins/worker.d.ts +1 -0
- package/dist/server/src/plugins/worker.js +24 -16
- package/dist/server/src/plugins/worker.js.map +1 -1
- package/dist/server/src/polyglot/node/decoder/child.js +16 -10
- package/dist/server/src/polyglot/node/decoder/child.js.map +1 -1
- package/dist/server/src/polyglot/node/decoder/imageUtils.js +2 -2
- package/dist/server/src/polyglot/node/decoder/imageUtils.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/cameraStorage.d.ts +3 -3
- package/dist/server/src/polyglot/node/plugins/cameraStorage.js +7 -21
- package/dist/server/src/polyglot/node/plugins/cameraStorage.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/child.d.ts +1 -0
- package/dist/server/src/polyglot/node/plugins/child.js +18 -5
- package/dist/server/src/polyglot/node/plugins/child.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/configService.d.ts +1 -1
- package/dist/server/src/polyglot/node/plugins/configService.js +5 -5
- package/dist/server/src/polyglot/node/plugins/configService.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/pluginApi.d.ts +3 -2
- package/dist/server/src/polyglot/node/plugins/pluginApi.js +3 -3
- package/dist/server/src/polyglot/node/plugins/pluginApi.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.d.ts +4 -4
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js +55 -46
- package/dist/server/src/polyglot/node/plugins/proxy/cameraDevice.js.map +1 -1
- package/dist/server/src/polyglot/node/plugins/storageController.d.ts +3 -1
- package/dist/server/src/polyglot/node/plugins/storageController.js +4 -2
- package/dist/server/src/polyglot/node/plugins/storageController.js.map +1 -1
- package/dist/server/src/polyglot/python/camera/iou.py +80 -0
- package/dist/server/src/polyglot/python/camera_ui_types/__init__.py +15 -9
- package/dist/server/src/polyglot/python/decoder/child.py +25 -16
- package/dist/server/src/polyglot/python/plugins/camera_storage.py +12 -62
- package/dist/server/src/polyglot/python/plugins/child.py +59 -23
- package/dist/server/src/polyglot/python/plugins/config_service.py +8 -1
- package/dist/server/src/polyglot/python/plugins/plugin_api.py +5 -1
- package/dist/server/src/polyglot/python/plugins/proxy/camera_device.py +88 -53
- package/dist/server/src/polyglot/python/plugins/proxy/core_manager.py +8 -8
- package/dist/server/src/polyglot/python/plugins/storage_controller.py +5 -3
- package/dist/server/src/polyglot/python/plugins/typings.py +6 -0
- package/dist/server/src/polyglot/python/utilities/json_lmdb.py +19 -0
- package/dist/server/src/polyglot/python/utilities/subscriptions.py +6 -4
- package/dist/server/src/polyglot/python/utilities/utils.py +63 -38
- package/dist/server/src/services/config/index.js +32 -21
- package/dist/server/src/services/config/index.js.map +1 -1
- package/dist/server/src/utils/npm.js +3 -3
- package/dist/server/src/utils/npm.js.map +1 -1
- package/dist/server/src/utils/pythonInstaller.js +16 -14
- package/dist/server/src/utils/pythonInstaller.js.map +1 -1
- package/package.json +4 -4
- package/dist/interface/Account.DTO3ooh3.0.0.15.js +0 -1
- package/dist/interface/Cameras.G9WAma5x.0.0.15.js +0 -1
- package/dist/interface/Config.CsvpXqyb.0.0.15.js +0 -1
- package/dist/interface/FirstSteps.ukPFDoeG.0.0.15.js +0 -1
- package/dist/interface/Plugin.N1q6ZCIP.0.0.15.js +0 -1
- package/dist/interface/Recordings.Bsbb82FW.0.0.15.js +0 -1
- package/dist/interface/Recordings.UbjwH1iF.0.0.15.js +0 -1
- package/dist/interface/System.XRKGIwr_.0.0.15.js +0 -4
- package/dist/interface/User.DzMhZQTR.0.0.15.js +0 -1
- package/dist/interface/VPlayer.B3iRkLXd.0.0.15.js +0 -1
- package/dist/interface/assets/FirstSteps.0.0.15.DFSydMqk.css +0 -1
- package/dist/interface/assets/User.0.0.15.CXUSYt8i.css +0 -1
- package/dist/interface/axios.BI2i94Vb.0.0.15.js +0 -6
- package/dist/interface/main.b1KIH7xr.0.0.15.js +0 -9
- package/dist/interface/system.Ddiy-UaE.0.0.15.js +0 -1
- /package/dist/interface/{@babel.l0sNRNKZ.0.0.15.js → @babel.l0sNRNKZ.0.0.17.js} +0 -0
- /package/dist/interface/{@intlify.YW_pt133.0.0.15.js → @intlify.YW_pt133.0.0.17.js} +0 -0
- /package/dist/interface/{@mdi.jq8isxax.0.0.15.js → @mdi.jq8isxax.0.0.17.js} +0 -0
- /package/dist/interface/{@popperjs.BQBsAJpH.0.0.15.js → @popperjs.BQBsAJpH.0.0.17.js} +0 -0
- /package/dist/interface/{@react-dnd.CcwRs9xb.0.0.15.js → @react-dnd.CcwRs9xb.0.0.17.js} +0 -0
- /package/dist/interface/{@socket.io.Dkula2eQ.0.0.15.js → @socket.io.Dkula2eQ.0.0.17.js} +0 -0
- /package/dist/interface/{@vue.CIFymae3.0.0.15.js → @vue.CIFymae3.0.0.17.js} +0 -0
- /package/dist/interface/{@xterm.CQtBFDn2.0.0.15.js → @xterm.Cq_3w6CG.0.0.17.js} +0 -0
- /package/dist/interface/assets/{@vueform.0.0.15.h7tNX9p6.css → @vueform.0.0.17.h7tNX9p6.css} +0 -0
- /package/dist/interface/assets/{@xterm.0.0.15.CGrrDQr5.css → @xterm.0.0.17.CGrrDQr5.css} +0 -0
- /package/dist/interface/assets/{Adminpanel.0.0.15.A2JXV1Ib.css → Adminpanel.0.0.17.A2JXV1Ib.css} +0 -0
- /package/dist/interface/assets/{Backup.0.0.15.BIwaSlv3.css → Backup.0.0.17.BIwaSlv3.css} +0 -0
- /package/dist/interface/assets/{Camera.0.0.15.BDtUJ-lA.css → Camera.0.0.17.BDtUJ-lA.css} +0 -0
- /package/dist/interface/assets/{Console.0.0.15.DWrfRWs9.css → Console.0.0.17.DWrfRWs9.css} +0 -0
- /package/dist/interface/assets/{NewCamera.0.0.15.CMzSwwHn.css → NewCamera.0.0.17.CMzSwwHn.css} +0 -0
- /package/dist/interface/assets/{Plugins.0.0.15.Cwu0aGUO.css → Plugins.0.0.17.Cwu0aGUO.css} +0 -0
- /package/dist/interface/assets/{Settings.0.0.15.DTxcLhIY.css → Settings.0.0.17.DTxcLhIY.css} +0 -0
- /package/dist/interface/assets/{VConsole.0.0.15.BZT1WyS-.css → VConsole.0.0.17.BZT1WyS-.css} +0 -0
- /package/dist/interface/assets/{VPluginCard.0.0.15.C2OqX7DJ.css → VPluginCard.0.0.17.C2OqX7DJ.css} +0 -0
- /package/dist/interface/assets/{highlight.0.0.15.DgoK_Xib.css → highlight.0.0.17.DgoK_Xib.css} +0 -0
- /package/dist/interface/assets/{logo-256.0.0.15.BCQk9H1-.png → logo-256.0.0.17.BCQk9H1-.png} +0 -0
- /package/dist/interface/assets/{logo-512.0.0.15.DLKVOU2S.png → logo-512.0.0.17.DLKVOU2S.png} +0 -0
- /package/dist/interface/assets/{logo.0.0.15.DmEiRk0z.png → logo.0.0.17.DmEiRk0z.png} +0 -0
- /package/dist/interface/assets/{mode-json.0.0.15.Br7xisR1.js → mode-json.0.0.17.Br7xisR1.js} +0 -0
- /package/dist/interface/assets/{mode-yaml.0.0.15.CIYL8U3d.js → mode-yaml.0.0.17.CIYL8U3d.js} +0 -0
- /package/dist/interface/assets/{v-calendar.0.0.15.CtSuDYZU.css → v-calendar.0.0.17.CtSuDYZU.css} +0 -0
- /package/dist/interface/assets/{vue3-toastify.0.0.15.DTY1DMRs.css → vue3-toastify.0.0.17.DTY1DMRs.css} +0 -0
- /package/dist/interface/assets/{vuetify.0.0.15.DPyVfAPv.css → vuetify.0.0.17.DPyVfAPv.css} +0 -0
- /package/dist/interface/{compare-versions.DqEOhma6.0.0.15.js → compare-versions.DqEOhma6.0.0.17.js} +0 -0
- /package/dist/interface/{dijkstrajs.D_NXgYpA.0.0.15.js → dijkstrajs.D_NXgYpA.0.0.17.js} +0 -0
- /package/dist/interface/{engine.io-parser.BiEtp6m2.0.0.15.js → engine.io-parser.BiEtp6m2.0.0.17.js} +0 -0
- /package/dist/interface/{entities.C20TfXL6.0.0.15.js → entities.C20TfXL6.0.0.17.js} +0 -0
- /package/dist/interface/{get-size.D1dS-IaP.0.0.15.js → get-size.D1dS-IaP.0.0.17.js} +0 -0
- /package/dist/interface/{mdurl.k9Sl0PQj.0.0.15.js → mdurl.k9Sl0PQj.0.0.17.js} +0 -0
- /package/dist/interface/{punycode.js.Dj65hjkv.0.0.15.js → punycode.js.Dj65hjkv.0.0.17.js} +0 -0
- /package/dist/interface/{react-dnd-html5-backend.1HQjlkwI.0.0.15.js → react-dnd-html5-backend.1HQjlkwI.0.0.17.js} +0 -0
- /package/dist/interface/{redux.CuxFRhX_.0.0.15.js → redux.CuxFRhX_.0.0.17.js} +0 -0
- /package/dist/interface/{tslib.9k7AwCpt.0.0.15.js → tslib.9k7AwCpt.0.0.17.js} +0 -0
- /package/dist/interface/{uc.micro.kMc2yuuw.0.0.15.js → uc.micro.kMc2yuuw.0.0.17.js} +0 -0
- /package/dist/interface/{utils.BvINh1mj.0.0.15.js → utils.BvINh1mj.0.0.17.js} +0 -0
- /package/dist/interface/{uuid.DvF23Exx.0.0.15.js → uuid.DvF23Exx.0.0.17.js} +0 -0
- /package/dist/interface/{vue.l0sNRNKZ.0.0.15.js → vue.l0sNRNKZ.0.0.17.js} +0 -0
- /package/dist/interface/{zod.BaF2dDCd.0.0.15.js → zod.BaF2dDCd.0.0.17.js} +0 -0
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import inspect
|
|
2
|
-
import json
|
|
3
2
|
from contextlib import suppress
|
|
4
3
|
from copy import deepcopy
|
|
5
|
-
from pathlib import Path
|
|
6
4
|
from typing import Any, Optional, TypeVar, Union, cast
|
|
7
5
|
|
|
8
6
|
from camera_ui_types import (
|
|
@@ -24,42 +22,16 @@ from schema import (
|
|
|
24
22
|
)
|
|
25
23
|
from typing_extensions import Literal, overload
|
|
26
24
|
from utilities.object_path import ObjectPath
|
|
27
|
-
from utilities.utils import merge_with
|
|
25
|
+
from utilities.utils import merge, merge_with
|
|
28
26
|
|
|
29
27
|
P = TypeVar("P", str, int, float, bool, dict[Any, Any], list[Any], None)
|
|
30
28
|
|
|
31
29
|
|
|
32
|
-
def merge(
|
|
33
|
-
obj_value: Any,
|
|
34
|
-
src_value: Any,
|
|
35
|
-
key: Union[str, int],
|
|
36
|
-
object: Union[dict[str, Any], list[Any]],
|
|
37
|
-
source: Union[dict[str, Any], list[Any]],
|
|
38
|
-
stack: list[Any],
|
|
39
|
-
) -> Any:
|
|
40
|
-
if isinstance(obj_value, list):
|
|
41
|
-
return src_value
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class JsonLmdb(Lmdb[Literal["config"], dict[str, Any]]):
|
|
45
|
-
def _pre_key(self, key: Literal["config"]) -> bytes:
|
|
46
|
-
return key.encode("utf-8")
|
|
47
|
-
|
|
48
|
-
def _post_key(self, key: bytes) -> Literal["config"]:
|
|
49
|
-
_key: Any = key.decode("utf-8")
|
|
50
|
-
return _key
|
|
51
|
-
|
|
52
|
-
def _pre_value(self, value: dict[str, Any]) -> bytes:
|
|
53
|
-
return json.dumps(value).encode("utf-8")
|
|
54
|
-
|
|
55
|
-
def _post_value(self, value: bytes) -> dict[str, Any]:
|
|
56
|
-
return json.loads(value.decode("utf-8"))
|
|
57
|
-
|
|
58
|
-
|
|
59
30
|
class CameraStorage:
|
|
60
31
|
def __init__(
|
|
61
32
|
self,
|
|
62
33
|
api: PluginAPI,
|
|
34
|
+
plugin_db: Lmdb[Literal["config"], dict[str, Any]],
|
|
63
35
|
instance: Any,
|
|
64
36
|
camera_id: str,
|
|
65
37
|
schema: Optional[JsonSchemaForm] = None,
|
|
@@ -67,15 +39,12 @@ class CameraStorage:
|
|
|
67
39
|
if schema is None:
|
|
68
40
|
schema = {}
|
|
69
41
|
self.__api = api
|
|
42
|
+
self.__plugin_db = plugin_db
|
|
70
43
|
self.__instance = instance
|
|
71
44
|
self.__camera_id = camera_id
|
|
72
45
|
self.schema: JsonSchemaForm = schema or {}
|
|
73
46
|
self.values: dict[str, Any] = {}
|
|
74
47
|
|
|
75
|
-
db_path = Path(api.storage_path) / "volume"
|
|
76
|
-
self.__db: Lmdb[Literal["config"], dict[str, Any]] = JsonLmdb.open(file=str(db_path), flag="c")
|
|
77
|
-
|
|
78
|
-
self.__api.device_manager.once("cameraDeselected", self.__deselected)
|
|
79
48
|
self.__api.once("shutdown", self.__close)
|
|
80
49
|
|
|
81
50
|
def initializeStorage(self) -> None:
|
|
@@ -84,17 +53,10 @@ class CameraStorage:
|
|
|
84
53
|
This will load the configuration from the database.
|
|
85
54
|
"""
|
|
86
55
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
try:
|
|
90
|
-
config: Any = self.__db.get("config") or {}
|
|
91
|
-
camera_config = config.get(self.__camera_id, {})
|
|
92
|
-
except: # noqa: E722
|
|
93
|
-
pass
|
|
94
|
-
|
|
56
|
+
config: Any = self.__plugin_db.get("config") or {}
|
|
57
|
+
camera_config = config.get(self.__camera_id, {})
|
|
95
58
|
schema_config = generate_json_from_root_schema({"schema": self.schema})
|
|
96
|
-
|
|
97
|
-
self.values = merge_with(schema_config, camera_config, merge, [])
|
|
59
|
+
self.values = merge_with(schema_config, camera_config, merge)
|
|
98
60
|
|
|
99
61
|
self.__save_db()
|
|
100
62
|
|
|
@@ -228,7 +190,7 @@ class CameraStorage:
|
|
|
228
190
|
elif isinstance(schema_or_path, dict) and schema is None:
|
|
229
191
|
new_schema = schema_or_path
|
|
230
192
|
|
|
231
|
-
self.schema = merge_with(self.schema, new_schema, merge
|
|
193
|
+
self.schema = merge_with(self.schema, new_schema, merge)
|
|
232
194
|
|
|
233
195
|
await self.__resolve_on_get_functions(new_schema)
|
|
234
196
|
|
|
@@ -258,7 +220,7 @@ class CameraStorage:
|
|
|
258
220
|
ObjectPath.delete(self.values, path)
|
|
259
221
|
|
|
260
222
|
if self.__contains_storable_schema(schema):
|
|
261
|
-
self.
|
|
223
|
+
self.__save_db()
|
|
262
224
|
|
|
263
225
|
async def changeSchema(self, path: str, new_schema: dict[str, Any]) -> None:
|
|
264
226
|
"""
|
|
@@ -274,7 +236,7 @@ class CameraStorage:
|
|
|
274
236
|
schema: Optional[JsonSchema] = ObjectPath.get(self.schema, schema_path) or None
|
|
275
237
|
|
|
276
238
|
if schema:
|
|
277
|
-
merge_with(schema, new_schema, merge
|
|
239
|
+
merge_with(schema, new_schema, merge)
|
|
278
240
|
ObjectPath.set(self.schema, schema_path, schema)
|
|
279
241
|
|
|
280
242
|
await self.__resolve_on_get_functions(schema, schema_path)
|
|
@@ -362,7 +324,7 @@ class CameraStorage:
|
|
|
362
324
|
schema_path = config_path_to_schema_path(new_path)
|
|
363
325
|
schema_item: Optional[JsonBaseSchema] = get_value_by_path(self.schema, schema_path)
|
|
364
326
|
|
|
365
|
-
if schema_item:
|
|
327
|
+
if schema_item and schema_item["type"] != "button":
|
|
366
328
|
on_set_function = schema_item.get("onSet", None)
|
|
367
329
|
if on_set_function:
|
|
368
330
|
if inspect.iscoroutinefunction(on_set_function):
|
|
@@ -417,25 +379,13 @@ class CameraStorage:
|
|
|
417
379
|
return False
|
|
418
380
|
|
|
419
381
|
def __save_db(self) -> None:
|
|
420
|
-
config: Any = self.
|
|
382
|
+
config: Any = self.__plugin_db.get("config") or {}
|
|
421
383
|
storable_config = self.__filter_storable_values(self.schema)
|
|
422
384
|
|
|
423
385
|
config[self.__camera_id] = storable_config
|
|
424
386
|
|
|
425
|
-
self.
|
|
426
|
-
|
|
427
|
-
def __remove_db(self) -> None:
|
|
428
|
-
config: Any = self.__db.get("config") or {}
|
|
429
|
-
|
|
430
|
-
if self.__camera_id in config:
|
|
431
|
-
del config[self.__camera_id]
|
|
432
|
-
self.__db.update(config)
|
|
433
|
-
|
|
434
|
-
def __deselected(self, id: str) -> None:
|
|
435
|
-
if id == self.__camera_id:
|
|
436
|
-
self.__remove_db()
|
|
387
|
+
self.__plugin_db.update({"config": config})
|
|
437
388
|
|
|
438
389
|
def __close(self) -> None:
|
|
439
390
|
with suppress(Exception):
|
|
440
391
|
self.__save_db()
|
|
441
|
-
self.__db.close()
|
|
@@ -7,11 +7,13 @@ import sys
|
|
|
7
7
|
import traceback
|
|
8
8
|
from asyncio import AbstractEventLoop
|
|
9
9
|
from contextlib import suppress
|
|
10
|
+
from pathlib import Path
|
|
10
11
|
from types import ModuleType
|
|
11
|
-
from typing import Any, Optional, cast
|
|
12
|
+
from typing import Any, Literal, Optional, cast
|
|
12
13
|
|
|
13
14
|
from camera_ui_types import BasePlugin, CameraDevice
|
|
14
15
|
from decoder.typings import AuthConfig
|
|
16
|
+
from lmdbm import Lmdb
|
|
15
17
|
from message_queue import MessageQueue
|
|
16
18
|
from nats.aio.msg import Msg
|
|
17
19
|
from plugin_api import PluginAPI
|
|
@@ -27,6 +29,7 @@ from typings import (
|
|
|
27
29
|
ProxyMessageStructure,
|
|
28
30
|
)
|
|
29
31
|
from utilities.connection import ProxyConnection
|
|
32
|
+
from utilities.json_lmdb import JsonLmdb
|
|
30
33
|
from utilities.packer import unpack
|
|
31
34
|
from utilities.subscriptions import ProxySubscription
|
|
32
35
|
from utilities.task import TaskSet
|
|
@@ -88,6 +91,7 @@ class PluginChild:
|
|
|
88
91
|
|
|
89
92
|
self.display_name = sys.argv[1] if len(sys.argv) > 1 else "PluginChild"
|
|
90
93
|
self.logger = PluginLogger(self.display_name, os.environ["LOGGER_DISABLE_TIMESTAMPS"] == "true")
|
|
94
|
+
self.plugin_db: Optional[Lmdb[Literal["config"], dict[str, Any]]] = None
|
|
91
95
|
|
|
92
96
|
self.subject = f"{os.environ['WORKER_ID']}.ipc.subscriber"
|
|
93
97
|
self.plugin_subject = f"{os.environ['PLUGIN_ID']}.child"
|
|
@@ -104,6 +108,7 @@ class PluginChild:
|
|
|
104
108
|
self.plugin: Optional[BasePlugin] = None
|
|
105
109
|
|
|
106
110
|
self.stopped = False
|
|
111
|
+
self.closed = False
|
|
107
112
|
|
|
108
113
|
async def run(self):
|
|
109
114
|
self.shutdown_event = asyncio.Event()
|
|
@@ -136,10 +141,28 @@ class PluginChild:
|
|
|
136
141
|
plugin_info = data["plugin"]
|
|
137
142
|
cameras = data["cameras"]
|
|
138
143
|
|
|
144
|
+
db_path = Path(storage_path) / "volume"
|
|
145
|
+
Path(db_path).mkdir(parents=True, exist_ok=True)
|
|
146
|
+
|
|
147
|
+
self.plugin_db = JsonLmdb.open(file=str(db_path), flag="c")
|
|
148
|
+
|
|
149
|
+
config: Any = self.plugin_db.get("config")
|
|
150
|
+
if config is None:
|
|
151
|
+
self.plugin_db.update({"config": {}})
|
|
152
|
+
|
|
139
153
|
self.api = PluginAPI(
|
|
140
|
-
plugin_info,
|
|
154
|
+
plugin_info,
|
|
155
|
+
storage_path,
|
|
156
|
+
config_file,
|
|
157
|
+
self.logger,
|
|
158
|
+
self.proxy_endpoints,
|
|
159
|
+
self.auth,
|
|
160
|
+
self.plugin_db,
|
|
141
161
|
)
|
|
142
162
|
|
|
163
|
+
plugin_constructor = self.load_plugin()
|
|
164
|
+
self.plugin = cast(BasePlugin, plugin_constructor(self.logger, self.api))
|
|
165
|
+
|
|
143
166
|
await asyncio.gather(
|
|
144
167
|
self.api.core_manager.init(),
|
|
145
168
|
self.api.device_manager.init(),
|
|
@@ -159,9 +182,6 @@ class PluginChild:
|
|
|
159
182
|
|
|
160
183
|
await asyncio.gather(*(camera_device.init() for camera_device in cameras_devices))
|
|
161
184
|
|
|
162
|
-
plugin_constructor = self.load_plugin()
|
|
163
|
-
self.plugin = cast(BasePlugin, plugin_constructor(self.logger, self.api))
|
|
164
|
-
|
|
165
185
|
self.api.device_manager.configure_cameras(cameras_devices)
|
|
166
186
|
self.plugin.configure_cameras(cast(list[CameraDevice], cameras_devices))
|
|
167
187
|
|
|
@@ -175,6 +195,9 @@ class PluginChild:
|
|
|
175
195
|
|
|
176
196
|
self.stopped = True
|
|
177
197
|
|
|
198
|
+
if self.api:
|
|
199
|
+
self.api.emit("shutdown")
|
|
200
|
+
|
|
178
201
|
if self.message_queue:
|
|
179
202
|
self.message_queue.abort_queue()
|
|
180
203
|
|
|
@@ -182,8 +205,10 @@ class PluginChild:
|
|
|
182
205
|
with suppress(Exception):
|
|
183
206
|
await self.publisher.close()
|
|
184
207
|
|
|
185
|
-
if self.
|
|
186
|
-
|
|
208
|
+
if self.plugin_db:
|
|
209
|
+
await asyncio.sleep(0.5)
|
|
210
|
+
with suppress(Exception):
|
|
211
|
+
self.plugin_db.close()
|
|
187
212
|
|
|
188
213
|
self.shutdown_event.set()
|
|
189
214
|
|
|
@@ -268,9 +293,27 @@ class PluginChild:
|
|
|
268
293
|
|
|
269
294
|
if "type" in message:
|
|
270
295
|
if message["type"] == PLUGIN_COMMAND.START.value and "data" in message:
|
|
271
|
-
self.
|
|
296
|
+
await self.start(message["data"])
|
|
272
297
|
elif message["type"] == PLUGIN_COMMAND.STOP.value:
|
|
273
|
-
self.
|
|
298
|
+
await self.stop()
|
|
299
|
+
|
|
300
|
+
async def gracefully_close(self, signame: str, reason: Any = "unknown"):
|
|
301
|
+
if self.stopped or self.closed:
|
|
302
|
+
return
|
|
303
|
+
|
|
304
|
+
self.closed = True
|
|
305
|
+
|
|
306
|
+
self.logger.log(
|
|
307
|
+
f"{self.display_name} is gracefully closing from signal='{signame}' reason='{reason}'..."
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
try:
|
|
311
|
+
stop_task = asyncio.create_task(self.stop(), name=f"{self.display_name} Stop")
|
|
312
|
+
await asyncio.wait_for(stop_task, timeout=2)
|
|
313
|
+
os.kill(os.getpid(), signal.SIGKILL)
|
|
314
|
+
except asyncio.TimeoutError:
|
|
315
|
+
self.logger.warn("Failed to gracefully close before timeout, force quit!")
|
|
316
|
+
os.kill(os.getpid(), signal.SIGKILL)
|
|
274
317
|
|
|
275
318
|
def setup_signal_handlers(self):
|
|
276
319
|
loop = asyncio.get_running_loop()
|
|
@@ -279,20 +322,12 @@ class PluginChild:
|
|
|
279
322
|
for signame in ("SIGINT", "SIGTERM"):
|
|
280
323
|
loop.add_signal_handler(
|
|
281
324
|
getattr(signal, signame),
|
|
282
|
-
lambda signame=signame:
|
|
325
|
+
lambda signame=signame: asyncio.create_task(
|
|
326
|
+
self.gracefully_close(signame, getattr(signal, signame)),
|
|
327
|
+
name=f"{self.display_name} Signal",
|
|
328
|
+
),
|
|
283
329
|
)
|
|
284
330
|
|
|
285
|
-
def gracefully_close(self, signame: str, reason: Any = "unknown"):
|
|
286
|
-
if self.stopped:
|
|
287
|
-
return
|
|
288
|
-
|
|
289
|
-
self.logger.log(
|
|
290
|
-
f"{self.display_name} is gracefully closing from signal='{signame}' reason='{reason}'..."
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
self.tasks.add(self.stop())
|
|
294
|
-
self.shutdown_event.set()
|
|
295
|
-
|
|
296
331
|
def handle_exception(self, loop: AbstractEventLoop, context: Any):
|
|
297
332
|
print("Exception context:", context)
|
|
298
333
|
traceback.print_exc()
|
|
@@ -308,9 +343,10 @@ class PluginChild:
|
|
|
308
343
|
self.logger.error(f"Caught exception: {msg}")
|
|
309
344
|
|
|
310
345
|
if loop.is_running():
|
|
311
|
-
self.gracefully_close("uncaughtException", msg)
|
|
346
|
+
asyncio.create_task(self.gracefully_close("uncaughtException", msg))
|
|
312
347
|
|
|
313
348
|
|
|
314
349
|
if __name__ == "__main__":
|
|
315
350
|
plugin_child = PluginChild()
|
|
316
|
-
asyncio.run(plugin_child.run()
|
|
351
|
+
asyncio.run(plugin_child.run())
|
|
352
|
+
# asyncio.run(plugin_child.run(), debug=True)
|
|
@@ -163,7 +163,14 @@ class PluginConfigService:
|
|
|
163
163
|
self.set(path_segments[0], self.__config[path_segments[0]], write)
|
|
164
164
|
|
|
165
165
|
def __init(self) -> None:
|
|
166
|
-
os.
|
|
166
|
+
directory = os.path.dirname(self.__config_file)
|
|
167
|
+
|
|
168
|
+
if not os.path.exists(directory):
|
|
169
|
+
os.makedirs(directory)
|
|
170
|
+
|
|
171
|
+
if not os.path.exists(self.__config_file):
|
|
172
|
+
open(self.__config_file, "a").close()
|
|
173
|
+
|
|
167
174
|
self.__read()
|
|
168
175
|
|
|
169
176
|
def __read(self) -> None:
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
from typing import Any, Literal
|
|
2
|
+
|
|
1
3
|
from config_service import PluginConfigService
|
|
2
4
|
from decoder.typings import AuthConfig
|
|
5
|
+
from lmdbm import Lmdb
|
|
3
6
|
from plugin_logger import PluginLogger
|
|
4
7
|
from pyeecui.asyncio import AsyncIOEventEmitter
|
|
5
8
|
from typings import PluginInfo
|
|
@@ -14,6 +17,7 @@ class PluginAPI(AsyncIOEventEmitter):
|
|
|
14
17
|
logger: PluginLogger,
|
|
15
18
|
proxy_endpoints: list[str],
|
|
16
19
|
auth: AuthConfig,
|
|
20
|
+
plugin_db: Lmdb[Literal["config"], dict[str, Any]],
|
|
17
21
|
) -> None:
|
|
18
22
|
super().__init__()
|
|
19
23
|
|
|
@@ -25,6 +29,6 @@ class PluginAPI(AsyncIOEventEmitter):
|
|
|
25
29
|
self.config_file = config_file
|
|
26
30
|
|
|
27
31
|
self.config_service = PluginConfigService(config_file)
|
|
28
|
-
self.storage_controller = StorageController(self)
|
|
32
|
+
self.storage_controller = StorageController(self, plugin_db)
|
|
29
33
|
self.core_manager = CoreManager(self, logger, plugin, proxy_endpoints, auth)
|
|
30
34
|
self.device_manager = DeviceManager(self, logger, plugin, proxy_endpoints, auth)
|
|
@@ -10,6 +10,7 @@ from uuid import uuid4
|
|
|
10
10
|
|
|
11
11
|
import aiohttp
|
|
12
12
|
from cachetools import LRUCache, cached
|
|
13
|
+
from camera.iou import merge_detections
|
|
13
14
|
from camera.polygon import are_motion_detections_valid, are_object_detections_valid
|
|
14
15
|
from camera.video_frame import MotionFrame, VideoFrame
|
|
15
16
|
from camera_ui_types import (
|
|
@@ -68,6 +69,7 @@ from typings import (
|
|
|
68
69
|
ClientType,
|
|
69
70
|
Delegates,
|
|
70
71
|
DeserializedError,
|
|
72
|
+
FrameSubscribtion,
|
|
71
73
|
PluginInfo,
|
|
72
74
|
ProxyMessageStructure,
|
|
73
75
|
)
|
|
@@ -190,13 +192,13 @@ class CameraDeviceProxy:
|
|
|
190
192
|
self.camera_subscriber: Optional[ProxySubscription] = None
|
|
191
193
|
self.camera_plugin_subscriber: Optional[ProxySubscription] = None
|
|
192
194
|
self.signaling_subscriber: Optional[ProxySubscription] = None
|
|
193
|
-
self.
|
|
194
|
-
self.
|
|
195
|
+
self.frame_subscribers: list[FrameSubscribtion] = []
|
|
196
|
+
self.motion_frame_subscribers: list[FrameSubscribtion] = []
|
|
195
197
|
|
|
196
198
|
self.tasks: TaskSet = TaskSet(f"{self.plugin['name']} - {self.name} - CameraDeviceProxy")
|
|
197
199
|
self.message_queue: Optional[MessageQueue] = None
|
|
198
200
|
self.active_requests: set[str] = set()
|
|
199
|
-
self.active_motion_requests =
|
|
201
|
+
self.active_motion_requests: set[str] = set()
|
|
200
202
|
|
|
201
203
|
# print(("INIT camera device with clientSubject", self.subject))
|
|
202
204
|
|
|
@@ -425,24 +427,24 @@ class CameraDeviceProxy:
|
|
|
425
427
|
|
|
426
428
|
if prebuffer_duration > 0:
|
|
427
429
|
request_type = "prebuffer"
|
|
428
|
-
prebuffer_duration =
|
|
430
|
+
prebuffer_duration = min(prebuffer_duration, 5)
|
|
429
431
|
|
|
430
432
|
request_id = f"{str(uuid4())}-{request_type}"
|
|
431
433
|
|
|
432
434
|
try:
|
|
433
435
|
metadata = await self.__connect_to_decoder(request_id)
|
|
436
|
+
frame_subscriber = await self.frame_publisher.subscribe(self.frame_subject)
|
|
434
437
|
|
|
435
|
-
|
|
436
|
-
self.frame_subscriber = await self.frame_publisher.subscribe(self.frame_subject)
|
|
438
|
+
self.frame_subscribers.append({"request_id": request_id, "subscriber": frame_subscriber})
|
|
437
439
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
+
try:
|
|
441
|
+
async for msg in frame_subscriber.subscriber.messages:
|
|
440
442
|
if (
|
|
441
443
|
not self.initialized
|
|
442
444
|
or len(self.active_requests) == 0
|
|
443
445
|
or request_id not in self.active_requests
|
|
444
446
|
):
|
|
445
|
-
|
|
447
|
+
return
|
|
446
448
|
|
|
447
449
|
if len(msg.data) == 0:
|
|
448
450
|
continue
|
|
@@ -450,35 +452,39 @@ class CameraDeviceProxy:
|
|
|
450
452
|
frame_data: FrameData = unpack(msg.data)
|
|
451
453
|
|
|
452
454
|
yield VideoFrame(self.id, self.frame_publisher, frame_data, metadata, prebuffer_duration)
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
else:
|
|
457
|
-
break
|
|
455
|
+
|
|
456
|
+
except GeneratorExit:
|
|
457
|
+
return
|
|
458
458
|
|
|
459
459
|
except asyncio.CancelledError:
|
|
460
|
-
|
|
460
|
+
return
|
|
461
461
|
except Exception as e:
|
|
462
462
|
if self.initialized:
|
|
463
463
|
self.logger.error("Error while generating frames:", e)
|
|
464
|
+
raise
|
|
464
465
|
finally:
|
|
465
|
-
self.
|
|
466
|
+
await self.__disconnect_from_decoder(request_id)
|
|
466
467
|
|
|
467
468
|
async def get_motion_frames(self) -> AsyncGenerator[MotionFrame, None]:
|
|
468
469
|
if not self.motion_frame_publisher:
|
|
469
470
|
raise Exception("Motion Frame Publisher is not initialized")
|
|
470
471
|
|
|
471
|
-
|
|
472
|
+
request_id = f"{str(uuid4())}-motion"
|
|
472
473
|
|
|
473
474
|
try:
|
|
474
|
-
|
|
475
|
-
self.motion_frame_subscriber = await self.motion_frame_publisher.subscribe(
|
|
476
|
-
self.motion_frame_subject
|
|
477
|
-
)
|
|
475
|
+
motion_frame_subscriber = await self.motion_frame_publisher.subscribe(self.motion_frame_subject)
|
|
478
476
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
477
|
+
self.motion_frame_subscribers.append(
|
|
478
|
+
{"request_id": request_id, "subscriber": motion_frame_subscriber}
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
try:
|
|
482
|
+
async for msg in motion_frame_subscriber.subscriber.messages:
|
|
483
|
+
if (
|
|
484
|
+
not self.initialized
|
|
485
|
+
or len(self.active_motion_requests) == 0
|
|
486
|
+
or request_id not in self.active_motion_requests
|
|
487
|
+
):
|
|
482
488
|
break
|
|
483
489
|
|
|
484
490
|
if not msg or not msg.data or len(msg.data) == 0:
|
|
@@ -499,22 +505,30 @@ class CameraDeviceProxy:
|
|
|
499
505
|
motion_state,
|
|
500
506
|
motion_frame["metadata"],
|
|
501
507
|
)
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
else:
|
|
506
|
-
break
|
|
508
|
+
|
|
509
|
+
except GeneratorExit:
|
|
510
|
+
return
|
|
507
511
|
|
|
508
512
|
except asyncio.CancelledError:
|
|
509
513
|
pass
|
|
510
514
|
except Exception as e:
|
|
511
515
|
if self.initialized:
|
|
512
516
|
self.logger.error("Error while generating motion frames:", e)
|
|
517
|
+
raise
|
|
513
518
|
finally:
|
|
514
|
-
self.active_motion_requests
|
|
519
|
+
if request_id in self.active_motion_requests:
|
|
520
|
+
self.active_motion_requests.remove(request_id)
|
|
521
|
+
|
|
522
|
+
motion_frame_subscribtion = next(
|
|
523
|
+
(sub for sub in self.motion_frame_subscribers if sub["request_id"] == request_id), None
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
if motion_frame_subscribtion:
|
|
527
|
+
self.motion_frame_subscribers.remove(motion_frame_subscribtion)
|
|
528
|
+
await motion_frame_subscribtion["subscriber"].close()
|
|
515
529
|
|
|
516
|
-
if self.
|
|
517
|
-
self.
|
|
530
|
+
if len(self.motion_frame_subscribers) == 0:
|
|
531
|
+
await self.__close_motion_frame_subscribers()
|
|
518
532
|
|
|
519
533
|
@overload
|
|
520
534
|
def get_value(self, state_name: Literal["light"]) -> LightState: ...
|
|
@@ -913,6 +927,8 @@ class CameraDeviceProxy:
|
|
|
913
927
|
det["boundingBox"] = cast(tuple[int, int, int, int], tuple(det["boundingBox"]))
|
|
914
928
|
det["confidence"] = float(det["confidence"])
|
|
915
929
|
|
|
930
|
+
motion_event["detections"] = merge_detections(motion_event["detections"])
|
|
931
|
+
|
|
916
932
|
motion_event["detections"] = are_motion_detections_valid(
|
|
917
933
|
motion_event["detections"], self.activity_zones, self.activity_settings
|
|
918
934
|
)
|
|
@@ -1433,37 +1449,48 @@ class CameraDeviceProxy:
|
|
|
1433
1449
|
metadata = metadata_response.get("metadata")
|
|
1434
1450
|
|
|
1435
1451
|
return metadata
|
|
1436
|
-
except
|
|
1437
|
-
self.logger.error("Failed to get metadata! Frame Worker FFmpeg process might not be running")
|
|
1452
|
+
except Exception as e:
|
|
1453
|
+
self.logger.error("Failed to get metadata! Frame Worker FFmpeg process might not be running", e)
|
|
1438
1454
|
|
|
1439
1455
|
async def __disconnect_from_decoder(self, request_id: str) -> None:
|
|
1440
1456
|
if request_id in self.active_requests:
|
|
1441
1457
|
self.active_requests.remove(request_id)
|
|
1442
1458
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1459
|
+
frame_subscription = next(
|
|
1460
|
+
(sub for sub in self.frame_subscribers if sub["request_id"] == request_id), None
|
|
1461
|
+
)
|
|
1445
1462
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
"
|
|
1449
|
-
"cameraId": self.id,
|
|
1450
|
-
"pluginId": self.plugin["id"],
|
|
1451
|
-
}
|
|
1463
|
+
if frame_subscription:
|
|
1464
|
+
self.frame_subscribers.remove(frame_subscription)
|
|
1465
|
+
await frame_subscription["subscriber"].close()
|
|
1452
1466
|
|
|
1453
|
-
|
|
1467
|
+
if self.signaling_publisher:
|
|
1468
|
+
message: SignalingRequest = {
|
|
1469
|
+
"type": "disconnect",
|
|
1470
|
+
"requestId": request_id,
|
|
1471
|
+
"cameraId": self.id,
|
|
1472
|
+
"pluginId": self.plugin["id"],
|
|
1473
|
+
}
|
|
1454
1474
|
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1475
|
+
await self.signaling_publisher.publish(self.signaling_target_subject, message)
|
|
1476
|
+
|
|
1477
|
+
async def __close_frame_subscribers(self) -> None:
|
|
1478
|
+
self.active_requests.clear()
|
|
1479
|
+
|
|
1480
|
+
for sub in self.frame_subscribers:
|
|
1481
|
+
with suppress(Exception):
|
|
1482
|
+
await sub["subscriber"].close()
|
|
1460
1483
|
|
|
1461
|
-
|
|
1462
|
-
|
|
1484
|
+
self.frame_subscribers.clear()
|
|
1485
|
+
|
|
1486
|
+
async def __close_motion_frame_subscribers(self) -> None:
|
|
1487
|
+
self.active_motion_requests.clear()
|
|
1488
|
+
|
|
1489
|
+
for sub in self.motion_frame_subscribers:
|
|
1463
1490
|
with suppress(Exception):
|
|
1464
|
-
await
|
|
1491
|
+
await sub["subscriber"].close()
|
|
1465
1492
|
|
|
1466
|
-
|
|
1493
|
+
self.motion_frame_subscribers.clear()
|
|
1467
1494
|
|
|
1468
1495
|
async def __request_handler(self, message: ProxyMessageStructure) -> None:
|
|
1469
1496
|
if not self.message_queue:
|
|
@@ -1565,8 +1592,16 @@ class CameraDeviceProxy:
|
|
|
1565
1592
|
if message["requestId"] in self.active_requests:
|
|
1566
1593
|
self.active_requests.remove(message["requestId"])
|
|
1567
1594
|
|
|
1595
|
+
frame_subscribtion = next(
|
|
1596
|
+
(sub for sub in self.frame_subscribers if sub["request_id"] == message["requestId"]), None
|
|
1597
|
+
)
|
|
1598
|
+
|
|
1599
|
+
if frame_subscribtion:
|
|
1600
|
+
self.frame_subscribers.remove(frame_subscribtion)
|
|
1601
|
+
await frame_subscribtion["subscriber"].close()
|
|
1602
|
+
|
|
1568
1603
|
if len(self.active_requests) == 0:
|
|
1569
|
-
self.tasks.add(self.
|
|
1604
|
+
self.tasks.add(self.__close_frame_subscribers())
|
|
1570
1605
|
|
|
1571
1606
|
async def __respond_to_signaling_message(self, msg: Msg, message: PingMessage) -> None:
|
|
1572
1607
|
try:
|
|
@@ -41,10 +41,10 @@ class CoreManager(AsyncIOEventEmitter):
|
|
|
41
41
|
self.cm_subject = "coreManager.subscriber"
|
|
42
42
|
|
|
43
43
|
self.publisher: Optional[ProxyConnection] = None
|
|
44
|
-
self.
|
|
44
|
+
self.cm_publisher: Optional[ProxyConnection] = None
|
|
45
45
|
|
|
46
46
|
self.subscriber: Optional[ProxySubscription] = None
|
|
47
|
-
self.
|
|
47
|
+
self.cm_subscriber: Optional[ProxySubscription] = None
|
|
48
48
|
|
|
49
49
|
self.tasks: TaskSet = TaskSet(f"{self.plugin['name']} CoreManager")
|
|
50
50
|
self.message_queue: Optional[MessageQueue] = None
|
|
@@ -64,8 +64,8 @@ class CoreManager(AsyncIOEventEmitter):
|
|
|
64
64
|
self.publisher = ProxyConnection(self.subject, servers, self.auth)
|
|
65
65
|
await self.publisher.connect()
|
|
66
66
|
|
|
67
|
-
self.
|
|
68
|
-
await self.
|
|
67
|
+
self.cm_publisher = ProxyConnection(self.cm_subject, servers, self.auth)
|
|
68
|
+
await self.cm_publisher.connect()
|
|
69
69
|
|
|
70
70
|
self.subscriber = await self.publisher.subscribe(subject=self.subject)
|
|
71
71
|
self.message_queue = MessageQueue(
|
|
@@ -75,8 +75,8 @@ class CoreManager(AsyncIOEventEmitter):
|
|
|
75
75
|
self.__request_handler,
|
|
76
76
|
)
|
|
77
77
|
|
|
78
|
-
self.
|
|
79
|
-
self.
|
|
78
|
+
self.cm_subscriber = await self.cm_publisher.subscribe(subject=self.cm_subject)
|
|
79
|
+
self.cm_subscriber.on("message", self.__on_proxy_message)
|
|
80
80
|
|
|
81
81
|
async def get_ffmpeg_path(self) -> str:
|
|
82
82
|
return await self.__on_request("getFFmpegPath")
|
|
@@ -141,5 +141,5 @@ class CoreManager(AsyncIOEventEmitter):
|
|
|
141
141
|
if self.publisher:
|
|
142
142
|
await self.publisher.close()
|
|
143
143
|
|
|
144
|
-
if self.
|
|
145
|
-
await self.
|
|
144
|
+
if self.cm_publisher:
|
|
145
|
+
await self.cm_publisher.close()
|