@camera.ui/server 0.0.69 → 0.0.71-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +91 -0
- package/README.md +0 -24
- package/cupdate.config.txt +0 -1
- package/dist/interface/assets/404-CIsBB4A0.js +1 -0
- package/dist/interface/assets/About-CkxZb9D-.js +1 -0
- package/dist/interface/assets/Adminpanel-BrZ55JBx.js +1 -0
- package/dist/interface/assets/Automation-BKhuIS2v.js +2 -0
- package/dist/interface/assets/Automation-Csu8t0D7.css +1 -0
- package/dist/interface/assets/Automations-CzdnqGGU.js +1 -0
- package/dist/interface/assets/Camera-BhCDJE7I.css +1 -0
- package/dist/interface/assets/Camera-CU3aKdBR.js +2 -0
- package/dist/interface/assets/CameraConsole-D7KxwRxQ.js +7 -0
- package/dist/interface/assets/Cameras-807mspcl.css +1 -0
- package/dist/interface/assets/Cameras-DJcAfGpU.js +656 -0
- package/dist/interface/assets/Camview-ArBQ3nES.js +1 -0
- package/dist/interface/assets/Camview-Dd7DwMHG.css +1 -0
- package/dist/interface/assets/Config-D2ftkjl2.js +2 -0
- package/dist/interface/assets/Config-JgftUZFe.css +1 -0
- package/dist/interface/assets/ConfigActionCameraControl-94iyzBzJ.js +1 -0
- package/dist/interface/assets/ConfigActionDelay-DKhE0Xr8.js +1 -0
- package/dist/interface/assets/ConfigActionHttp-BbfN1UGF.js +1 -0
- package/dist/interface/assets/ConfigActionImageInput-P39gRfld.js +1 -0
- package/dist/interface/assets/ConfigActionNotification-CuDDnksK.js +1 -0
- package/dist/interface/assets/ConfigActionOutput-BIHvC1Z5.js +1 -0
- package/dist/interface/assets/ConfigActionPlugin-CDA53LwA.js +1 -0
- package/dist/interface/assets/ConfigActionSensor-BBkfWT_r.js +1 -0
- package/dist/interface/assets/ConfigActionSnapshot-C5enxVcl.js +1 -0
- package/dist/interface/assets/ConfigActionVariable-CVaOMoOi.js +1 -0
- package/dist/interface/assets/ConfigConditionIfElse-DiIOUqA5.js +1 -0
- package/dist/interface/assets/ConfigConditionSensorState-DBktbA8F.js +1 -0
- package/dist/interface/assets/ConfigConditionSwitch-DWqcQ3Ip.js +1 -0
- package/dist/interface/assets/ConfigConditionTime-BEaHclqa.js +1 -0
- package/dist/interface/assets/ConfigTriggerDetection-CRnZR91p.js +1 -0
- package/dist/interface/assets/ConfigTriggerGeofence-DODdJBZW.js +1 -0
- package/dist/interface/assets/ConfigTriggerManual-V8-5hrdl.js +1 -0
- package/dist/interface/assets/ConfigTriggerSchedule-CqID85d1.js +1 -0
- package/dist/interface/assets/ConfigTriggerSensor-DR6ifBrK.js +1 -0
- package/dist/interface/assets/ConfigTriggerSystem-K1ohOW18.js +1 -0
- package/dist/interface/assets/ConfigTriggerWebhook-Cmwu5IU4.js +1 -0
- package/dist/interface/assets/Console-IC7AOnvc.js +6 -0
- package/dist/interface/assets/CuiActionButton-Ba5wT-4n.js +1 -0
- package/dist/interface/assets/CuiAvatar-BtMXnhxd.css +1 -0
- package/dist/interface/assets/CuiAvatar-Bu4NixiB.js +1 -0
- package/dist/interface/assets/CuiBBoxPlayground-Cmbd4_qG.js +1 -0
- package/dist/interface/assets/CuiBBoxPlayground-EFkdOBvq.css +1 -0
- package/dist/interface/assets/CuiBottomSheet-BN5exkJm.js +1 -0
- package/dist/interface/assets/CuiBottomSheet-CHspaYgP.js +1 -0
- package/dist/interface/assets/CuiBottomSheet-DxQ6D_RM.css +1 -0
- package/dist/interface/assets/CuiCameraCard-C7eDwhgw.js +1 -0
- package/dist/interface/assets/CuiCameraCard-dNsAwlKS.css +1 -0
- package/dist/interface/assets/CuiCameraPipCard-C8Pg7xT9.js +1 -0
- package/dist/interface/assets/CuiCameraPipCard-D3o29_wc.css +1 -0
- package/dist/interface/assets/CuiCameraRecordings-CQHbo-_J.js +1 -0
- package/dist/interface/assets/CuiCameraRecordings-DM_o0Lya.css +1 -0
- package/dist/interface/assets/CuiCameraShares-DNuCgk4b.js +1 -0
- package/dist/interface/assets/CuiCameraSnapshot-BpUMwSoR.js +1 -0
- package/dist/interface/assets/CuiCameraTable-DQffvTtY.js +2 -0
- package/dist/interface/assets/CuiFloatingButton-RaxwbGht.js +1 -0
- package/dist/interface/assets/CuiImage-60jwFIqc.js +1 -0
- package/dist/interface/assets/CuiImage-Bxf7z2N4.css +1 -0
- package/dist/interface/assets/CuiMarkdownContent-M5v8bBmS.js +1 -0
- package/dist/interface/assets/CuiMenu-B4CHT2F_.js +1 -0
- package/dist/interface/assets/CuiMenu-BWUfWLQP.css +1 -0
- package/dist/interface/assets/CuiPluginCard-5ItfIe1Z.js +2 -0
- package/dist/interface/assets/CuiPluginCard-CTTsEM9M.css +1 -0
- package/dist/interface/assets/CuiPluginOAuthButton-BJRU2JBX.js +2 -0
- package/dist/interface/assets/CuiQRCode-CNeepRQw.js +1 -0
- package/dist/interface/assets/CuiQRCode-DfUba6JB.css +1 -0
- package/dist/interface/assets/CuiRecordingsGrid-CKHFeJlJ.js +1 -0
- package/dist/interface/assets/CuiRecordingsGrid-CZIZiEuT.css +1 -0
- package/dist/interface/assets/CuiSchema--yMBD996.css +1 -0
- package/dist/interface/assets/CuiSchema-CTRLO0uq.js +1 -0
- package/dist/interface/assets/CuiTopNavbarItem-CgaR_X1z.js +1 -0
- package/dist/interface/assets/CuiTopNavbarItem-w54CrODK.css +1 -0
- package/dist/interface/assets/CuiTopbarSlot-BDZoZ_yn.js +1 -0
- package/dist/interface/assets/Faces-JoBk1Mcv.js +1 -0
- package/dist/interface/assets/FirstSteps-CSMvd_p0.js +1 -0
- package/dist/interface/assets/Instances-DwNihvsL.js +1 -0
- package/dist/interface/assets/Menu-CUnOgtD5.js +1 -0
- package/dist/interface/assets/OAuthDeviceFlow-aUHpE7wP.js +1 -0
- package/dist/interface/assets/Plugin-DoxdkvWR.css +1 -0
- package/dist/interface/assets/Plugin-LjpUwn17.js +1 -0
- package/dist/interface/assets/PluginConsole-CvDWPKOs.js +7 -0
- package/dist/interface/assets/PluginSchema-DL7Bfd_U.js +1 -0
- package/dist/interface/assets/Plugins-B207FOsG.js +2 -0
- package/dist/interface/assets/Plugins-BPt1RSKT.css +1 -0
- package/dist/interface/assets/Recordings-Bt_GlPOK.css +1 -0
- package/dist/interface/assets/Recordings-adHTSogQ.js +1 -0
- package/dist/interface/assets/Settings-bwLTNAxX.css +1 -0
- package/dist/interface/assets/Settings-iBjUbXTH.js +1 -0
- package/dist/interface/assets/SettingsAccount-Ce0UnkLb.js +1 -0
- package/dist/interface/assets/SettingsAccount-DXKQY4Iz.css +1 -0
- package/dist/interface/assets/SettingsAccount-f2wkt4kx.js +1 -0
- package/dist/interface/assets/SettingsAppearance-2TfnSgkI.js +1 -0
- package/dist/interface/assets/SettingsAppearance-Dca237An.js +1 -0
- package/dist/interface/assets/SettingsBackup-Bh5x-GU_.js +1 -0
- package/dist/interface/assets/SettingsNotifications-BVmhorXq.js +2 -0
- package/dist/interface/assets/SettingsRecordings-dPUm5hma.js +1 -0
- package/dist/interface/assets/SettingsRemote-BcVzn2m3.js +1 -0
- package/dist/interface/assets/SettingsRemote-CjVK9pGg.css +1 -0
- package/dist/interface/assets/SettingsSystem-Dz76BUJ-.js +2 -0
- package/dist/interface/assets/SettingsUsers-Dzj--Rmf.js +1 -0
- package/dist/interface/assets/Terminal-BAMMh8Px.js +4 -0
- package/dist/interface/assets/Terminal-CrOfQJ-O.css +1 -0
- package/dist/interface/assets/VariableInput-D_-qKfZK.js +1 -0
- package/dist/interface/assets/VariableSuggestions-Br4yDsLZ.js +1 -0
- package/dist/interface/assets/VersionsHandler-CfNT3Yke.js +7 -0
- package/dist/interface/assets/Workers-D3jFWBjm.js +1 -0
- package/dist/interface/assets/_plugin-vue_export-helper-BDNMzG2s.js +1 -0
- package/dist/interface/assets/ace-BRyQJK-L.js +1 -0
- package/dist/interface/assets/ace.config-fXRdG20S.js +1 -0
- package/dist/interface/assets/alert-outline-D3FCIX7_.js +1 -0
- package/dist/interface/assets/api-BaywoTCE.js +2 -0
- package/dist/interface/assets/api-Cna9Poda.css +2 -0
- package/dist/interface/assets/api-DvuXV3Xb.js +1 -0
- package/dist/interface/assets/auth-Cu-pUvKk.js +1 -0
- package/dist/interface/assets/automation-CbEPnAW4.js +1 -0
- package/dist/interface/assets/automations-Bj3wF0wR.js +1 -0
- package/dist/interface/assets/automations-C6ssihoC.js +1 -0
- package/dist/interface/assets/back-filled-CvLD0CND.js +1 -0
- package/dist/interface/assets/backup-DK5aZBLo.js +1 -0
- package/dist/interface/assets/bell-outline-JZZKpcfS.js +1 -0
- package/dist/interface/assets/camera-preview-C7GT5VHo.png +0 -0
- package/dist/interface/assets/cameras-DQ28quQb.js +1 -0
- package/dist/interface/assets/cameras.schema-CDeB5JeE.js +1 -0
- package/dist/interface/assets/cctv-SQFfbBnL.js +1 -0
- package/dist/interface/assets/check-BQQidcYi.js +1 -0
- package/dist/interface/assets/chevron-down-Dd1qHXVA.js +1 -0
- package/dist/interface/assets/chevron-right-DOmJR2OL.js +1 -0
- package/dist/interface/assets/circular-connection-nKCVm4QI.js +1 -0
- package/dist/interface/assets/close-Dhjo4o57.js +1 -0
- package/dist/interface/assets/close-WdhW_91X.js +1 -0
- package/dist/interface/assets/close-circle-i5PrRG0X.js +1 -0
- package/dist/interface/assets/close-rounded-6nzLVPw0.js +1 -0
- package/dist/interface/assets/cloud-check-DeN6leiB.js +1 -0
- package/dist/interface/assets/cloud-outline-BHjUiP9q.js +1 -0
- package/dist/interface/assets/cloud-outline-BQddJElX.js +1 -0
- package/dist/interface/assets/cloudHandoff-DxhttWWd.js +1 -0
- package/dist/interface/assets/cog-Batjj1se.js +1 -0
- package/dist/interface/assets/copy-16-filled-DuAEBVEX.js +1 -0
- package/dist/interface/assets/copy-BeuZDsJN.js +1 -0
- package/dist/interface/assets/delete-DvMWXBFV.js +1 -0
- package/dist/interface/assets/dist-CcCNy5h7.js +1 -0
- package/dist/interface/assets/download-Cna5QEEj.js +1 -0
- package/dist/interface/assets/esm-B4Pd2w1t.js +1 -0
- package/dist/interface/assets/esm-B4l8-ACY.js +1 -0
- package/dist/interface/assets/esm-BE98HKPg.js +1 -0
- package/dist/interface/assets/esm-BNSLSv2m.js +1 -0
- package/dist/interface/assets/esm-BnT9fzsT.js +1 -0
- package/dist/interface/assets/esm-C-uLCRX1.js +1 -0
- package/dist/interface/assets/esm-C6JCcz6o.js +1 -0
- package/dist/interface/assets/esm-D5_rxfjE.js +1 -0
- package/dist/interface/assets/esm-D6ymjVa1.js +1 -0
- package/dist/interface/assets/esm-D8teZoG1.js +1 -0
- package/dist/interface/assets/esm-DnSGrmvg.js +1 -0
- package/dist/interface/assets/esm-DqkQVzkL.js +1 -0
- package/dist/interface/assets/esm-tnu6qUMk.js +1 -0
- package/dist/interface/assets/eventIcons-2hVCNchU.css +1 -0
- package/dist/interface/assets/eventIcons-DVykqtE5.js +1 -0
- package/dist/interface/assets/face-recognition-5Yp1IcUb.js +1 -0
- package/dist/interface/assets/github-37yEERpu.js +1 -0
- package/dist/interface/assets/grid-fill-BGU3gqir.js +1 -0
- package/dist/interface/assets/hasPermission-DIF0bX8u.js +1 -0
- package/dist/interface/assets/home-sSF_NnOu.js +1 -0
- package/dist/interface/assets/information-outline-fu18_QSH.js +1 -0
- package/dist/interface/assets/instances-DGPhZWRw.js +1 -0
- package/dist/interface/assets/lightbulb-outline-DWc53kV7.js +1 -0
- package/dist/interface/assets/locale-Bm1nXzqV.js +1 -0
- package/dist/interface/assets/main-BqVSZVz1.css +1 -0
- package/dist/interface/assets/main-D1gFWXGG.js +3 -0
- package/dist/interface/assets/microphone-ChDR4mkG.js +1 -0
- package/dist/interface/assets/native-Cq3ra8E-.js +1 -0
- package/dist/interface/assets/native-DfLBhmBo.js +1 -0
- package/dist/interface/assets/nodeDefinitions-BLSMZueH.js +1 -0
- package/dist/interface/assets/notifications-DNRzOl89.js +1 -0
- package/dist/interface/assets/play-solid-B_749j1A.js +1 -0
- package/dist/interface/assets/plugin-C1NakF2p.js +1 -0
- package/dist/interface/assets/plugins-DzRwEcA4.js +1 -0
- package/dist/interface/assets/plus-B5eEboLZ.js +1 -0
- package/dist/interface/assets/plus-Dis0MPt8.js +1 -0
- package/dist/interface/assets/power-CxGfHa98.js +1 -0
- package/dist/interface/assets/ring-resize-fOkdAS5R.js +1 -0
- package/dist/interface/assets/rolldown-runtime-CMxvf4Kt.js +1 -0
- package/dist/interface/assets/round-alt-arrow-left-bold-ekP_ATNV.js +1 -0
- package/dist/interface/assets/round-restart-alt-BWTTuG_j.js +1 -0
- package/dist/interface/assets/round-restart-alt-CJgRaJjF.css +1 -0
- package/dist/interface/assets/router-CuAn6JZ_.css +1 -0
- package/dist/interface/assets/router-DGyFln7e.js +2 -0
- package/dist/interface/assets/routerState-DMVeYr60.js +1 -0
- package/dist/interface/assets/search-YdrT6au7.js +1 -0
- package/dist/interface/assets/server-BWxbeZzY.js +1 -0
- package/dist/interface/assets/settings-D2-mWioF.js +1 -0
- package/dist/interface/assets/shares-BLuBJftj.js +1 -0
- package/dist/interface/assets/shield-check-DFR-xg-g.js +1 -0
- package/dist/interface/assets/terminal-BYi6cqd4.js +1 -0
- package/dist/interface/assets/theme-D08Upl8q.js +1 -0
- package/dist/interface/assets/trash-2-Du7oioNA.js +1 -0
- package/dist/interface/assets/trash-can-YTXLzAmt.js +1 -0
- package/dist/interface/assets/trash-fill-ZI3YYgNp.js +1 -0
- package/dist/interface/assets/types-B_isDU64.js +1 -0
- package/dist/interface/assets/types-BxFyoO54.js +1 -0
- package/dist/interface/assets/types-kxdn9XBW.js +1 -0
- package/dist/interface/assets/ui-aYGNqaHi.js +1 -0
- package/dist/interface/assets/upload-Chr4Uunq.js +1 -0
- package/dist/interface/assets/useBiometricCredentials-B-zA6b-X.js +1 -0
- package/dist/interface/assets/useCameraOptions-0w0LNh72.js +1 -0
- package/dist/interface/assets/useCuiCameraDrawer-Dn97MLFe.js +1 -0
- package/dist/interface/assets/useCuiDialog-BbkaNkQN.js +2 -0
- package/dist/interface/assets/useElectron-mh8HQUAI.js +1 -0
- package/dist/interface/assets/useFileDownload-g3sM8lp6.js +1 -0
- package/dist/interface/assets/useLogsSocket-CZld674d.js +4 -0
- package/dist/interface/assets/useLogsSocket-pqdh7jNG.css +1 -0
- package/dist/interface/assets/useSharedComposables-riqEUgwX.js +1 -0
- package/dist/interface/assets/useStreamStatus-2lguNuWT.js +1 -0
- package/dist/interface/assets/users.schema-CUZOYClB.js +1 -0
- package/dist/interface/assets/vendor-DmhYd_sB.js +22 -0
- package/dist/interface/assets/vendor-ace-B9YSA4ub.js +1085 -0
- package/dist/interface/assets/vendor-cameraui-DggYb17u.js +1976 -0
- package/dist/interface/assets/vendor-capacitor-IA6kwsx8.js +2 -0
- package/dist/interface/assets/vendor-chart-Dnlz1Jgy.js +3 -0
- package/dist/interface/assets/vendor-core-B6F-imJj.js +1 -0
- package/dist/interface/assets/vendor-dnd-Dp0ottZI.js +2 -0
- package/dist/interface/assets/vendor-draggabilly-C2ae3o70.js +1 -0
- package/dist/interface/assets/vendor-gridstack-Dxjc1EeA.js +3 -0
- package/dist/interface/assets/vendor-gridstack-Rg2RhwAc.css +1 -0
- package/dist/interface/assets/vendor-leaflet-B5L2Aw8Y.js +1 -0
- package/dist/interface/assets/vendor-leaflet-vh-t_kPv.css +1 -0
- package/dist/interface/assets/vendor-markdown-D3nVi7gw.js +15 -0
- package/dist/interface/assets/vendor-markdown-DtOhvyRx.css +1 -0
- package/dist/interface/assets/vendor-primevue--pcuf6kA.js +4289 -0
- package/dist/interface/assets/vendor-vueflow-CBuKPASC.js +26 -0
- package/dist/interface/assets/vendor-xterm-BrP-ENHg.css +1 -0
- package/dist/interface/assets/vendor-xterm-D8Z_h2U0.js +145 -0
- package/dist/interface/assets/vendor-zod-CmGeQCqy.js +127 -0
- package/dist/interface/assets/view-grid-96p9T-KQ.js +1 -0
- package/dist/interface/assets/view-grid-SdzaC3O_.css +1 -0
- package/dist/interface/assets/web-3Sh2qjiP.js +1 -0
- package/dist/interface/assets/web-B0BK4Q2M.js +1 -0
- package/dist/interface/assets/web-BjKL51lK-DzG2kK8Q.js +1 -0
- package/dist/interface/assets/web-COttRPza.js +1 -0
- package/dist/interface/assets/web-Ck1J3gUt.js +1 -0
- package/dist/interface/assets/web-DPxPmEOR.js +1 -0
- package/dist/interface/assets/web-DRprnZwc.js +1 -0
- package/dist/interface/assets/web-DusfFKJE.js +1 -0
- package/dist/interface/assets/web-U3ajDFzM.js +1 -0
- package/dist/interface/assets/web-jcLz0P7f.js +1 -0
- package/dist/interface/assets/web-tQAiC0W2.js +1 -0
- package/dist/interface/assets/web-x9pvmNMf.js +1 -0
- package/dist/interface/assets/workbox-window.prod.es5-DkzC-kEO.js +1 -0
- package/dist/interface/assets/worker-base-ybazWkNy.js +1337 -0
- package/dist/interface/assets/worker-yaml-crtWQpDN.js +5824 -0
- package/dist/interface/assets/zoom-in-zoFmMkYM.js +1 -0
- package/dist/interface/index.html +96 -45
- package/dist/interface/manifest.webmanifest +1 -1
- package/dist/interface/og-share.png +0 -0
- package/dist/interface/sw.js +1 -1
- package/dist/interface/workbox-5f44db27.js +1 -0
- package/dist/server/package.json +73 -79
- package/dist/server/requirements.txt +9 -14
- package/dist/server/src/_camera_ui_tools/camera_ui_common/__init__.py +19 -11
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/__init__.py +23 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/object_path.py +35 -22
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/promise.py +41 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/reactive.py +17 -14
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/signal_handler.py +12 -4
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/subscribed.py +15 -2
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/task.py +9 -3
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/thread.py +10 -2
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/utils.py +21 -13
- package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/__init__.py +8 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/logger.py +237 -99
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/__init__.py +77 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/channel.py +321 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/chunking.py +290 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/client.py +1694 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/codec.py +73 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/decorators.py +307 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/errors.py +76 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/executor.py +29 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/handler.py +523 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/service.py +524 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/svcm.py +15 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/types.py +427 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/utils.py +332 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/__init__.py +515 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/__init__.py +173 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/config.py +256 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/detection.py +135 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/device.py +432 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/enums.py +111 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/events.py +146 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/frames.py +21 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/streaming.py +188 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/__init__.py +92 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/camera_config_internal.py +46 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/camera_enums.py +9 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/camera_wire.py +15 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/event_emitter.py +102 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/manager_rpc.py +27 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/sensor_rpc.py +89 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/sensor_triggers.py +4 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/shared_utils.py +73 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/streaming_internal.py +16 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/manager/__init__.py +348 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/observable/__init__.py +557 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/__init__.py +104 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/api.py +137 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/contract.py +164 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/helper.py +242 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/interfaces.py +427 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/notifier.py +142 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/oauth.py +150 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/__init__.py +203 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/audio.py +241 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/base.py +551 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/battery.py +167 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/classifier.py +196 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/clip.py +67 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/contact.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/detection.py +60 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/doorbell.py +122 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/face.py +184 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/garage.py +174 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/humidity.py +79 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/leak.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/license_plate.py +186 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/light.py +157 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/lock.py +149 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/motion.py +203 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/object.py +210 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/occupancy.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/ptz.py +256 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/security_system.py +157 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/siren.py +150 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/smoke.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/spec.py +56 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/switch.py +107 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/temperature.py +80 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/storage/__init__.py +695 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/types.py +54 -0
- package/dist/server/src/api/controllers/api.controller.d.ts +2 -2
- package/dist/server/src/api/controllers/api.controller.js +3 -3
- package/dist/server/src/api/controllers/api.controller.js.map +1 -1
- package/dist/server/src/api/controllers/auth.controller.d.ts +20 -5
- package/dist/server/src/api/controllers/auth.controller.js +418 -134
- package/dist/server/src/api/controllers/auth.controller.js.map +1 -1
- package/dist/server/src/api/controllers/automations.controller.d.ts +17 -0
- package/dist/server/src/api/controllers/automations.controller.js +146 -0
- package/dist/server/src/api/controllers/automations.controller.js.map +1 -0
- package/dist/server/src/api/controllers/backup.controller.js +0 -1
- package/dist/server/src/api/controllers/backup.controller.js.map +1 -1
- package/dist/server/src/api/controllers/cameras.controller.d.ts +14 -5
- package/dist/server/src/api/controllers/cameras.controller.js +490 -69
- package/dist/server/src/api/controllers/cameras.controller.js.map +1 -1
- package/dist/server/src/api/controllers/config.controller.d.ts +2 -2
- package/dist/server/src/api/controllers/config.controller.js +2 -2
- package/dist/server/src/api/controllers/config.controller.js.map +1 -1
- package/dist/server/src/api/controllers/download.controller.d.ts +7 -0
- package/dist/server/src/api/controllers/download.controller.js +12 -0
- package/dist/server/src/api/controllers/download.controller.js.map +1 -0
- package/dist/server/src/api/controllers/files.controller.js.map +1 -1
- package/dist/server/src/api/controllers/frameWorkers.controller.d.ts +1 -1
- package/dist/server/src/api/controllers/frameWorkers.controller.js +1 -1
- package/dist/server/src/api/controllers/frameWorkers.controller.js.map +1 -1
- package/dist/server/src/api/controllers/instances.controller.d.ts +15 -0
- package/dist/server/src/api/controllers/instances.controller.js +100 -0
- package/dist/server/src/api/controllers/instances.controller.js.map +1 -0
- package/dist/server/src/api/controllers/notifications.controller.d.ts +15 -0
- package/dist/server/src/api/controllers/notifications.controller.js +121 -0
- package/dist/server/src/api/controllers/notifications.controller.js.map +1 -0
- package/dist/server/src/api/controllers/oauthCallback.controller.d.ts +15 -0
- package/dist/server/src/api/controllers/oauthCallback.controller.js +53 -0
- package/dist/server/src/api/controllers/oauthCallback.controller.js.map +1 -0
- package/dist/server/src/api/controllers/plugins.controller.d.ts +5 -9
- package/dist/server/src/api/controllers/plugins.controller.js +129 -246
- package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
- package/dist/server/src/api/controllers/remote.controller.d.ts +27 -0
- package/dist/server/src/api/controllers/remote.controller.js +247 -0
- package/dist/server/src/api/controllers/remote.controller.js.map +1 -0
- package/dist/server/src/api/controllers/server.controller.d.ts +24 -0
- package/dist/server/src/api/controllers/server.controller.js +236 -0
- package/dist/server/src/api/controllers/server.controller.js.map +1 -0
- package/dist/server/src/api/controllers/shares.controller.d.ts +12 -0
- package/dist/server/src/api/controllers/shares.controller.js +121 -0
- package/dist/server/src/api/controllers/shares.controller.js.map +1 -0
- package/dist/server/src/api/controllers/tunnel.controller.d.ts +9 -0
- package/dist/server/src/api/controllers/tunnel.controller.js +39 -0
- package/dist/server/src/api/controllers/tunnel.controller.js.map +1 -0
- package/dist/server/src/api/controllers/users.controller.d.ts +2 -2
- package/dist/server/src/api/controllers/users.controller.js +11 -2
- package/dist/server/src/api/controllers/users.controller.js.map +1 -1
- package/dist/server/src/api/controllers/workers.controller.d.ts +14 -0
- package/dist/server/src/api/controllers/workers.controller.js +69 -0
- package/dist/server/src/api/controllers/workers.controller.js.map +1 -0
- package/dist/server/src/api/database/checks.js +2 -2
- package/dist/server/src/api/database/checks.js.map +1 -1
- package/dist/server/src/api/database/constants.d.ts +10 -1
- package/dist/server/src/api/database/constants.js +10 -1
- package/dist/server/src/api/database/constants.js.map +1 -1
- package/dist/server/src/api/database/index.d.ts +24 -12
- package/dist/server/src/api/database/index.js +182 -126
- package/dist/server/src/api/database/index.js.map +1 -1
- package/dist/server/src/api/database/migration.d.ts +4 -13
- package/dist/server/src/api/database/migration.js +20 -80
- package/dist/server/src/api/database/migration.js.map +1 -1
- package/dist/server/src/api/database/migrations/index.d.ts +2 -0
- package/dist/server/src/api/database/migrations/index.js +24 -0
- package/dist/server/src/api/database/migrations/index.js.map +1 -0
- package/dist/server/src/api/database/migrations/types.d.ts +13 -0
- package/dist/server/src/api/database/migrations/types.js.map +1 -0
- package/dist/server/src/api/database/selfcheck.js +3 -0
- package/dist/server/src/api/database/selfcheck.js.map +1 -1
- package/dist/server/src/api/database/types.d.ts +173 -28
- package/dist/server/src/api/index.d.ts +8 -2
- package/dist/server/src/api/index.js +122 -43
- package/dist/server/src/api/index.js.map +1 -1
- package/dist/server/src/api/middlewares/authPermission.middleware.d.ts +4 -4
- package/dist/server/src/api/middlewares/authPermission.middleware.js +8 -8
- package/dist/server/src/api/middlewares/authPermission.middleware.js.map +1 -1
- package/dist/server/src/api/middlewares/authValidation.middleware.d.ts +5 -2
- package/dist/server/src/api/middlewares/authValidation.middleware.js +75 -114
- package/dist/server/src/api/middlewares/authValidation.middleware.js.map +1 -1
- package/dist/server/src/api/middlewares/pagination.middleware.d.ts +1 -1
- package/dist/server/src/api/middlewares/pagination.middleware.js +2 -2
- package/dist/server/src/api/middlewares/pagination.middleware.js.map +1 -1
- package/dist/server/src/api/middlewares/socketAuth.middleware.d.ts +2 -2
- package/dist/server/src/api/middlewares/socketAuth.middleware.js +5 -4
- package/dist/server/src/api/middlewares/socketAuth.middleware.js.map +1 -1
- package/dist/server/src/api/plugins/header.plugin.js +1 -1
- package/dist/server/src/api/plugins/header.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/logger.plugin.js +13 -10
- package/dist/server/src/api/plugins/logger.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/proxy.plugin.js +76 -105
- package/dist/server/src/api/plugins/proxy.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/system.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/useragent.plugin.d.ts +2 -2
- package/dist/server/src/api/plugins/useragent.plugin.js +2 -2
- package/dist/server/src/api/plugins/useragent.plugin.js.map +1 -1
- package/dist/server/src/api/routes/api.routes.js +18 -2
- package/dist/server/src/api/routes/api.routes.js.map +1 -1
- package/dist/server/src/api/routes/auth.routes.js +131 -9
- package/dist/server/src/api/routes/auth.routes.js.map +1 -1
- package/dist/server/src/api/routes/automations.routes.d.ts +2 -0
- package/dist/server/src/api/routes/automations.routes.js +128 -0
- package/dist/server/src/api/routes/automations.routes.js.map +1 -0
- package/dist/server/src/api/routes/backup.routes.js +6 -0
- package/dist/server/src/api/routes/backup.routes.js.map +1 -1
- package/dist/server/src/api/routes/cameras.routes.js +346 -33
- package/dist/server/src/api/routes/cameras.routes.js.map +1 -1
- package/dist/server/src/api/routes/config.routes.js +26 -4
- package/dist/server/src/api/routes/config.routes.js.map +1 -1
- package/dist/server/src/api/routes/download.routes.d.ts +2 -0
- package/dist/server/src/api/routes/download.routes.js +16 -0
- package/dist/server/src/api/routes/download.routes.js.map +1 -0
- package/dist/server/src/api/routes/files.routes.js +7 -1
- package/dist/server/src/api/routes/files.routes.js.map +1 -1
- package/dist/server/src/api/routes/frameWorkers.routes.js +26 -4
- package/dist/server/src/api/routes/frameWorkers.routes.js.map +1 -1
- package/dist/server/src/api/routes/index.d.ts +1 -0
- package/dist/server/src/api/routes/index.js +23 -3
- package/dist/server/src/api/routes/index.js.map +1 -1
- package/dist/server/src/api/routes/instances.routes.d.ts +2 -0
- package/dist/server/src/api/routes/instances.routes.js +105 -0
- package/dist/server/src/api/routes/instances.routes.js.map +1 -0
- package/dist/server/src/api/routes/notifications.routes.d.ts +2 -0
- package/dist/server/src/api/routes/notifications.routes.js +102 -0
- package/dist/server/src/api/routes/notifications.routes.js.map +1 -0
- package/dist/server/src/api/routes/oauthCallback.routes.d.ts +2 -0
- package/dist/server/src/api/routes/oauthCallback.routes.js +17 -0
- package/dist/server/src/api/routes/oauthCallback.routes.js.map +1 -0
- package/dist/server/src/api/routes/plugins.routes.js +259 -95
- package/dist/server/src/api/routes/plugins.routes.js.map +1 -1
- package/dist/server/src/api/routes/remote.routes.d.ts +2 -0
- package/dist/server/src/api/routes/remote.routes.js +164 -0
- package/dist/server/src/api/routes/remote.routes.js.map +1 -0
- package/dist/server/src/api/routes/server.routes.d.ts +2 -0
- package/dist/server/src/api/routes/server.routes.js +130 -0
- package/dist/server/src/api/routes/server.routes.js.map +1 -0
- package/dist/server/src/api/routes/shares.routes.d.ts +2 -0
- package/dist/server/src/api/routes/shares.routes.js +71 -0
- package/dist/server/src/api/routes/shares.routes.js.map +1 -0
- package/dist/server/src/api/routes/tunnel.routes.d.ts +2 -0
- package/dist/server/src/api/routes/tunnel.routes.js +14 -0
- package/dist/server/src/api/routes/tunnel.routes.js.map +1 -0
- package/dist/server/src/api/routes/users.routes.js +92 -12
- package/dist/server/src/api/routes/users.routes.js.map +1 -1
- package/dist/server/src/api/routes/workers.routes.d.ts +2 -0
- package/dist/server/src/api/routes/workers.routes.js +71 -0
- package/dist/server/src/api/routes/workers.routes.js.map +1 -0
- package/dist/server/src/api/schemas/auth.schema.d.ts +35 -0
- package/dist/server/src/api/schemas/auth.schema.js +37 -0
- package/dist/server/src/api/schemas/auth.schema.js.map +1 -0
- package/dist/server/src/api/schemas/automations.schema.d.ts +151 -0
- package/dist/server/src/api/schemas/automations.schema.js +84 -0
- package/dist/server/src/api/schemas/automations.schema.js.map +1 -0
- package/dist/server/src/api/schemas/backup.schema.d.ts +15 -190
- package/dist/server/src/api/schemas/backup.schema.js +5 -23
- package/dist/server/src/api/schemas/backup.schema.js.map +1 -1
- package/dist/server/src/api/schemas/cameras.schema.d.ts +1062 -1647
- package/dist/server/src/api/schemas/cameras.schema.js +218 -49
- package/dist/server/src/api/schemas/cameras.schema.js.map +1 -1
- package/dist/server/src/api/schemas/common.schema.d.ts +7 -0
- package/dist/server/src/api/schemas/common.schema.js +7 -0
- package/dist/server/src/api/schemas/common.schema.js.map +1 -0
- package/dist/server/src/api/schemas/config.schema.d.ts +41 -79
- package/dist/server/src/api/schemas/config.schema.js +19 -1
- package/dist/server/src/api/schemas/config.schema.js.map +1 -1
- package/dist/server/src/api/schemas/download.schema.d.ts +5 -0
- package/dist/server/src/api/schemas/download.schema.js +5 -0
- package/dist/server/src/api/schemas/download.schema.js.map +1 -0
- package/dist/server/src/api/schemas/files.schema.d.ts +5 -0
- package/dist/server/src/api/schemas/files.schema.js +5 -0
- package/dist/server/src/api/schemas/files.schema.js.map +1 -0
- package/dist/server/src/api/schemas/frameWorkers.schema.d.ts +5 -0
- package/dist/server/src/api/schemas/frameWorkers.schema.js +5 -0
- package/dist/server/src/api/schemas/frameWorkers.schema.js.map +1 -0
- package/dist/server/src/api/schemas/go2rtc.schema.d.ts +90 -640
- package/dist/server/src/api/schemas/go2rtc.schema.js +1 -16
- package/dist/server/src/api/schemas/go2rtc.schema.js.map +1 -1
- package/dist/server/src/api/schemas/instances.schema.d.ts +23 -0
- package/dist/server/src/api/schemas/instances.schema.js +24 -0
- package/dist/server/src/api/schemas/instances.schema.js.map +1 -0
- package/dist/server/src/api/schemas/notifications.schema.d.ts +26 -0
- package/dist/server/src/api/schemas/notifications.schema.js +25 -0
- package/dist/server/src/api/schemas/notifications.schema.js.map +1 -0
- package/dist/server/src/api/schemas/oauthCallback.schema.d.ts +11 -0
- package/dist/server/src/api/schemas/oauthCallback.schema.js +10 -0
- package/dist/server/src/api/schemas/oauthCallback.schema.js.map +1 -0
- package/dist/server/src/api/schemas/plugins.schema.d.ts +62 -59
- package/dist/server/src/api/schemas/plugins.schema.js +54 -81
- package/dist/server/src/api/schemas/plugins.schema.js.map +1 -1
- package/dist/server/src/api/schemas/remote.schema.d.ts +44 -0
- package/dist/server/src/api/schemas/remote.schema.js +80 -0
- package/dist/server/src/api/schemas/remote.schema.js.map +1 -0
- package/dist/server/src/api/schemas/server.schema.d.ts +9 -0
- package/dist/server/src/api/schemas/server.schema.js +12 -0
- package/dist/server/src/api/schemas/server.schema.js.map +1 -0
- package/dist/server/src/api/schemas/shares.schema.d.ts +21 -0
- package/dist/server/src/api/schemas/shares.schema.js +22 -0
- package/dist/server/src/api/schemas/shares.schema.js.map +1 -0
- package/dist/server/src/api/schemas/storage.schema.d.ts +5 -15
- package/dist/server/src/api/schemas/users.schema.d.ts +294 -786
- package/dist/server/src/api/schemas/users.schema.js +76 -39
- package/dist/server/src/api/schemas/users.schema.js.map +1 -1
- package/dist/server/src/api/schemas/workers.schema.d.ts +14 -0
- package/dist/server/src/api/schemas/workers.schema.js +12 -0
- package/dist/server/src/api/schemas/workers.schema.js.map +1 -0
- package/dist/server/src/api/services/auth.service.d.ts +27 -17
- package/dist/server/src/api/services/auth.service.js +106 -134
- package/dist/server/src/api/services/auth.service.js.map +1 -1
- package/dist/server/src/api/services/automations.service.d.ts +24 -0
- package/dist/server/src/api/services/automations.service.js +157 -0
- package/dist/server/src/api/services/automations.service.js.map +1 -0
- package/dist/server/src/api/services/backup.service.js +0 -5
- package/dist/server/src/api/services/backup.service.js.map +1 -1
- package/dist/server/src/api/services/cameras.service.d.ts +28 -15
- package/dist/server/src/api/services/cameras.service.js +532 -305
- package/dist/server/src/api/services/cameras.service.js.map +1 -1
- package/dist/server/src/api/services/downloads.service.d.ts +9 -0
- package/dist/server/src/api/services/downloads.service.js +20 -0
- package/dist/server/src/api/services/downloads.service.js.map +1 -0
- package/dist/server/src/api/services/instances.service.d.ts +52 -0
- package/dist/server/src/api/services/instances.service.js +344 -0
- package/dist/server/src/api/services/instances.service.js.map +1 -0
- package/dist/server/src/api/services/notifications.service.d.ts +21 -0
- package/dist/server/src/api/services/notifications.service.js +48 -0
- package/dist/server/src/api/services/notifications.service.js.map +1 -0
- package/dist/server/src/api/services/plugins.service.js +31 -35
- package/dist/server/src/api/services/plugins.service.js.map +1 -1
- package/dist/server/src/api/services/remote.service.d.ts +35 -0
- package/dist/server/src/api/services/remote.service.js +207 -0
- package/dist/server/src/api/services/remote.service.js.map +1 -0
- package/dist/server/src/api/services/server.service.d.ts +15 -0
- package/dist/server/src/api/services/server.service.js +75 -0
- package/dist/server/src/api/services/server.service.js.map +1 -0
- package/dist/server/src/api/services/shares.service.d.ts +46 -0
- package/dist/server/src/api/services/shares.service.js +233 -0
- package/dist/server/src/api/services/shares.service.js.map +1 -0
- package/dist/server/src/api/services/twoFactor.service.d.ts +22 -0
- package/dist/server/src/api/services/twoFactor.service.js +81 -0
- package/dist/server/src/api/services/twoFactor.service.js.map +1 -0
- package/dist/server/src/api/services/users.service.d.ts +9 -5
- package/dist/server/src/api/services/users.service.js +157 -121
- package/dist/server/src/api/services/users.service.js.map +1 -1
- package/dist/server/src/api/services/workers.service.d.ts +5 -0
- package/dist/server/src/api/services/workers.service.js +19 -0
- package/dist/server/src/api/services/workers.service.js.map +1 -0
- package/dist/server/src/api/types/index.d.ts +350 -133
- package/dist/server/src/api/types/index.js +5 -4
- package/dist/server/src/api/types/index.js.map +1 -1
- package/dist/server/src/api/utils/cert.js +1 -1
- package/dist/server/src/api/utils/cert.js.map +1 -1
- package/dist/server/src/api/utils/encryption.d.ts +5 -0
- package/dist/server/src/api/utils/encryption.js +25 -0
- package/dist/server/src/api/utils/encryption.js.map +1 -0
- package/dist/server/src/api/utils/plugin.d.ts +4 -0
- package/dist/server/src/api/utils/plugin.js +8 -0
- package/dist/server/src/api/utils/plugin.js.map +1 -0
- package/dist/server/src/api/utils/regex.d.ts +3 -0
- package/dist/server/src/api/utils/regex.js +4 -0
- package/dist/server/src/api/utils/regex.js.map +1 -0
- package/dist/server/src/api/utils/upload.d.ts +3 -0
- package/dist/server/src/api/utils/upload.js +23 -0
- package/dist/server/src/api/utils/upload.js.map +1 -0
- package/dist/server/src/api/websocket/index.js +18 -16
- package/dist/server/src/api/websocket/index.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/cameras.d.ts +21 -0
- package/dist/server/src/api/websocket/nsp/cameras.js +152 -0
- package/dist/server/src/api/websocket/nsp/cameras.js.map +1 -0
- package/dist/server/src/api/websocket/nsp/logs.d.ts +1 -1
- package/dist/server/src/api/websocket/nsp/logs.js +65 -52
- package/dist/server/src/api/websocket/nsp/logs.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/main.d.ts +4 -1
- package/dist/server/src/api/websocket/nsp/main.js +29 -1
- package/dist/server/src/api/websocket/nsp/main.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/metrics.js +4 -4
- package/dist/server/src/api/websocket/nsp/metrics.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/notifications.d.ts +3 -3
- package/dist/server/src/api/websocket/nsp/notifications.js +10 -11
- package/dist/server/src/api/websocket/nsp/notifications.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/server.d.ts +4 -4
- package/dist/server/src/api/websocket/nsp/server.js +48 -27
- package/dist/server/src/api/websocket/nsp/server.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/status.d.ts +3 -3
- package/dist/server/src/api/websocket/nsp/status.js +3 -3
- package/dist/server/src/api/websocket/nsp/status.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/workers.d.ts +17 -0
- package/dist/server/src/api/websocket/nsp/workers.js +46 -0
- package/dist/server/src/api/websocket/nsp/workers.js.map +1 -0
- package/dist/server/src/api/websocket/types.d.ts +2 -1
- package/dist/server/src/api.d.ts +11 -16
- package/dist/server/src/api.js +62 -48
- package/dist/server/src/api.js.map +1 -1
- package/dist/server/src/automations/actions/cameraControl.d.ts +2 -0
- package/dist/server/src/automations/actions/cameraControl.js +35 -0
- package/dist/server/src/automations/actions/cameraControl.js.map +1 -0
- package/dist/server/src/automations/actions/delay.d.ts +2 -0
- package/dist/server/src/automations/actions/delay.js +8 -0
- package/dist/server/src/automations/actions/delay.js.map +1 -0
- package/dist/server/src/automations/actions/http.d.ts +2 -0
- package/dist/server/src/automations/actions/http.js +44 -0
- package/dist/server/src/automations/actions/http.js.map +1 -0
- package/dist/server/src/automations/actions/index.d.ts +4 -0
- package/dist/server/src/automations/actions/index.js +20 -0
- package/dist/server/src/automations/actions/index.js.map +1 -0
- package/dist/server/src/automations/actions/notification.d.ts +2 -0
- package/dist/server/src/automations/actions/notification.js +76 -0
- package/dist/server/src/automations/actions/notification.js.map +1 -0
- package/dist/server/src/automations/actions/plugin.d.ts +3 -0
- package/dist/server/src/automations/actions/plugin.js +73 -0
- package/dist/server/src/automations/actions/plugin.js.map +1 -0
- package/dist/server/src/automations/actions/sensor.d.ts +2 -0
- package/dist/server/src/automations/actions/sensor.js +17 -0
- package/dist/server/src/automations/actions/sensor.js.map +1 -0
- package/dist/server/src/automations/actions/snapshot.d.ts +2 -0
- package/dist/server/src/automations/actions/snapshot.js +20 -0
- package/dist/server/src/automations/actions/snapshot.js.map +1 -0
- package/dist/server/src/automations/actions/types.d.ts +14 -0
- package/dist/server/src/automations/actions/types.js.map +1 -0
- package/dist/server/src/automations/actions/variable.d.ts +2 -0
- package/dist/server/src/automations/actions/variable.js +17 -0
- package/dist/server/src/automations/actions/variable.js.map +1 -0
- package/dist/server/src/automations/conditions/ifelse.d.ts +3 -0
- package/dist/server/src/automations/conditions/ifelse.js +39 -0
- package/dist/server/src/automations/conditions/ifelse.js.map +1 -0
- package/dist/server/src/automations/conditions/index.d.ts +4 -0
- package/dist/server/src/automations/conditions/index.js +20 -0
- package/dist/server/src/automations/conditions/index.js.map +1 -0
- package/dist/server/src/automations/conditions/sensorState.d.ts +3 -0
- package/dist/server/src/automations/conditions/sensorState.js +21 -0
- package/dist/server/src/automations/conditions/sensorState.js.map +1 -0
- package/dist/server/src/automations/conditions/switch.d.ts +3 -0
- package/dist/server/src/automations/conditions/switch.js +9 -0
- package/dist/server/src/automations/conditions/switch.js.map +1 -0
- package/dist/server/src/automations/conditions/time.d.ts +3 -0
- package/dist/server/src/automations/conditions/time.js +24 -0
- package/dist/server/src/automations/conditions/time.js.map +1 -0
- package/dist/server/src/automations/conditions/types.d.ts +7 -0
- package/dist/server/src/automations/conditions/types.js.map +1 -0
- package/dist/server/src/automations/context.d.ts +48 -0
- package/dist/server/src/automations/context.js +146 -0
- package/dist/server/src/automations/context.js.map +1 -0
- package/dist/server/src/automations/engine.d.ts +35 -0
- package/dist/server/src/automations/engine.js +321 -0
- package/dist/server/src/automations/engine.js.map +1 -0
- package/dist/server/src/automations/haversine.d.ts +1 -0
- package/dist/server/src/automations/haversine.js +9 -0
- package/dist/server/src/automations/haversine.js.map +1 -0
- package/dist/server/src/automations/parseValue.d.ts +1 -0
- package/dist/server/src/automations/parseValue.js +11 -0
- package/dist/server/src/automations/parseValue.js.map +1 -0
- package/dist/server/src/automations/pluginMethodRegistry.d.ts +37 -0
- package/dist/server/src/automations/pluginMethodRegistry.js +162 -0
- package/dist/server/src/automations/pluginMethodRegistry.js.map +1 -0
- package/dist/server/src/automations/runner.d.ts +23 -0
- package/dist/server/src/automations/runner.js +166 -0
- package/dist/server/src/automations/runner.js.map +1 -0
- package/dist/server/src/automations/triggers/detection.d.ts +3 -0
- package/dist/server/src/automations/triggers/detection.js +102 -0
- package/dist/server/src/automations/triggers/detection.js.map +1 -0
- package/dist/server/src/automations/triggers/geofence.d.ts +13 -0
- package/dist/server/src/automations/triggers/geofence.js +8 -0
- package/dist/server/src/automations/triggers/geofence.js.map +1 -0
- package/dist/server/src/automations/triggers/index.d.ts +9 -0
- package/dist/server/src/automations/triggers/index.js +7 -0
- package/dist/server/src/automations/triggers/index.js.map +1 -0
- package/dist/server/src/automations/triggers/schedule.d.ts +3 -0
- package/dist/server/src/automations/triggers/schedule.js +54 -0
- package/dist/server/src/automations/triggers/schedule.js.map +1 -0
- package/dist/server/src/automations/triggers/sensor.d.ts +3 -0
- package/dist/server/src/automations/triggers/sensor.js +44 -0
- package/dist/server/src/automations/triggers/sensor.js.map +1 -0
- package/dist/server/src/automations/triggers/system.d.ts +3 -0
- package/dist/server/src/automations/triggers/system.js +31 -0
- package/dist/server/src/automations/triggers/system.js.map +1 -0
- package/dist/server/src/automations/triggers/types.d.ts +12 -0
- package/dist/server/src/automations/triggers/types.js.map +1 -0
- package/dist/server/src/automations/triggers/webhook.d.ts +7 -0
- package/dist/server/src/automations/triggers/webhook.js +8 -0
- package/dist/server/src/automations/triggers/webhook.js.map +1 -0
- package/dist/server/src/automations/utilities/imageInput.d.ts +2 -0
- package/dist/server/src/automations/utilities/imageInput.js +139 -0
- package/dist/server/src/automations/utilities/imageInput.js.map +1 -0
- package/dist/server/src/automations/utilities/index.d.ts +2 -0
- package/dist/server/src/automations/utilities/index.js +7 -0
- package/dist/server/src/automations/utilities/index.js.map +1 -0
- package/dist/server/src/automations/utilities/output.d.ts +2 -0
- package/dist/server/src/automations/utilities/output.js +10 -0
- package/dist/server/src/automations/utilities/output.js.map +1 -0
- package/dist/server/src/camera/controller.d.ts +56 -45
- package/dist/server/src/camera/controller.js +468 -326
- package/dist/server/src/camera/controller.js.map +1 -1
- package/dist/server/src/camera/decoder/audio-source.d.ts +34 -0
- package/dist/server/src/camera/decoder/audio-source.js +170 -0
- package/dist/server/src/camera/decoder/audio-source.js.map +1 -0
- package/dist/server/src/camera/decoder/cascade-manager.d.ts +22 -0
- package/dist/server/src/camera/decoder/cascade-manager.js +82 -0
- package/dist/server/src/camera/decoder/cascade-manager.js.map +1 -0
- package/dist/server/src/camera/decoder/child.d.ts +28 -0
- package/dist/server/src/camera/decoder/child.js +187 -0
- package/dist/server/src/camera/decoder/child.js.map +1 -0
- package/dist/server/src/camera/decoder/detection-coordinator.d.ts +142 -0
- package/dist/server/src/camera/decoder/detection-coordinator.js +1844 -0
- package/dist/server/src/camera/decoder/detection-coordinator.js.map +1 -0
- package/dist/server/src/camera/decoder/detection-pipeline.d.ts +41 -0
- package/dist/server/src/camera/decoder/detection-pipeline.js +216 -0
- package/dist/server/src/camera/decoder/detection-pipeline.js.map +1 -0
- package/dist/server/src/camera/decoder/dwell-manager.d.ts +23 -0
- package/dist/server/src/camera/decoder/dwell-manager.js +82 -0
- package/dist/server/src/camera/decoder/dwell-manager.js.map +1 -0
- package/dist/server/src/camera/decoder/event-manager.d.ts +97 -0
- package/dist/server/src/camera/decoder/event-manager.js +674 -0
- package/dist/server/src/camera/decoder/event-manager.js.map +1 -0
- package/dist/server/src/camera/decoder/frame-scaler.d.ts +53 -0
- package/dist/server/src/camera/decoder/frame-scaler.js +136 -0
- package/dist/server/src/camera/decoder/frame-scaler.js.map +1 -0
- package/dist/server/src/camera/decoder/frame-source.d.ts +54 -0
- package/dist/server/src/camera/decoder/frame-source.js +341 -0
- package/dist/server/src/camera/decoder/frame-source.js.map +1 -0
- package/dist/server/src/camera/decoder/ptz-autotracker.d.ts +57 -0
- package/dist/server/src/camera/decoder/ptz-autotracker.js +369 -0
- package/dist/server/src/camera/decoder/ptz-autotracker.js.map +1 -0
- package/dist/server/src/camera/decoder/types.d.ts +7 -0
- package/dist/server/src/camera/decoder/types.js +6 -0
- package/dist/server/src/camera/decoder/types.js.map +1 -0
- package/dist/server/src/camera/decoder/worker.d.ts +48 -0
- package/dist/server/src/camera/decoder/worker.js +465 -0
- package/dist/server/src/camera/decoder/worker.js.map +1 -0
- package/dist/server/src/camera/index.d.ts +43 -59
- package/dist/server/src/camera/index.js +72 -438
- package/dist/server/src/camera/index.js.map +1 -1
- package/dist/server/src/camera/sensors/controller.d.ts +96 -0
- package/dist/server/src/camera/sensors/controller.js +517 -0
- package/dist/server/src/camera/sensors/controller.js.map +1 -0
- package/dist/server/src/camera/sensors/sensor.d.ts +34 -0
- package/dist/server/src/camera/sensors/sensor.js +176 -0
- package/dist/server/src/camera/sensors/sensor.js.map +1 -0
- package/dist/server/src/camera/sensors/types.d.ts +27 -0
- package/dist/server/src/camera/sensors/types.js +225 -0
- package/dist/server/src/camera/sensors/types.js.map +1 -0
- package/dist/server/src/camera/streaming/fmp4-session.d.ts +10 -12
- package/dist/server/src/camera/streaming/fmp4-session.js +162 -268
- package/dist/server/src/camera/streaming/fmp4-session.js.map +1 -1
- package/dist/server/src/camera/streaming/rtp-session.d.ts +19 -0
- package/dist/server/src/camera/streaming/rtp-session.js +363 -0
- package/dist/server/src/camera/streaming/rtp-session.js.map +1 -0
- package/dist/server/src/camera/utils/filter.d.ts +6 -0
- package/dist/server/src/camera/utils/filter.js +83 -0
- package/dist/server/src/camera/utils/filter.js.map +1 -0
- package/dist/server/src/camera/utils.d.ts +2 -7
- package/dist/server/src/camera/utils.js +53 -194
- package/dist/server/src/camera/utils.js.map +1 -1
- package/dist/server/src/go2rtc/api/index.d.ts +16 -0
- package/dist/server/src/go2rtc/api/index.js +33 -0
- package/dist/server/src/go2rtc/api/index.js.map +1 -0
- package/dist/server/src/go2rtc/api/instance.d.ts +7 -0
- package/dist/server/src/go2rtc/api/instance.js +49 -0
- package/dist/server/src/go2rtc/api/instance.js.map +1 -0
- package/dist/server/src/go2rtc/api/manager.d.ts +11 -0
- package/dist/server/src/go2rtc/api/manager.js +38 -0
- package/dist/server/src/go2rtc/api/manager.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/application.d.ts +9 -0
- package/dist/server/src/go2rtc/api/routes/application.js +40 -0
- package/dist/server/src/go2rtc/api/routes/application.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/config.d.ts +8 -0
- package/dist/server/src/go2rtc/api/routes/config.js +42 -0
- package/dist/server/src/go2rtc/api/routes/config.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/discover.d.ts +30 -0
- package/dist/server/src/go2rtc/api/routes/discover.js +158 -0
- package/dist/server/src/go2rtc/api/routes/discover.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/snapshot.d.ts +8 -0
- package/dist/server/src/go2rtc/api/routes/snapshot.js +34 -0
- package/dist/server/src/go2rtc/api/routes/snapshot.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/streams.d.ts +18 -0
- package/dist/server/src/go2rtc/api/routes/streams.js +161 -0
- package/dist/server/src/go2rtc/api/routes/streams.js.map +1 -0
- package/dist/server/src/go2rtc/index.d.ts +7 -2
- package/dist/server/src/go2rtc/index.js +52 -30
- package/dist/server/src/go2rtc/index.js.map +1 -1
- package/dist/server/src/go2rtc/types.d.ts +167 -1
- package/dist/server/src/go2rtc/types.js +3 -0
- package/dist/server/src/go2rtc/types.js.map +1 -1
- package/dist/server/src/internal-bus.d.ts +41 -0
- package/dist/server/src/internal-bus.js +19 -0
- package/dist/server/src/internal-bus.js.map +1 -0
- package/dist/server/src/main.d.ts +8 -2
- package/dist/server/src/main.js +110 -21
- package/dist/server/src/main.js.map +1 -1
- package/dist/server/src/manager/coreManager.d.ts +12 -9
- package/dist/server/src/manager/coreManager.js +45 -48
- package/dist/server/src/manager/coreManager.js.map +1 -1
- package/dist/server/src/manager/deviceManager.d.ts +10 -8
- package/dist/server/src/manager/deviceManager.js +31 -96
- package/dist/server/src/manager/deviceManager.js.map +1 -1
- package/dist/server/src/manager/discoveryManager.d.ts +73 -0
- package/dist/server/src/manager/discoveryManager.js +800 -0
- package/dist/server/src/manager/discoveryManager.js.map +1 -0
- package/dist/server/src/manager/downloadManager.d.ts +27 -0
- package/dist/server/src/manager/downloadManager.js +353 -0
- package/dist/server/src/manager/downloadManager.js.map +1 -0
- package/dist/server/src/manager/notificationManager.d.ts +37 -0
- package/dist/server/src/manager/notificationManager.js +334 -0
- package/dist/server/src/manager/notificationManager.js.map +1 -0
- package/dist/server/src/manager/terminalManager.d.ts +27 -0
- package/dist/server/src/manager/terminalManager.js +239 -0
- package/dist/server/src/manager/terminalManager.js.map +1 -0
- package/dist/server/src/manager/types.d.ts +39 -14
- package/dist/server/src/manager/types.js +12 -1
- package/dist/server/src/manager/types.js.map +1 -1
- package/dist/server/src/plugins/index.d.ts +9 -6
- package/dist/server/src/plugins/index.js +69 -52
- package/dist/server/src/plugins/index.js.map +1 -1
- package/dist/server/src/plugins/plugin.d.ts +16 -16
- package/dist/server/src/plugins/plugin.js +42 -36
- package/dist/server/src/plugins/plugin.js.map +1 -1
- package/dist/server/src/plugins/runtime/base.d.ts +5 -14
- package/dist/server/src/plugins/runtime/base.js +39 -111
- package/dist/server/src/plugins/runtime/base.js.map +1 -1
- package/dist/server/src/plugins/runtime/go/index.d.ts +7 -0
- package/dist/server/src/plugins/runtime/go/index.js +110 -0
- package/dist/server/src/plugins/runtime/go/index.js.map +1 -0
- package/dist/server/src/plugins/runtime/index.js +5 -1
- package/dist/server/src/plugins/runtime/index.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/child.d.ts +7 -6
- package/dist/server/src/plugins/runtime/node/child.js +70 -38
- package/dist/server/src/plugins/runtime/node/child.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/index.d.ts +1 -0
- package/dist/server/src/plugins/runtime/node/index.js +31 -5
- package/dist/server/src/plugins/runtime/node/index.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/pluginApi.d.ts +9 -6
- package/dist/server/src/plugins/runtime/node/pluginApi.js +10 -4
- package/dist/server/src/plugins/runtime/node/pluginApi.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.d.ts +27 -15
- package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.js +312 -173
- package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/coreManager.d.ts +7 -10
- package/dist/server/src/plugins/runtime/node/proxy/coreManager.js +28 -43
- package/dist/server/src/plugins/runtime/node/proxy/coreManager.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/deviceManager.d.ts +7 -11
- package/dist/server/src/plugins/runtime/node/proxy/deviceManager.js +40 -57
- package/dist/server/src/plugins/runtime/node/proxy/deviceManager.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/downloadManager.d.ts +9 -0
- package/dist/server/src/plugins/runtime/node/proxy/downloadManager.js +22 -0
- package/dist/server/src/plugins/runtime/node/proxy/downloadManager.js.map +1 -0
- package/dist/server/src/plugins/runtime/node/proxy/notificationManager.d.ts +7 -0
- package/dist/server/src/plugins/runtime/node/proxy/notificationManager.js +20 -0
- package/dist/server/src/plugins/runtime/node/proxy/notificationManager.js.map +1 -0
- package/dist/server/src/plugins/runtime/node/proxy/sensor.d.ts +45 -0
- package/dist/server/src/plugins/runtime/node/proxy/sensor.js +149 -0
- package/dist/server/src/plugins/runtime/node/proxy/sensor.js.map +1 -0
- package/dist/server/src/plugins/runtime/node/storage.d.ts +6 -11
- package/dist/server/src/plugins/runtime/node/storage.js +69 -46
- package/dist/server/src/plugins/runtime/node/storage.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/storageController.d.ts +10 -7
- package/dist/server/src/plugins/runtime/node/storageController.js +57 -17
- package/dist/server/src/plugins/runtime/node/storageController.js.map +1 -1
- package/dist/server/src/plugins/runtime/python/camera/utils.py +105 -0
- package/dist/server/src/plugins/runtime/python/child.py +108 -68
- package/dist/server/src/plugins/runtime/python/index.js.map +1 -1
- package/dist/server/src/plugins/runtime/python/namespaces.py +155 -60
- package/dist/server/src/plugins/runtime/python/plugin_api.py +72 -6
- package/dist/server/src/plugins/runtime/python/proxy/camera_device.py +592 -1522
- package/dist/server/src/plugins/runtime/python/proxy/core_manager.py +75 -76
- package/dist/server/src/plugins/runtime/python/proxy/device_manager.py +81 -93
- package/dist/server/src/plugins/runtime/python/proxy/download_manager.py +33 -0
- package/dist/server/src/plugins/runtime/python/proxy/notification_manager.py +31 -0
- package/dist/server/src/plugins/runtime/python/proxy/sensor.py +169 -0
- package/dist/server/src/plugins/runtime/python/rpc/typings.py +56 -0
- package/dist/server/src/plugins/runtime/python/schema.py +54 -19
- package/dist/server/src/plugins/runtime/python/storage.py +84 -66
- package/dist/server/src/plugins/runtime/python/storage_controller.py +132 -38
- package/dist/server/src/plugins/runtime/python/typings.py +78 -152
- package/dist/server/src/plugins/schema.d.ts +27 -26
- package/dist/server/src/plugins/schema.js +183 -103
- package/dist/server/src/plugins/schema.js.map +1 -1
- package/dist/server/src/plugins/types.d.ts +2 -14
- package/dist/server/src/plugins/types.js +0 -1
- package/dist/server/src/plugins/types.js.map +1 -1
- package/dist/server/src/plugins/worker.d.ts +7 -7
- package/dist/server/src/plugins/worker.js +37 -26
- package/dist/server/src/plugins/worker.js.map +1 -1
- package/dist/server/src/remote/api/credentialStore.d.ts +18 -0
- package/dist/server/src/remote/api/credentialStore.js +101 -0
- package/dist/server/src/remote/api/credentialStore.js.map +1 -0
- package/dist/server/src/remote/api/index.d.ts +9 -0
- package/dist/server/src/remote/api/index.js +16 -0
- package/dist/server/src/remote/api/index.js.map +1 -0
- package/dist/server/src/remote/api/instance.d.ts +9 -0
- package/dist/server/src/remote/api/instance.js +44 -0
- package/dist/server/src/remote/api/instance.js.map +1 -0
- package/dist/server/src/remote/api/routes/oauth.d.ts +23 -0
- package/dist/server/src/remote/api/routes/oauth.js +79 -0
- package/dist/server/src/remote/api/routes/oauth.js.map +1 -0
- package/dist/server/src/remote/api/routes/server.d.ts +20 -0
- package/dist/server/src/remote/api/routes/server.js +58 -0
- package/dist/server/src/remote/api/routes/server.js.map +1 -0
- package/dist/server/src/remote/index.d.ts +25 -0
- package/dist/server/src/remote/index.js +70 -0
- package/dist/server/src/remote/index.js.map +1 -0
- package/dist/server/src/remote/push.d.ts +15 -0
- package/dist/server/src/remote/push.js +85 -0
- package/dist/server/src/remote/push.js.map +1 -0
- package/dist/server/src/remote/services/cloudflare-managed.d.ts +42 -0
- package/dist/server/src/remote/services/cloudflare-managed.js +284 -0
- package/dist/server/src/remote/services/cloudflare-managed.js.map +1 -0
- package/dist/server/src/remote/services/cloudflare.d.ts +38 -0
- package/dist/server/src/remote/services/cloudflare.js +232 -0
- package/dist/server/src/remote/services/cloudflare.js.map +1 -0
- package/dist/server/src/remote/services/customDomain.d.ts +9 -0
- package/dist/server/src/remote/services/customDomain.js +40 -0
- package/dist/server/src/remote/services/customDomain.js.map +1 -0
- package/dist/server/src/remote/services/index.d.ts +43 -0
- package/dist/server/src/remote/services/index.js +285 -0
- package/dist/server/src/remote/services/index.js.map +1 -0
- package/dist/server/src/remote/services/upnp.js +2 -0
- package/dist/server/src/remote/services/upnp.js.map +1 -0
- package/dist/server/src/remote/tunnel/client.d.ts +38 -0
- package/dist/server/src/remote/tunnel/client.js +241 -0
- package/dist/server/src/remote/tunnel/client.js.map +1 -0
- package/dist/server/src/remote/tunnel/index.d.ts +15 -0
- package/dist/server/src/remote/tunnel/index.js +68 -0
- package/dist/server/src/remote/tunnel/index.js.map +1 -0
- package/dist/server/src/remote/types.d.ts +31 -0
- package/dist/server/src/remote/types.js +2 -0
- package/dist/server/src/remote/types.js.map +1 -0
- package/dist/server/src/rpc/index.d.ts +24 -25
- package/dist/server/src/rpc/index.js +93 -77
- package/dist/server/src/rpc/index.js.map +1 -1
- package/dist/server/src/rpc/interfaces/config.d.ts +74 -0
- package/dist/server/src/rpc/interfaces/config.js +2 -0
- package/dist/server/src/rpc/interfaces/config.js.map +1 -0
- package/dist/server/src/rpc/interfaces/core.d.ts +25 -0
- package/dist/server/src/rpc/interfaces/core.js +2 -0
- package/dist/server/src/rpc/interfaces/core.js.map +1 -0
- package/dist/server/src/rpc/interfaces/detection.d.ts +70 -0
- package/dist/server/src/rpc/interfaces/detection.js +2 -0
- package/dist/server/src/rpc/interfaces/detection.js.map +1 -0
- package/dist/server/src/rpc/interfaces/device.d.ts +62 -0
- package/dist/server/src/rpc/interfaces/device.js +2 -0
- package/dist/server/src/rpc/interfaces/device.js.map +1 -0
- package/dist/server/src/rpc/interfaces/discovery.d.ts +46 -0
- package/dist/server/src/rpc/interfaces/discovery.js +2 -0
- package/dist/server/src/rpc/interfaces/discovery.js.map +1 -0
- package/dist/server/src/rpc/interfaces/download.d.ts +22 -0
- package/dist/server/src/rpc/interfaces/download.js +2 -0
- package/dist/server/src/rpc/interfaces/download.js.map +1 -0
- package/dist/server/src/rpc/interfaces/frameworker.d.ts +12 -0
- package/dist/server/src/rpc/interfaces/frameworker.js +2 -0
- package/dist/server/src/rpc/interfaces/frameworker.js.map +1 -0
- package/dist/server/src/rpc/interfaces/notification.d.ts +6 -0
- package/dist/server/src/rpc/interfaces/notification.js +2 -0
- package/dist/server/src/rpc/interfaces/notification.js.map +1 -0
- package/dist/server/src/rpc/interfaces/sensor.d.ts +75 -0
- package/dist/server/src/rpc/interfaces/sensor.js +2 -0
- package/dist/server/src/rpc/interfaces/sensor.js.map +1 -0
- package/dist/server/src/rpc/interfaces/terminal.d.ts +34 -0
- package/dist/server/src/rpc/interfaces/terminal.js +2 -0
- package/dist/server/src/rpc/interfaces/terminal.js.map +1 -0
- package/dist/server/src/rpc/namespaces.d.ts +50 -2
- package/dist/server/src/rpc/namespaces.js +70 -4
- package/dist/server/src/rpc/namespaces.js.map +1 -1
- package/dist/server/src/rpc/server.d.ts +22 -3
- package/dist/server/src/rpc/server.js +110 -37
- package/dist/server/src/rpc/server.js.map +1 -1
- package/dist/server/src/rpc/utils.d.ts +2 -1
- package/dist/server/src/rpc/utils.js +8 -0
- package/dist/server/src/rpc/utils.js.map +1 -1
- package/dist/server/src/services/config/constants.d.ts +7 -1
- package/dist/server/src/services/config/constants.js +17 -2
- package/dist/server/src/services/config/constants.js.map +1 -1
- package/dist/server/src/services/config/defaults.js +3 -3
- package/dist/server/src/services/config/defaults.js.map +1 -1
- package/dist/server/src/services/config/index.d.ts +6 -43
- package/dist/server/src/services/config/index.js +56 -108
- package/dist/server/src/services/config/index.js.map +1 -1
- package/dist/server/src/services/config/types.d.ts +14 -2
- package/dist/server/src/services/config/types.js.map +1 -1
- package/dist/server/src/services/logger/index.d.ts +13 -11
- package/dist/server/src/services/logger/index.js +47 -50
- package/dist/server/src/services/logger/index.js.map +1 -1
- package/dist/server/src/services/logger/logManager.d.ts +35 -0
- package/dist/server/src/services/logger/logManager.js +196 -0
- package/dist/server/src/services/logger/logManager.js.map +1 -0
- package/dist/server/src/services/logger/transports/fileTransport.d.ts +34 -0
- package/dist/server/src/services/logger/transports/fileTransport.js +152 -0
- package/dist/server/src/services/logger/transports/fileTransport.js.map +1 -0
- package/dist/server/src/services/logger/transports/index.d.ts +1 -0
- package/dist/server/src/services/logger/transports/index.js +2 -0
- package/dist/server/src/services/logger/transports/index.js.map +1 -0
- package/dist/server/src/types.d.ts +3 -0
- package/dist/server/src/utils/camera.d.ts +4 -0
- package/dist/server/src/utils/camera.js +79 -0
- package/dist/server/src/utils/camera.js.map +1 -0
- package/dist/server/src/utils/env.js +8 -0
- package/dist/server/src/utils/env.js.map +1 -0
- package/dist/server/src/utils/ipc.d.ts +1 -1
- package/dist/server/src/utils/ipc.js +2 -2
- package/dist/server/src/utils/ipc.js.map +1 -1
- package/dist/server/src/utils/path.js +3 -3
- package/dist/server/src/utils/path.js.map +1 -1
- package/dist/server/src/utils/pythonInstaller.d.ts +2 -1
- package/dist/server/src/utils/pythonInstaller.js +6 -6
- package/dist/server/src/utils/pythonInstaller.js.map +1 -1
- package/dist/server/src/workers/agent.d.ts +27 -0
- package/dist/server/src/workers/agent.js +161 -0
- package/dist/server/src/workers/agent.js.map +1 -0
- package/dist/server/src/workers/capabilities/frame-decoding.d.ts +24 -0
- package/dist/server/src/workers/capabilities/frame-decoding.js +180 -0
- package/dist/server/src/workers/capabilities/frame-decoding.js.map +1 -0
- package/dist/server/src/workers/capabilities/handler.d.ts +8 -0
- package/dist/server/src/workers/capabilities/handler.js +2 -0
- package/dist/server/src/workers/capabilities/handler.js.map +1 -0
- package/dist/server/src/workers/manager.d.ts +31 -0
- package/dist/server/src/workers/manager.js +260 -0
- package/dist/server/src/workers/manager.js.map +1 -0
- package/dist/server/src/workers/types.d.ts +59 -0
- package/dist/server/src/workers/types.js +5 -0
- package/dist/server/src/workers/types.js.map +1 -0
- package/package.json +73 -79
- package/dist/interface/assets/@xterm.DYP7pi_n.0.0.69.css +0 -32
- package/dist/interface/assets/Adminpanel.BKek2EMH.0.0.69.css +0 -1
- package/dist/interface/assets/Cameras.BDWZJqPN.0.0.69.css +0 -1
- package/dist/interface/assets/Camview.Cvhuou6V.0.0.69.css +0 -1
- package/dist/interface/assets/CuiConsole.DCYyxdVg.0.0.69.css +0 -1
- package/dist/interface/assets/CuiPluginCard.yF8V0SZY.0.0.69.css +0 -1
- package/dist/interface/assets/CuiTimeline.BkIwlYtw.0.0.69.css +0 -1
- package/dist/interface/assets/Plugin.DJElsAn5.0.0.69.css +0 -1
- package/dist/interface/assets/Plugins.BwPlcRrV.0.0.69.css +0 -1
- package/dist/interface/assets/Settings.CkgfRkQr.0.0.69.css +0 -1
- package/dist/interface/assets/SettingsAccount.CDZT7gN-.0.0.69.css +0 -1
- package/dist/interface/assets/highlight.Ch2EwETz.0.0.69.css +0 -1
- package/dist/interface/assets/main.BmO7mnW4.0.0.69.css +0 -1
- package/dist/interface/assets/worker-base.jEXLGV2h.0.0.69.js +0 -1332
- package/dist/interface/assets/worker-yaml.B3uUYINB.0.0.69.js +0 -5819
- package/dist/interface/js/@babel.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/@intlify.6ljJeWIl.0.0.69.js +0 -15
- package/dist/interface/js/@kurkle.D8fDXNIl.0.0.69.js +0 -6
- package/dist/interface/js/@primeuix.bRNqZjQz.0.0.69.js +0 -5889
- package/dist/interface/js/@primevue.C5r50LKM.0.0.69.js +0 -57
- package/dist/interface/js/@react-dnd.CcwRs9xb.0.0.69.js +0 -1
- package/dist/interface/js/@socket.io.Dkula2eQ.0.0.69.js +0 -1
- package/dist/interface/js/@tanstack.ESyaYTt8.0.0.69.js +0 -1
- package/dist/interface/js/@vee-validate.CeUgfPaH.0.0.69.js +0 -5
- package/dist/interface/js/@vue.BsSvBeCe.0.0.69.js +0 -17
- package/dist/interface/js/@vueuse.NhwSnX_y.0.0.69.js +0 -1
- package/dist/interface/js/@xterm.DHnCBlz-.0.0.69.js +0 -66
- package/dist/interface/js/Adminpanel.CR_zSM68.0.0.69.js +0 -1
- package/dist/interface/js/Camera.Cc2GMAQz.0.0.69.js +0 -1
- package/dist/interface/js/Cameras.AVNvfmPx.0.0.69.js +0 -482
- package/dist/interface/js/Cammesh.6TFnt2Jx.0.0.69.js +0 -1
- package/dist/interface/js/Camview.CTs17jUK.0.0.69.js +0 -1
- package/dist/interface/js/Config.BcnTMnwK.0.0.69.js +0 -2
- package/dist/interface/js/Console.C2u30_a4.0.0.69.js +0 -4
- package/dist/interface/js/CuiConsole.C_vx3eur.0.0.69.js +0 -1
- package/dist/interface/js/CuiPluginCard.DXCSR91d.0.0.69.js +0 -4
- package/dist/interface/js/CuiTimeline.D24_kazZ.0.0.69.js +0 -1
- package/dist/interface/js/FirstSteps.DmFQyph_.0.0.69.js +0 -1
- package/dist/interface/js/Plugin.DnLoseHB.0.0.69.js +0 -1
- package/dist/interface/js/Plugins.D6nWkZe3.0.0.69.js +0 -1
- package/dist/interface/js/Recordings.BGcye9TW.0.0.69.js +0 -1
- package/dist/interface/js/Settings.CLR_jqKd.0.0.69.js +0 -1
- package/dist/interface/js/SettingsAccount.D9QAC8hM.0.0.69.js +0 -1
- package/dist/interface/js/SettingsAppearance.Dg_3Nbvy.0.0.69.js +0 -1
- package/dist/interface/js/SettingsAppearance.vue_vue_type_script_setup_true_lang.DZQvbT2Y.0.0.69.js +0 -1
- package/dist/interface/js/SettingsBackup.C35jy9a9.0.0.69.js +0 -1
- package/dist/interface/js/SettingsRecordings.C5na6ke4.0.0.69.js +0 -1
- package/dist/interface/js/SettingsRemote.BrU66scR.0.0.69.js +0 -1
- package/dist/interface/js/SettingsSystem.DmU4H9b1.0.0.69.js +0 -1
- package/dist/interface/js/SettingsUsers.DQN0jbzy.0.0.69.js +0 -1
- package/dist/interface/js/VersionsHandler.vue_vue_type_script_setup_true_lang.Cyp9Qkwy.0.0.69.js +0 -4
- package/dist/interface/js/ace-builds.D-7Qis2t.0.0.69.js +0 -1091
- package/dist/interface/js/ace.config.ButjQxKc.0.0.69.js +0 -1
- package/dist/interface/js/axios.lj9VQs0f.0.0.69.js +0 -6
- package/dist/interface/js/backup.ZVXbFg1K.0.0.69.js +0 -1
- package/dist/interface/js/birpc.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/chart.js.Dz1J8kd4.0.0.69.js +0 -13
- package/dist/interface/js/close-circle.DJNW4HfJ.0.0.69.js +0 -1
- package/dist/interface/js/compare-versions.DqEOhma6.0.0.69.js +0 -1
- package/dist/interface/js/dijkstrajs.C00ieaqj.0.0.69.js +0 -1
- package/dist/interface/js/dnd-core.D_qG7vz7.0.0.69.js +0 -1
- package/dist/interface/js/draggabilly.BoYjrLDK.0.0.69.js +0 -6
- package/dist/interface/js/engine.io-client.B5m3FsEv.0.0.69.js +0 -1
- package/dist/interface/js/engine.io-parser.BiEtp6m2.0.0.69.js +0 -1
- package/dist/interface/js/entities.C20TfXL6.0.0.69.js +0 -1
- package/dist/interface/js/ev-emitter.X5f1qa-c.0.0.69.js +0 -1
- package/dist/interface/js/fast-deep-equal.IL3J8jAG.0.0.69.js +0 -1
- package/dist/interface/js/get-size.D1dS-IaP.0.0.69.js +0 -5
- package/dist/interface/js/highlight.js.BSQb76p3.0.0.69.js +0 -3
- package/dist/interface/js/hookable.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/linkify-it.DggZxsPz.0.0.69.js +0 -1
- package/dist/interface/js/main.BNZUJnjG.0.0.69.js +0 -31
- package/dist/interface/js/markdown-it.MLL3O76W.0.0.69.js +0 -15
- package/dist/interface/js/mdurl.k9Sl0PQj.0.0.69.js +0 -2
- package/dist/interface/js/nprogress.BYU1Y2h8.0.0.69.js +0 -2
- package/dist/interface/js/perfect-debounce.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/pinia.xXUM0Drf.0.0.69.js +0 -5
- package/dist/interface/js/primelocale.Bga3dOQu.0.0.69.js +0 -1
- package/dist/interface/js/primevue.CYqFPO0y.0.0.69.js +0 -142
- package/dist/interface/js/punycode.js.Dj65hjkv.0.0.69.js +0 -1
- package/dist/interface/js/qrcode.D3FbUuTi.0.0.69.js +0 -8
- package/dist/interface/js/react-dnd-html5-backend.1HQjlkwI.0.0.69.js +0 -2
- package/dist/interface/js/react-dnd-touch-backend.ChJx6T3S.0.0.69.js +0 -1
- package/dist/interface/js/redux.BFxtlG_c.0.0.69.js +0 -1
- package/dist/interface/js/refresh-rounded.DLelUEXh.0.0.69.js +0 -1
- package/dist/interface/js/rxjs.AXKlNjX-.0.0.69.js +0 -3
- package/dist/interface/js/socket.io-client.NZWSNJlD.0.0.69.js +0 -1
- package/dist/interface/js/socket.io-parser.3CqTF9_v.0.0.69.js +0 -1
- package/dist/interface/js/system.AeO3hneo.0.0.69.js +0 -1
- package/dist/interface/js/trash-fill.CxzXm2nA.0.0.69.js +0 -1
- package/dist/interface/js/tslib.9k7AwCpt.0.0.69.js +0 -1
- package/dist/interface/js/uc.micro.kMc2yuuw.0.0.69.js +0 -1
- package/dist/interface/js/unidragger.UylmBmyV.0.0.69.js +0 -5
- package/dist/interface/js/uuid.C6aID195.0.0.69.js +0 -1
- package/dist/interface/js/vee-validate.CXzK59HL.0.0.69.js +0 -5
- package/dist/interface/js/vue-chartjs.Dr8dSHCc.0.0.69.js +0 -1
- package/dist/interface/js/vue-i18n.BsJO9RBQ.0.0.69.js +0 -5
- package/dist/interface/js/vue-inline-svg.1baioXR8.0.0.69.js +0 -1
- package/dist/interface/js/vue-router.Cnp23wAe.0.0.69.js +0 -5
- package/dist/interface/js/vue-zoomable.DMxVl9qH.0.0.69.js +0 -1
- package/dist/interface/js/vue.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/vue3-dnd.Cre7FigV.0.0.69.js +0 -1
- package/dist/interface/js/zod.2bfLsWMZ.0.0.69.js +0 -1
- package/dist/interface/js/zoom-out.BEqLMm84.0.0.69.js +0 -1
- package/dist/interface/registerSW.js +0 -1
- package/dist/interface/workbox-5ffe50d4.js +0 -1
- package/dist/server/src/_camera_ui_tools/camera_ui_common/camera_utils/utils.py +0 -52
- package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/test.py +0 -116
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/__init__.py +0 -350
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/__init__.py +0 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/base.py +0 -237
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/client.py +0 -256
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/connection.py +0 -784
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/errors.py +0 -745
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/messaging.py +0 -57
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/rpc.py +0 -227
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/rpc_generator.py +0 -584
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/constants.py +0 -96
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/typings.py +0 -218
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/__init__.py +0 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/connection_state.py +0 -86
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/logger.py +0 -30
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/metrics.py +0 -152
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/packer.py +0 -20
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/routing.py +0 -75
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/rpc.py +0 -177
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/subscriptions.py +0 -24
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/tasks.py +0 -39
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/uid.py +0 -37
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/validate.py +0 -119
- package/dist/server/src/_camera_ui_tools/camera_ui_types/__init__.py +0 -1369
- package/dist/server/src/_camera_ui_tools/camera_ui_types/hybrid_observer.py +0 -338
- package/dist/server/src/_camera_ui_tools/camera_ui_types/test.py +0 -196
- package/dist/server/src/api/controllers/system.controller.d.ts +0 -24
- package/dist/server/src/api/controllers/system.controller.js +0 -235
- package/dist/server/src/api/controllers/system.controller.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/application.d.ts +0 -9
- package/dist/server/src/api/go2rtc/api/application.js +0 -39
- package/dist/server/src/api/go2rtc/api/application.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/config.d.ts +0 -8
- package/dist/server/src/api/go2rtc/api/config.js +0 -44
- package/dist/server/src/api/go2rtc/api/config.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/discover.d.ts +0 -30
- package/dist/server/src/api/go2rtc/api/discover.js +0 -162
- package/dist/server/src/api/go2rtc/api/discover.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/index.d.ts +0 -1
- package/dist/server/src/api/go2rtc/api/index.js +0 -42
- package/dist/server/src/api/go2rtc/api/index.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/snapshot.d.ts +0 -8
- package/dist/server/src/api/go2rtc/api/snapshot.js +0 -34
- package/dist/server/src/api/go2rtc/api/snapshot.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/streams.d.ts +0 -20
- package/dist/server/src/api/go2rtc/api/streams.js +0 -190
- package/dist/server/src/api/go2rtc/api/streams.js.map +0 -1
- package/dist/server/src/api/go2rtc/index.d.ts +0 -16
- package/dist/server/src/api/go2rtc/index.js +0 -33
- package/dist/server/src/api/go2rtc/index.js.map +0 -1
- package/dist/server/src/api/go2rtc/queue.d.ts +0 -10
- package/dist/server/src/api/go2rtc/queue.js +0 -38
- package/dist/server/src/api/go2rtc/queue.js.map +0 -1
- package/dist/server/src/api/go2rtc/types.d.ts +0 -151
- package/dist/server/src/api/go2rtc/types.js.map +0 -1
- package/dist/server/src/api/routes/system.routes.d.ts +0 -2
- package/dist/server/src/api/routes/system.routes.js +0 -86
- package/dist/server/src/api/routes/system.routes.js.map +0 -1
- package/dist/server/src/api/schemas/system.schema.d.ts +0 -185
- package/dist/server/src/api/schemas/system.schema.js +0 -40
- package/dist/server/src/api/schemas/system.schema.js.map +0 -1
- package/dist/server/src/api/services/system.service.d.ts +0 -13
- package/dist/server/src/api/services/system.service.js +0 -63
- package/dist/server/src/api/services/system.service.js.map +0 -1
- package/dist/server/src/camera/classes.d.ts +0 -2
- package/dist/server/src/camera/classes.js +0 -24
- package/dist/server/src/camera/classes.js.map +0 -1
- package/dist/server/src/camera/device.d.ts +0 -34
- package/dist/server/src/camera/device.js +0 -327
- package/dist/server/src/camera/device.js.map +0 -1
- package/dist/server/src/camera/frameWorker.d.ts +0 -46
- package/dist/server/src/camera/frameWorker.js +0 -347
- package/dist/server/src/camera/frameWorker.js.map +0 -1
- package/dist/server/src/camera/interfaces.d.ts +0 -17
- package/dist/server/src/camera/interfaces.js +0 -99
- package/dist/server/src/camera/interfaces.js.map +0 -1
- package/dist/server/src/camera/iou.d.ts +0 -2
- package/dist/server/src/camera/iou.js +0 -122
- package/dist/server/src/camera/iou.js.map +0 -1
- package/dist/server/src/camera/polygon.d.ts +0 -4
- package/dist/server/src/camera/polygon.js +0 -192
- package/dist/server/src/camera/polygon.js.map +0 -1
- package/dist/server/src/camera/python/__init__.py +0 -0
- package/dist/server/src/camera/python/classes.py +0 -41
- package/dist/server/src/camera/python/interfaces.py +0 -131
- package/dist/server/src/camera/python/iou.py +0 -158
- package/dist/server/src/camera/python/polygon.py +0 -230
- package/dist/server/src/camera/python/typings.py +0 -50
- package/dist/server/src/camera/python/video_frame.py +0 -143
- package/dist/server/src/camera/streaming/peer-connection.d.ts +0 -26
- package/dist/server/src/camera/streaming/peer-connection.js +0 -213
- package/dist/server/src/camera/streaming/peer-connection.js.map +0 -1
- package/dist/server/src/camera/streaming/rtsp-session.d.ts +0 -19
- package/dist/server/src/camera/streaming/rtsp-session.js +0 -196
- package/dist/server/src/camera/streaming/rtsp-session.js.map +0 -1
- package/dist/server/src/camera/streaming/webrtc-connection.d.ts +0 -44
- package/dist/server/src/camera/streaming/webrtc-connection.js +0 -177
- package/dist/server/src/camera/streaming/webrtc-connection.js.map +0 -1
- package/dist/server/src/camera/streaming/werift-session.d.ts +0 -19
- package/dist/server/src/camera/streaming/werift-session.js +0 -246
- package/dist/server/src/camera/streaming/werift-session.js.map +0 -1
- package/dist/server/src/camera/types.d.ts +0 -17
- package/dist/server/src/camera/types.js.map +0 -1
- package/dist/server/src/camera/videoFrame.d.ts +0 -18
- package/dist/server/src/camera/videoFrame.js +0 -88
- package/dist/server/src/camera/videoFrame.js.map +0 -1
- package/dist/server/src/cloud/index.d.ts +0 -12
- package/dist/server/src/cloud/index.js +0 -49
- package/dist/server/src/cloud/index.js.map +0 -1
- package/dist/server/src/cloud/remote/cloudflare.d.ts +0 -7
- package/dist/server/src/cloud/remote/cloudflare.js +0 -12
- package/dist/server/src/cloud/remote/cloudflare.js.map +0 -1
- package/dist/server/src/cloud/remote/upnp.d.ts +0 -7
- package/dist/server/src/cloud/remote/upnp.js +0 -12
- package/dist/server/src/cloud/remote/upnp.js.map +0 -1
- package/dist/server/src/cloud/remote/utils.d.ts +0 -3
- package/dist/server/src/cloud/remote/utils.js +0 -21
- package/dist/server/src/cloud/remote/utils.js.map +0 -1
- package/dist/server/src/cloud/types.d.ts +0 -15
- package/dist/server/src/cloud/types.js +0 -11
- package/dist/server/src/cloud/types.js.map +0 -1
- package/dist/server/src/decoder/child.js +0 -748
- package/dist/server/src/decoder/child.js.map +0 -1
- package/dist/server/src/decoder/imageUtils.d.ts +0 -21
- package/dist/server/src/decoder/imageUtils.js +0 -204
- package/dist/server/src/decoder/imageUtils.js.map +0 -1
- package/dist/server/src/decoder/manager.d.ts +0 -19
- package/dist/server/src/decoder/manager.js +0 -208
- package/dist/server/src/decoder/manager.js.map +0 -1
- package/dist/server/src/decoder/python/__init__.py +0 -0
- package/dist/server/src/decoder/python/child.py +0 -902
- package/dist/server/src/decoder/python/image_utils.py +0 -196
- package/dist/server/src/decoder/python/pool.py +0 -45
- package/dist/server/src/decoder/python/typings.py +0 -57
- package/dist/server/src/decoder/python/utils.py +0 -70
- package/dist/server/src/decoder/types.d.ts +0 -23
- package/dist/server/src/decoder/types.js.map +0 -1
- package/dist/server/src/decoder/utils.d.ts +0 -13
- package/dist/server/src/decoder/utils.js +0 -45
- package/dist/server/src/decoder/utils.js.map +0 -1
- package/dist/server/src/decoder/wasm/build/decoder.d.ts +0 -43
- package/dist/server/src/decoder/wasm/build/decoder.js +0 -108
- package/dist/server/src/decoder/wasm/build/decoder.wasm +0 -0
- package/dist/server/src/decoder/worker.js +0 -79
- package/dist/server/src/decoder/worker.js.map +0 -1
- package/dist/server/src/plugins/runtime/node/plugin.d.ts +0 -24
- package/dist/server/src/plugins/runtime/node/plugin.js +0 -128
- package/dist/server/src/plugins/runtime/node/plugin.js.map +0 -1
- package/dist/server/src/plugins/runtime/python/plugin.py +0 -155
- package/dist/server/src/rpc/types.d.ts +0 -112
- package/dist/server/src/rpc/types.js.map +0 -1
- /package/dist/interface/assets/{SettingsBackup.CX0rT0QJ.0.0.69.css → SettingsBackup-CX0rT0QJ.css} +0 -0
- /package/dist/interface/assets/{logo-512.DLKVOU2S.0.0.69.png → error-256-DLKVOU2S.png} +0 -0
- /package/dist/interface/assets/{logo-256.BCQk9H1-.0.0.69.png → logo-256-BCQk9H1-.png} +0 -0
- /package/dist/interface/assets/{logo.DmEiRk0z.0.0.69.png → logo-DmEiRk0z.png} +0 -0
- /package/dist/interface/assets/{mode-yaml.CIYL8U3d.0.0.69.js → mode-yaml-CIYL8U3d.js} +0 -0
- /package/dist/server/src/api/{go2rtc → database/migrations}/types.js +0 -0
- /package/dist/server/src/{camera → automations/actions}/types.js +0 -0
- /package/dist/server/src/{decoder → automations/conditions}/types.js +0 -0
- /package/dist/server/src/{rpc → automations/triggers}/types.js +0 -0
- /package/dist/server/src/{decoder/child.d.ts → remote/services/upnp.d.ts} +0 -0
- /package/dist/server/src/{decoder/worker.d.ts → utils/env.d.ts} +0 -0
|
@@ -0,0 +1,1844 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
11
|
+
if (value !== null && value !== void 0) {
|
|
12
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
13
|
+
var dispose, inner;
|
|
14
|
+
if (async) {
|
|
15
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
16
|
+
dispose = value[Symbol.asyncDispose];
|
|
17
|
+
}
|
|
18
|
+
if (dispose === void 0) {
|
|
19
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
20
|
+
dispose = value[Symbol.dispose];
|
|
21
|
+
if (async) inner = dispose;
|
|
22
|
+
}
|
|
23
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
24
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
25
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
26
|
+
}
|
|
27
|
+
else if (async) {
|
|
28
|
+
env.stack.push({ async: true });
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
};
|
|
32
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
33
|
+
return function (env) {
|
|
34
|
+
function fail(e) {
|
|
35
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
36
|
+
env.hasError = true;
|
|
37
|
+
}
|
|
38
|
+
var r, s = 0;
|
|
39
|
+
function next() {
|
|
40
|
+
while (r = env.stack.pop()) {
|
|
41
|
+
try {
|
|
42
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
43
|
+
if (r.dispose) {
|
|
44
|
+
var result = r.dispose.call(r.value);
|
|
45
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
46
|
+
}
|
|
47
|
+
else s |= 1;
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
fail(e);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
54
|
+
if (env.hasError) throw env.error;
|
|
55
|
+
}
|
|
56
|
+
return next();
|
|
57
|
+
};
|
|
58
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
59
|
+
var e = new Error(message);
|
|
60
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
61
|
+
});
|
|
62
|
+
import { isNoRespondersError, RPCClass, RPCMethod } from '@camera.ui/rpc';
|
|
63
|
+
import { SensorType } from '@camera.ui/sdk';
|
|
64
|
+
// import { writeFileSync } from 'node:fs';
|
|
65
|
+
import { NamespaceManager } from '../../rpc/namespaces.js';
|
|
66
|
+
import { DETECTION_SENSOR_TYPES, SENSOR_TYPE_CONFIG } from '../sensors/types.js';
|
|
67
|
+
import { normalizeZone } from '../utils/filter.js';
|
|
68
|
+
import { AudioSource } from './audio-source.js';
|
|
69
|
+
import { CascadeManager } from './cascade-manager.js';
|
|
70
|
+
import { DetectionPipeline } from './detection-pipeline.js';
|
|
71
|
+
import { DwellManager } from './dwell-manager.js';
|
|
72
|
+
import { DetectionEventManager } from './event-manager.js';
|
|
73
|
+
import { FrameScaler } from './frame-scaler.js';
|
|
74
|
+
import { FrameSource } from './frame-source.js';
|
|
75
|
+
import { PtzAutotracker } from './ptz-autotracker.js';
|
|
76
|
+
import { MOTION_WIDTH_MAP } from './types.js';
|
|
77
|
+
// Default cascade hold-open window in seconds
|
|
78
|
+
export const DEFAULT_CASCADE_TIMEOUT = 10;
|
|
79
|
+
// Tracks below this speed (normalized units/s) are considered stationary.
|
|
80
|
+
// Typical values: parked bike ~0.0006, standing person ~0.003–0.03.
|
|
81
|
+
export const STATIONARY_SPEED_THRESHOLD = 0.002;
|
|
82
|
+
// Object detection dwell window — bridges 1-2 missed frames inside an active
|
|
83
|
+
// cascade so a single uncertain frame doesn't fire `detected=false` and split
|
|
84
|
+
// the event. Mirrors the motion/audio dwell pattern.
|
|
85
|
+
const OBJECT_DWELL_SECONDS = 2;
|
|
86
|
+
let DetectionCoordinator = class DetectionCoordinator {
|
|
87
|
+
config;
|
|
88
|
+
proxy;
|
|
89
|
+
logger;
|
|
90
|
+
frameSource;
|
|
91
|
+
frameScaler;
|
|
92
|
+
singlePlugins = new Map();
|
|
93
|
+
multiPlugins = new Map();
|
|
94
|
+
loopRunning = false;
|
|
95
|
+
loopPromise;
|
|
96
|
+
videoStopPromise;
|
|
97
|
+
audioSource;
|
|
98
|
+
audioLoopRunning = false;
|
|
99
|
+
audioLoopPromise;
|
|
100
|
+
audioStopPromise;
|
|
101
|
+
audioReconnectCount = 0;
|
|
102
|
+
reconnectCount = 0;
|
|
103
|
+
maxReconnectCount = 10;
|
|
104
|
+
normalReconnectDelay = 10000;
|
|
105
|
+
maxReconnectDelay = 60000;
|
|
106
|
+
ptzAutotracker;
|
|
107
|
+
eventManager;
|
|
108
|
+
cascade = new CascadeManager();
|
|
109
|
+
dwell = new DwellManager();
|
|
110
|
+
pipeline;
|
|
111
|
+
adHocVideoLoop = false;
|
|
112
|
+
processingExternalSecondary = false;
|
|
113
|
+
cascadeUnsubscribe;
|
|
114
|
+
dwellUnsubscribe;
|
|
115
|
+
seenStationaryTracks = new Set();
|
|
116
|
+
activeSensorTriggerTypes = new Map();
|
|
117
|
+
currentDetectionState = {};
|
|
118
|
+
get cascadeEnabled() {
|
|
119
|
+
return this.config.detectionSettings.cascadeDetection !== false;
|
|
120
|
+
}
|
|
121
|
+
get cascadeTimeoutSeconds() {
|
|
122
|
+
return this.config.detectionSettings.cascadeTimeout ?? DEFAULT_CASCADE_TIMEOUT;
|
|
123
|
+
}
|
|
124
|
+
get audioMinDecibels() {
|
|
125
|
+
return this.config.detectionSettings.audio.minDecibels;
|
|
126
|
+
}
|
|
127
|
+
get motionResolution() {
|
|
128
|
+
return this.config.detectionSettings.motion.resolution;
|
|
129
|
+
}
|
|
130
|
+
get targetFps() {
|
|
131
|
+
return this.frameSource.fps;
|
|
132
|
+
}
|
|
133
|
+
get videoAspectRatio() {
|
|
134
|
+
const [w, h] = this.config.interfaceSettings.aspectRatio.split(':').map(Number);
|
|
135
|
+
return w / h;
|
|
136
|
+
}
|
|
137
|
+
nvrProxy;
|
|
138
|
+
nvrProxyPromise;
|
|
139
|
+
constructor(config, proxy, logger) {
|
|
140
|
+
this.config = config;
|
|
141
|
+
this.proxy = proxy;
|
|
142
|
+
this.logger = logger;
|
|
143
|
+
const frameSourceConfig = {
|
|
144
|
+
streamUrl: config.streamUrl,
|
|
145
|
+
snapshotUrl: config.snapshotUrl,
|
|
146
|
+
fps: this.config.frameWorkerSettings.fps,
|
|
147
|
+
};
|
|
148
|
+
this.frameSource = new FrameSource(frameSourceConfig, logger);
|
|
149
|
+
this.frameScaler = new FrameScaler(null, logger);
|
|
150
|
+
this.pipeline = new DetectionPipeline(config.zones, config.detectionSettings);
|
|
151
|
+
if (config.lines.length > 0) {
|
|
152
|
+
this.pipeline.updateLines(config.lines, this.videoAspectRatio);
|
|
153
|
+
}
|
|
154
|
+
this.eventManager = new DetectionEventManager(config.cameraId, this.proxy, this.logger);
|
|
155
|
+
this.eventManager.onEventEnd(() => this.handleEventEnded());
|
|
156
|
+
this.ptzAutotracker = new PtzAutotracker({
|
|
157
|
+
logger: this.logger,
|
|
158
|
+
proxy: this.proxy,
|
|
159
|
+
cameraId: this.config.cameraId,
|
|
160
|
+
settings: this.config.ptzAutotrack,
|
|
161
|
+
onSuppressionActivated: () => this.clearMotionStateForSuppression(),
|
|
162
|
+
});
|
|
163
|
+
this.cascadeUnsubscribe = this.cascade.onChange((event) => {
|
|
164
|
+
if (event.type === 'activated') {
|
|
165
|
+
this.pipeline.setReidHitCounterMax(this.cascadeTimeoutSeconds * this.targetFps);
|
|
166
|
+
this.startAdHocVideoLoopIfNeeded();
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
this.pipeline.setReidHitCounterMax(0);
|
|
170
|
+
this.stopAdHocVideoLoopIfIdle();
|
|
171
|
+
this.handleCascadeDeactivated();
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
this.dwellUnsubscribe = this.dwell.onChange((event) => {
|
|
175
|
+
const isSensorTrigger = event.sensorId.startsWith('trigger:');
|
|
176
|
+
if (event.state === 'activated') {
|
|
177
|
+
// Only write detected/blocked for detection sensors (motion/audio/object).
|
|
178
|
+
// Sensor triggers (contact/switch/light) manage their own properties.
|
|
179
|
+
if (!isSensorTrigger) {
|
|
180
|
+
this.writeSensorProperties(event.sensorId, {
|
|
181
|
+
detected: true,
|
|
182
|
+
blocked: true,
|
|
183
|
+
lastTriggered: event.timestamp,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
if (!isSensorTrigger) {
|
|
189
|
+
this.writeSensorProperties(event.sensorId, { detected: false, blocked: false });
|
|
190
|
+
}
|
|
191
|
+
this.activeSensorTriggerTypes.delete(event.sensorId);
|
|
192
|
+
if (!this.dwell.hasActive()) {
|
|
193
|
+
this.eventManager.forceEndActiveEvent();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
handleCascadeDeactivated() {
|
|
199
|
+
// Clear cascade-gated buffer slots but keep motion/audio intact
|
|
200
|
+
const cs = this.currentDetectionState;
|
|
201
|
+
cs.object = undefined;
|
|
202
|
+
cs.face = undefined;
|
|
203
|
+
cs.licensePlate = undefined;
|
|
204
|
+
cs.classifiers = undefined;
|
|
205
|
+
cs.clip = undefined;
|
|
206
|
+
cs.lineCrossings = undefined;
|
|
207
|
+
cs.cascadeTriggered = undefined;
|
|
208
|
+
// Publish empty detections for all cascade-gated sensors so UI clears bboxes
|
|
209
|
+
const clearTargets = [];
|
|
210
|
+
for (const [type, plugin] of this.singlePlugins) {
|
|
211
|
+
if (type === SensorType.Object || type === SensorType.Face || type === SensorType.LicensePlate) {
|
|
212
|
+
clearTargets.push({ sensorId: plugin.sensorId, type });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const classifierPlugins = this.multiPlugins.get(SensorType.Classifier);
|
|
216
|
+
if (classifierPlugins) {
|
|
217
|
+
for (const plugin of classifierPlugins.values()) {
|
|
218
|
+
clearTargets.push({ sensorId: plugin.sensorId, type: SensorType.Classifier });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
for (const { sensorId } of clearTargets) {
|
|
222
|
+
this.writeSensorProperties(sensorId, { detected: false, detections: [] });
|
|
223
|
+
}
|
|
224
|
+
// Tick EventManager — segment ends but event continues (motion still active)
|
|
225
|
+
this.eventManager.processResults(this.buildSnapshot());
|
|
226
|
+
}
|
|
227
|
+
handleEventEnded() {
|
|
228
|
+
this.pipeline.cleanup();
|
|
229
|
+
this.seenStationaryTracks.clear();
|
|
230
|
+
this.activeSensorTriggerTypes.clear();
|
|
231
|
+
this.currentDetectionState = {};
|
|
232
|
+
}
|
|
233
|
+
writeSensorProperties(sensorId, properties) {
|
|
234
|
+
const msg = {
|
|
235
|
+
sensorId,
|
|
236
|
+
properties,
|
|
237
|
+
timestamp: Date.now(),
|
|
238
|
+
};
|
|
239
|
+
this.proxy.publish(NamespaceManager.sensorControllerNamespaces(this.config.cameraId).sensorWriteSubject, msg);
|
|
240
|
+
}
|
|
241
|
+
buildSnapshot() {
|
|
242
|
+
const cs = this.currentDetectionState;
|
|
243
|
+
return {
|
|
244
|
+
hasCascadeTrigger: this.cascade.isActive,
|
|
245
|
+
motion: cs.motion ? { detected: cs.motion.detected ?? false } : undefined,
|
|
246
|
+
audio: cs.audio ? { detected: cs.audio.detected ?? false, detections: cs.audio.detections ?? [] } : undefined,
|
|
247
|
+
cascadeTriggered: cs.cascadeTriggered,
|
|
248
|
+
sensorTriggers: [...new Set(this.activeSensorTriggerTypes.values())],
|
|
249
|
+
objects: cs.object?.detected ? cs.object.detections : [],
|
|
250
|
+
faces: cs.face?.detections ?? [],
|
|
251
|
+
faceEmbeddingModel: cs.faceEmbeddingModel,
|
|
252
|
+
plates: cs.licensePlate?.detections ?? [],
|
|
253
|
+
classifiers: cs.classifiers ? Object.values(cs.classifiers).flatMap((c) => c.detections) : [],
|
|
254
|
+
clips: cs.clip?.embeddings ?? [],
|
|
255
|
+
clipEmbeddingModel: cs.clipEmbeddingModel,
|
|
256
|
+
thumbnails: undefined,
|
|
257
|
+
lineCrossings: cs.lineCrossings,
|
|
258
|
+
timestamp: Date.now(),
|
|
259
|
+
segmentTimeout: 10,
|
|
260
|
+
expectedEndTime: this.dwell.maxExpiry(),
|
|
261
|
+
detectionZones: this.getNormalizedDetectionZones(),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
getNormalizedDetectionZones() {
|
|
265
|
+
if (!this.config.zones || this.config.zones.length === 0)
|
|
266
|
+
return [];
|
|
267
|
+
const result = [];
|
|
268
|
+
for (const zone of this.config.zones) {
|
|
269
|
+
if (zone.isPrivacyMask)
|
|
270
|
+
continue;
|
|
271
|
+
if (!zone.name)
|
|
272
|
+
continue;
|
|
273
|
+
const normalized = normalizeZone(zone);
|
|
274
|
+
result.push({ name: zone.name, points: normalized.points });
|
|
275
|
+
}
|
|
276
|
+
return result;
|
|
277
|
+
}
|
|
278
|
+
applyExternalDetectionFilters(sensorType, properties) {
|
|
279
|
+
const detections = properties.detections;
|
|
280
|
+
if (!Array.isArray(detections) || detections.length === 0)
|
|
281
|
+
return properties;
|
|
282
|
+
let filtered;
|
|
283
|
+
switch (sensorType) {
|
|
284
|
+
case SensorType.Face:
|
|
285
|
+
filtered = this.pipeline.runZoneFilterWithLabel(detections, 'person');
|
|
286
|
+
break;
|
|
287
|
+
case SensorType.LicensePlate:
|
|
288
|
+
filtered = this.pipeline.runZoneFilterWithLabel(detections, 'vehicle');
|
|
289
|
+
break;
|
|
290
|
+
case SensorType.Object:
|
|
291
|
+
case SensorType.Classifier:
|
|
292
|
+
case SensorType.Motion:
|
|
293
|
+
filtered = this.pipeline.runZoneFilter(detections);
|
|
294
|
+
break;
|
|
295
|
+
default:
|
|
296
|
+
return properties; // Audio etc — no zone filter
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
...properties,
|
|
300
|
+
detections: filtered,
|
|
301
|
+
detected: filtered.length > 0,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
ingestDetectionResult(sensorType, sensorId, properties, pluginId) {
|
|
305
|
+
// Note: PTZ-suppression gating happens upstream — processDetection and
|
|
306
|
+
// reportSensorWrite decide whether to route to autotracker-only vs. full
|
|
307
|
+
// ingest. By the time we land here, the caller has already decided this
|
|
308
|
+
// write belongs in the full pipeline.
|
|
309
|
+
// Update aggregated buffer based on sensor type. Each type maps to a different
|
|
310
|
+
// ProcessedDetectionData field — partial-merge with what's already buffered.
|
|
311
|
+
this.updateBufferForType(sensorType, properties, pluginId);
|
|
312
|
+
const detected = properties.detected === true;
|
|
313
|
+
// Motion/Audio: refresh dwell on positive detection. Dwell drives the
|
|
314
|
+
// `detected` / `blocked` / `lastTriggered` lifecycle entirely — see the
|
|
315
|
+
// dwell.onChange listener wired in the constructor. Motion additionally
|
|
316
|
+
// triggers cascade.
|
|
317
|
+
if (sensorType === SensorType.Motion && detected) {
|
|
318
|
+
const motionTimeout = this.config.detectionSettings.motion.timeout;
|
|
319
|
+
this.dwell.refresh(sensorId, motionTimeout);
|
|
320
|
+
if (this.cascadeEnabled) {
|
|
321
|
+
this.cascade.triggerMomentary(this.cascadeTimeoutSeconds);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
else if (sensorType === SensorType.Audio && detected) {
|
|
325
|
+
const audioTimeout = this.config.detectionSettings.audio.timeout;
|
|
326
|
+
this.dwell.refresh(sensorId, audioTimeout);
|
|
327
|
+
if (this.cascadeEnabled) {
|
|
328
|
+
this.cascade.triggerMomentary(this.cascadeTimeoutSeconds);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
else if (sensorType === SensorType.Object && detected) {
|
|
332
|
+
// Object dwell — anti-chatter for object detection. Single missed frame
|
|
333
|
+
// (model uncertain for ~100ms) must not split the event into two.
|
|
334
|
+
//
|
|
335
|
+
// Stationary object gating: a track that is stationary AND was already
|
|
336
|
+
// seen in a previous frame during this event must NOT refresh the dwell.
|
|
337
|
+
// This prevents parked cars/bikes from keeping events alive forever.
|
|
338
|
+
// Moving tracks always refresh. Stationary tracks refresh only once
|
|
339
|
+
// (first time seen) — after that they're in seenStationaryTracks and
|
|
340
|
+
// get skipped. The set is cleared on cascade deactivate (event boundary).
|
|
341
|
+
const detections = properties.detections ?? [];
|
|
342
|
+
let hasActiveTrack = false;
|
|
343
|
+
for (const t of detections) {
|
|
344
|
+
if (t.trackLost)
|
|
345
|
+
continue;
|
|
346
|
+
const isStationary = (t.trackSpeed ?? 0) < STATIONARY_SPEED_THRESHOLD;
|
|
347
|
+
if (isStationary) {
|
|
348
|
+
if (t.trackId !== undefined && !this.seenStationaryTracks.has(t.trackId)) {
|
|
349
|
+
// First time seeing this stationary track — count it as active
|
|
350
|
+
this.seenStationaryTracks.add(t.trackId);
|
|
351
|
+
hasActiveTrack = true;
|
|
352
|
+
}
|
|
353
|
+
// Already seen stationary track — does not count
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
// Moving track — always counts
|
|
357
|
+
hasActiveTrack = true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (hasActiveTrack) {
|
|
361
|
+
this.dwell.refresh(sensorId, OBJECT_DWELL_SECONDS);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
// Only known stationary tracks — suppress detected and clear detections
|
|
365
|
+
// from the buffer so the EventManager doesn't open a new segment for
|
|
366
|
+
// objects we've already seen. The UI still gets the bboxes via the
|
|
367
|
+
// property publish (publishProps path below).
|
|
368
|
+
properties.detected = false;
|
|
369
|
+
if (this.currentDetectionState.object) {
|
|
370
|
+
this.currentDetectionState.object.detected = false;
|
|
371
|
+
this.currentDetectionState.object.detections = [];
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// Publish path. For motion/audio sensors, dwell is the SOLE owner of
|
|
376
|
+
// `detected` / `blocked` / `lastTriggered` regardless of the current
|
|
377
|
+
// frame's detected value — anti-chatter means a "no detection" frame
|
|
378
|
+
// must NOT overwrite the dwell-set `detected=true`. Always strip these
|
|
379
|
+
// dwell-managed properties from the publish, and let `dwell.onChange`
|
|
380
|
+
// (activated/expired) be the only path that writes them.
|
|
381
|
+
let publishProps = properties;
|
|
382
|
+
if (sensorType === SensorType.Motion || sensorType === SensorType.Audio || sensorType === SensorType.Object) {
|
|
383
|
+
const { detected: _d, blocked: _b, lastTriggered: _t, ...rest } = properties;
|
|
384
|
+
publishProps = rest;
|
|
385
|
+
}
|
|
386
|
+
if (Object.keys(publishProps).length > 0) {
|
|
387
|
+
this.writeSensorProperties(sensorId, publishProps);
|
|
388
|
+
}
|
|
389
|
+
// EventManager is NOT ticked here — detection-coordinator flushes once
|
|
390
|
+
// per frame at the end of processDetection() after all detectors + thumbnails.
|
|
391
|
+
}
|
|
392
|
+
updateBufferForType(sensorType, properties, pluginId) {
|
|
393
|
+
const cs = this.currentDetectionState;
|
|
394
|
+
const detections = properties.detections ?? [];
|
|
395
|
+
const detected = properties.detected === true;
|
|
396
|
+
switch (sensorType) {
|
|
397
|
+
case SensorType.Motion:
|
|
398
|
+
cs.motion = { detected, detections };
|
|
399
|
+
break;
|
|
400
|
+
case SensorType.Audio:
|
|
401
|
+
cs.audio = {
|
|
402
|
+
detected,
|
|
403
|
+
detections,
|
|
404
|
+
decibels: properties.decibels ?? cs.audio?.decibels,
|
|
405
|
+
};
|
|
406
|
+
break;
|
|
407
|
+
case SensorType.Object:
|
|
408
|
+
cs.object = { detected, detections };
|
|
409
|
+
break;
|
|
410
|
+
case SensorType.Face:
|
|
411
|
+
cs.face = { detected, detections: detections };
|
|
412
|
+
break;
|
|
413
|
+
case SensorType.LicensePlate:
|
|
414
|
+
cs.licensePlate = { detected, detections: detections };
|
|
415
|
+
break;
|
|
416
|
+
case SensorType.Classifier:
|
|
417
|
+
if (pluginId) {
|
|
418
|
+
cs.classifiers ??= {};
|
|
419
|
+
cs.classifiers[pluginId] = { detected, detections: detections };
|
|
420
|
+
}
|
|
421
|
+
break;
|
|
422
|
+
case SensorType.Clip:
|
|
423
|
+
cs.clip = { embeddings: properties.embeddings ?? [], embeddingModel: cs.clipEmbeddingModel ?? '' };
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
updateZones(zones) {
|
|
428
|
+
this.config.zones = zones;
|
|
429
|
+
this.pipeline.updateZones(zones);
|
|
430
|
+
}
|
|
431
|
+
updateLines(lines) {
|
|
432
|
+
this.config.lines = lines;
|
|
433
|
+
this.pipeline.updateLines(lines, this.videoAspectRatio);
|
|
434
|
+
}
|
|
435
|
+
updateDetectionSettings(settings) {
|
|
436
|
+
this.config.detectionSettings = settings;
|
|
437
|
+
this.pipeline.updateSettings(settings);
|
|
438
|
+
}
|
|
439
|
+
updatePtzAutotrackSettings(settings) {
|
|
440
|
+
this.config.ptzAutotrack = settings;
|
|
441
|
+
this.ptzAutotracker.updateSettings(settings);
|
|
442
|
+
}
|
|
443
|
+
updateFrameWorkerSettings(settings) {
|
|
444
|
+
this.config.frameWorkerSettings = settings;
|
|
445
|
+
}
|
|
446
|
+
updateInterfaceSettings(settings) {
|
|
447
|
+
this.config.interfaceSettings = settings;
|
|
448
|
+
if (this.config.lines.length > 0) {
|
|
449
|
+
this.pipeline.updateLines(this.config.lines, this.videoAspectRatio);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
async dispose() {
|
|
453
|
+
await this.stopVideoLoop();
|
|
454
|
+
await this.stopAudioLoop();
|
|
455
|
+
this.ptzAutotracker.dispose();
|
|
456
|
+
this.cascadeUnsubscribe?.();
|
|
457
|
+
this.dwellUnsubscribe?.();
|
|
458
|
+
this.cascade.dispose();
|
|
459
|
+
this.dwell.dispose();
|
|
460
|
+
this.eventManager.destroy();
|
|
461
|
+
this.adHocVideoLoop = false;
|
|
462
|
+
this.frameScaler.dispose();
|
|
463
|
+
this.pipeline.cleanup();
|
|
464
|
+
this.currentDetectionState = {};
|
|
465
|
+
}
|
|
466
|
+
async onSensorAdded(sensor) {
|
|
467
|
+
if (DETECTION_SENSOR_TYPES.has(sensor.sensorType) && sensor.requiresFrames) {
|
|
468
|
+
await this.registerDetectionPluginInternal(sensor);
|
|
469
|
+
}
|
|
470
|
+
if (sensor.sensorType === SensorType.PTZ) {
|
|
471
|
+
await this.ptzAutotracker.bind({
|
|
472
|
+
pluginId: sensor.pluginId,
|
|
473
|
+
sensorId: sensor.sensorId,
|
|
474
|
+
capabilities: sensor.capabilities,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
async onSensorRemoved(sensorId) {
|
|
479
|
+
await this.removeDetectionPluginBySensor(sensorId);
|
|
480
|
+
this.ptzAutotracker.unbind(sensorId);
|
|
481
|
+
const dwellKey = `trigger:${sensorId}`;
|
|
482
|
+
this.activeSensorTriggerTypes.delete(dwellKey);
|
|
483
|
+
this.dwell.clear(dwellKey);
|
|
484
|
+
this.dwell.clear(sensorId);
|
|
485
|
+
}
|
|
486
|
+
onSensorCapabilitiesChanged(sensorId, capabilities) {
|
|
487
|
+
this.ptzAutotracker.setCapabilities(sensorId, capabilities);
|
|
488
|
+
}
|
|
489
|
+
async registerDetectionPluginInternal(sensor) {
|
|
490
|
+
// Wait for any in-progress stop to complete before starting a new loop
|
|
491
|
+
if (this.videoStopPromise)
|
|
492
|
+
await this.videoStopPromise;
|
|
493
|
+
if (this.audioStopPromise)
|
|
494
|
+
await this.audioStopPromise;
|
|
495
|
+
const wasVideoNeeded = this.shouldVideoBeActive();
|
|
496
|
+
const wasAudioNeeded = this.shouldAudioBeActive();
|
|
497
|
+
const namespaces = NamespaceManager.sensorProviderNamespaces(sensor.pluginId, this.config.cameraId, sensor.sensorId);
|
|
498
|
+
const sensorProxy = this.proxy.createProxy(namespaces.sensorRpc);
|
|
499
|
+
const pluginInfo = {
|
|
500
|
+
pluginId: sensor.pluginId,
|
|
501
|
+
sensorId: sensor.sensorId,
|
|
502
|
+
sensorType: sensor.sensorType,
|
|
503
|
+
requiresFrames: sensor.requiresFrames,
|
|
504
|
+
modelSpec: sensor.modelSpec,
|
|
505
|
+
proxy: sensorProxy,
|
|
506
|
+
};
|
|
507
|
+
if (this.isMultiProvider(sensor.sensorType)) {
|
|
508
|
+
if (!this.multiPlugins.has(sensor.sensorType)) {
|
|
509
|
+
this.multiPlugins.set(sensor.sensorType, new Map());
|
|
510
|
+
}
|
|
511
|
+
const typePlugins = this.multiPlugins.get(sensor.sensorType);
|
|
512
|
+
if (typePlugins.has(sensor.pluginId))
|
|
513
|
+
return;
|
|
514
|
+
typePlugins.set(sensor.pluginId, pluginInfo);
|
|
515
|
+
this.logger.trace(`Multi-provider plugin registered: ${sensor.pluginId} for ${sensor.sensorType}`);
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
if (this.singlePlugins.has(sensor.sensorType))
|
|
519
|
+
return;
|
|
520
|
+
this.singlePlugins.set(sensor.sensorType, pluginInfo);
|
|
521
|
+
this.logger.trace(`Plugin registered: ${sensor.pluginId} for ${sensor.sensorType}`);
|
|
522
|
+
}
|
|
523
|
+
if (!wasVideoNeeded && this.shouldVideoBeActive()) {
|
|
524
|
+
this.adHocVideoLoop = false;
|
|
525
|
+
this.startVideoLoop();
|
|
526
|
+
}
|
|
527
|
+
if (!wasAudioNeeded && this.shouldAudioBeActive()) {
|
|
528
|
+
this.startAudioLoop();
|
|
529
|
+
}
|
|
530
|
+
if (this.cascade.isActive) {
|
|
531
|
+
this.startAdHocVideoLoopIfNeeded();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
async removeDetectionPluginBySensor(sensorId) {
|
|
535
|
+
const wasVideoNeeded = this.shouldVideoBeActive();
|
|
536
|
+
const wasAudioNeeded = this.shouldAudioBeActive();
|
|
537
|
+
let removed = false;
|
|
538
|
+
for (const [sensorType, plugin] of this.singlePlugins) {
|
|
539
|
+
if (plugin.sensorId === sensorId) {
|
|
540
|
+
this.singlePlugins.delete(sensorType);
|
|
541
|
+
removed = true;
|
|
542
|
+
this.logger.trace(`Plugin unregistered: ${plugin.pluginId} (${sensorType})`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
for (const [sensorType, typePlugins] of this.multiPlugins) {
|
|
546
|
+
for (const [pluginId, plugin] of typePlugins) {
|
|
547
|
+
if (plugin.sensorId === sensorId) {
|
|
548
|
+
typePlugins.delete(pluginId);
|
|
549
|
+
removed = true;
|
|
550
|
+
this.logger.trace(`Multi-provider plugin unregistered: ${pluginId} (${sensorType})`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (typePlugins.size === 0)
|
|
554
|
+
this.multiPlugins.delete(sensorType);
|
|
555
|
+
}
|
|
556
|
+
if (!removed)
|
|
557
|
+
return;
|
|
558
|
+
if (!this.singlePlugins.has(SensorType.Object)) {
|
|
559
|
+
this.adHocVideoLoop = false;
|
|
560
|
+
}
|
|
561
|
+
// Hot-reload: if the ad-hoc loop is no longer needed after removing the
|
|
562
|
+
// plugin, stop it. Uses needsAdHocLoop() (not shouldVideoBeActive) so we
|
|
563
|
+
// don't accidentally stop a loop still needed for F object (requiresFrames=true).
|
|
564
|
+
if (this.adHocVideoLoop && !this.needsAdHocLoop()) {
|
|
565
|
+
this.adHocVideoLoop = false;
|
|
566
|
+
this.logger.debug('Stopping ad-hoc video loop — last frame-based consumer removed');
|
|
567
|
+
this.stopVideoLoop();
|
|
568
|
+
}
|
|
569
|
+
// Await to prevent race: a rapid re-register could start a second loop
|
|
570
|
+
// while the old one is still shutting down.
|
|
571
|
+
if (wasVideoNeeded && !this.shouldVideoBeActive() && !this.adHocVideoLoop) {
|
|
572
|
+
await this.stopVideoLoop();
|
|
573
|
+
}
|
|
574
|
+
if (wasAudioNeeded && !this.shouldAudioBeActive()) {
|
|
575
|
+
await this.stopAudioLoop();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
async reportSensorWrite(sensorId, sensorType, properties) {
|
|
579
|
+
if (sensorType === SensorType.Object) {
|
|
580
|
+
const filtered = this.applyExternalDetectionFilters(sensorType, properties);
|
|
581
|
+
// Always feed the autotracker — it needs fresh data every write, even
|
|
582
|
+
// (especially) during suppression, so it can decide when to stop.
|
|
583
|
+
// External-sensor object writes are presence-only (SDK synthesises a
|
|
584
|
+
// full-frame bbox when the plugin reports without coordinates), so use
|
|
585
|
+
// the presence channel — it holds the return-to-home timer without
|
|
586
|
+
// driving the motor.
|
|
587
|
+
const externalDetections = filtered.detections ?? [];
|
|
588
|
+
this.ptzAutotracker.handlePresenceDetections(externalDetections);
|
|
589
|
+
// During PTZ suppression: autotracker got the data, but tracker/pipeline/
|
|
590
|
+
// events/UI are gated (no stale bboxes, no false events from camera pose
|
|
591
|
+
// change). Skip the rest.
|
|
592
|
+
if (this.ptzAutotracker.suppressionActive)
|
|
593
|
+
return;
|
|
594
|
+
this.ingestDetectionResult(SensorType.Object, sensorId, filtered);
|
|
595
|
+
this.eventManager.processResults(this.buildSnapshot());
|
|
596
|
+
if (!this.hasFrameBasedSecondary())
|
|
597
|
+
return;
|
|
598
|
+
if (this.processingExternalSecondary)
|
|
599
|
+
return; // busy-skip: previous RPC still running
|
|
600
|
+
this.processingExternalSecondary = true;
|
|
601
|
+
try {
|
|
602
|
+
// Wrap the zone-filtered external boxes as TrackedDetection (no real
|
|
603
|
+
// tracking, just shape adapter — `trackLost: false`) so the secondary
|
|
604
|
+
// pipeline can treat them uniformly with frame-driven output.
|
|
605
|
+
const rawExternal = filtered.detections ?? [];
|
|
606
|
+
const objectDetections = this.pipeline.processExternal(rawExternal);
|
|
607
|
+
// Fast path: loop is running and has a frame → crop mode.
|
|
608
|
+
const peeked = this.frameSource.peekLatestFrame();
|
|
609
|
+
if (peeked) {
|
|
610
|
+
try {
|
|
611
|
+
const results = { timestamp: Date.now() };
|
|
612
|
+
await this.runSecondariesAndThumbnails(peeked.frame, objectDetections, results);
|
|
613
|
+
this.ingestResultsForAllSecondaries(results);
|
|
614
|
+
const snapshot = this.buildSnapshot();
|
|
615
|
+
if (results.thumbnails && results.thumbnails.length > 0) {
|
|
616
|
+
snapshot.thumbnails = results.thumbnails;
|
|
617
|
+
}
|
|
618
|
+
this.eventManager.processResults(snapshot);
|
|
619
|
+
}
|
|
620
|
+
finally {
|
|
621
|
+
await peeked[Symbol.asyncDispose]();
|
|
622
|
+
}
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
// Slow path: loop hasn't produced a frame yet → snapshot fetch fallback.
|
|
626
|
+
// Full-frame mode (no per-detection crops) — secondaries run global
|
|
627
|
+
// detection on the whole scaled frame.
|
|
628
|
+
const fetched = await this.frameSource.fetchSnapshotFrame();
|
|
629
|
+
if (!fetched)
|
|
630
|
+
return;
|
|
631
|
+
try {
|
|
632
|
+
const results = { timestamp: Date.now() };
|
|
633
|
+
const sceneJpeg = await this.runSecondariesFullFrame(fetched.frame, results);
|
|
634
|
+
this.ingestResultsForAllSecondaries(results);
|
|
635
|
+
const snapshot = this.buildSnapshot();
|
|
636
|
+
if (sceneJpeg)
|
|
637
|
+
snapshot.eventThumbnail = sceneJpeg;
|
|
638
|
+
this.eventManager.processResults(snapshot);
|
|
639
|
+
}
|
|
640
|
+
finally {
|
|
641
|
+
await fetched[Symbol.asyncDispose]();
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
finally {
|
|
645
|
+
this.processingExternalSecondary = false;
|
|
646
|
+
}
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (sensorType === SensorType.Motion) {
|
|
650
|
+
// Motion: fully gated during suppression. Frame-diff is fake during
|
|
651
|
+
// camera repositioning.
|
|
652
|
+
if (this.ptzAutotracker.suppressionActive)
|
|
653
|
+
return;
|
|
654
|
+
const filtered = this.applyExternalDetectionFilters(sensorType, properties);
|
|
655
|
+
this.ingestDetectionResult(SensorType.Motion, sensorId, filtered);
|
|
656
|
+
this.eventManager.processResults(this.buildSnapshot());
|
|
657
|
+
this.fetchEventThumbnailAsync();
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
// External secondaries (Face/Plate/Classifier/Clip with requiresFrames=false):
|
|
661
|
+
// direct ingest, no pixel work. For multi-provider types (Classifier), look
|
|
662
|
+
// up the owning pluginId for buffer keying.
|
|
663
|
+
let pluginId;
|
|
664
|
+
if (sensorType === SensorType.Classifier) {
|
|
665
|
+
const typePlugins = this.multiPlugins.get(SensorType.Classifier);
|
|
666
|
+
if (typePlugins) {
|
|
667
|
+
for (const plugin of typePlugins.values()) {
|
|
668
|
+
if (plugin.sensorId === sensorId) {
|
|
669
|
+
pluginId = plugin.pluginId;
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
const filtered = this.applyExternalDetectionFilters(sensorType, properties);
|
|
676
|
+
this.ingestDetectionResult(sensorType, sensorId, filtered, pluginId);
|
|
677
|
+
this.eventManager.processResults(this.buildSnapshot());
|
|
678
|
+
}
|
|
679
|
+
reportSensorTrigger(sensorId, triggerType, action, _sustained, timeoutSeconds) {
|
|
680
|
+
// Use namespaced dwell key so sensor trigger dwells don't overwrite
|
|
681
|
+
// the sensor's own properties (detected/blocked). Motion/audio sensors
|
|
682
|
+
// have their properties managed by dwell; contact/switch/light sensors don't.
|
|
683
|
+
const dwellKey = `trigger:${sensorId}`;
|
|
684
|
+
// Track active sensor trigger types for snapshot
|
|
685
|
+
if (action === 'activate') {
|
|
686
|
+
this.activeSensorTriggerTypes.set(dwellKey, triggerType);
|
|
687
|
+
}
|
|
688
|
+
// Dwell for event lifecycle — consistent with motion/audio.
|
|
689
|
+
// Activate: starts/extends the event. Deactivate: refreshes for cooldown window.
|
|
690
|
+
this.dwell.refresh(dwellKey, timeoutSeconds);
|
|
691
|
+
// Cascade for object-detection gating — only on activate
|
|
692
|
+
if (action === 'activate' && this.cascadeEnabled) {
|
|
693
|
+
this.cascade.triggerMomentary(this.cascadeTimeoutSeconds);
|
|
694
|
+
}
|
|
695
|
+
// Flush immediately so EventManager sees the trigger (like reportSensorWrite)
|
|
696
|
+
this.eventManager.processResults(this.buildSnapshot());
|
|
697
|
+
// Async event-thumb fetch via snapshot URL — covers the trigger-only path
|
|
698
|
+
// (doorbell, contact sensor) where no loop frame is available to encode from.
|
|
699
|
+
// No-op if a loop frame already populated the thumb earlier.
|
|
700
|
+
if (action === 'activate') {
|
|
701
|
+
this.fetchEventThumbnailAsync();
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
reconcileSensorTriggers(activeSensorIds) {
|
|
705
|
+
const activeSet = new Set(activeSensorIds);
|
|
706
|
+
for (const dwellKey of this.activeSensorTriggerTypes.keys()) {
|
|
707
|
+
const sensorId = dwellKey.slice('trigger:'.length);
|
|
708
|
+
if (!activeSet.has(sensorId)) {
|
|
709
|
+
this.activeSensorTriggerTypes.delete(dwellKey);
|
|
710
|
+
this.dwell.clear(dwellKey);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
clearMotionStateForSuppression() {
|
|
715
|
+
const cs = this.currentDetectionState;
|
|
716
|
+
cs.motion = undefined;
|
|
717
|
+
const motionPlugin = this.singlePlugins.get(SensorType.Motion);
|
|
718
|
+
if (motionPlugin) {
|
|
719
|
+
this.writeSensorProperties(motionPlugin.sensorId, { detections: [] });
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
hasPlugin(sensorType) {
|
|
723
|
+
if (this.isMultiProvider(sensorType)) {
|
|
724
|
+
const typePlugins = this.multiPlugins.get(sensorType);
|
|
725
|
+
return typePlugins !== undefined && typePlugins.size > 0;
|
|
726
|
+
}
|
|
727
|
+
return this.singlePlugins.has(sensorType);
|
|
728
|
+
}
|
|
729
|
+
getPlugin(sensorType) {
|
|
730
|
+
return this.singlePlugins.get(sensorType);
|
|
731
|
+
}
|
|
732
|
+
getPluginsForType(sensorType) {
|
|
733
|
+
if (this.isMultiProvider(sensorType)) {
|
|
734
|
+
const typePlugins = this.multiPlugins.get(sensorType);
|
|
735
|
+
return typePlugins ? Array.from(typePlugins.values()) : [];
|
|
736
|
+
}
|
|
737
|
+
const plugin = this.singlePlugins.get(sensorType);
|
|
738
|
+
return plugin ? [plugin] : [];
|
|
739
|
+
}
|
|
740
|
+
getPlugins() {
|
|
741
|
+
const allPlugins = [];
|
|
742
|
+
for (const plugin of this.singlePlugins.values())
|
|
743
|
+
allPlugins.push(plugin);
|
|
744
|
+
for (const typePlugins of this.multiPlugins.values()) {
|
|
745
|
+
for (const plugin of typePlugins.values())
|
|
746
|
+
allPlugins.push(plugin);
|
|
747
|
+
}
|
|
748
|
+
return allPlugins;
|
|
749
|
+
}
|
|
750
|
+
hasAnyPlugins() {
|
|
751
|
+
if (this.singlePlugins.size > 0)
|
|
752
|
+
return true;
|
|
753
|
+
for (const typePlugins of this.multiPlugins.values()) {
|
|
754
|
+
if (typePlugins.size > 0)
|
|
755
|
+
return true;
|
|
756
|
+
}
|
|
757
|
+
return false;
|
|
758
|
+
}
|
|
759
|
+
isRunning() {
|
|
760
|
+
return this.loopRunning;
|
|
761
|
+
}
|
|
762
|
+
isStreaming() {
|
|
763
|
+
return this.frameSource.isStreaming;
|
|
764
|
+
}
|
|
765
|
+
hasSecondaryModelSpec(spec) {
|
|
766
|
+
return spec !== undefined && 'triggerLabels' in spec && Array.isArray(spec.triggerLabels);
|
|
767
|
+
}
|
|
768
|
+
isVideoInputSpec(spec) {
|
|
769
|
+
return spec != null && typeof spec === 'object' && 'width' in spec && 'height' in spec && 'format' in spec;
|
|
770
|
+
}
|
|
771
|
+
isOnEdge(box) {
|
|
772
|
+
return box.x < 0.02 || box.y < 0.02 || box.x + box.width > 0.98 || box.y + box.height > 0.98;
|
|
773
|
+
}
|
|
774
|
+
isAudioModelSpec(spec) {
|
|
775
|
+
return spec !== undefined && 'input' in spec && typeof spec.input === 'object' && 'sampleRate' in spec.input;
|
|
776
|
+
}
|
|
777
|
+
isMultiProvider(sensorType) {
|
|
778
|
+
return SENSOR_TYPE_CONFIG[sensorType]?.multiProvider === true;
|
|
779
|
+
}
|
|
780
|
+
// Video stream is permanently needed when: (1) frame-based motion detection, or
|
|
781
|
+
// (2) audio plugin + object plugin for continuous audio-triggered cascade.
|
|
782
|
+
// External motion (requiresFrames=false) and sensor cascade triggers use an ad-hoc
|
|
783
|
+
// video loop — started on-demand, stopped when cascade ends. This prevents blocking
|
|
784
|
+
// event-based cameras (e.g. Ring) that stop firing events while the stream is consumed.
|
|
785
|
+
shouldVideoBeActive() {
|
|
786
|
+
const motionPlugin = this.singlePlugins.get(SensorType.Motion);
|
|
787
|
+
const objectPlugin = this.singlePlugins.get(SensorType.Object);
|
|
788
|
+
const audioPlugin = this.singlePlugins.get(SensorType.Audio);
|
|
789
|
+
if (motionPlugin?.requiresFrames)
|
|
790
|
+
return true;
|
|
791
|
+
if (audioPlugin && objectPlugin?.requiresFrames)
|
|
792
|
+
return true;
|
|
793
|
+
return false;
|
|
794
|
+
}
|
|
795
|
+
shouldAudioBeActive() {
|
|
796
|
+
const audioPlugin = this.singlePlugins.get(SensorType.Audio);
|
|
797
|
+
return audioPlugin?.requiresFrames === true;
|
|
798
|
+
}
|
|
799
|
+
startVideoLoop() {
|
|
800
|
+
if (this.loopRunning || this.videoStopPromise)
|
|
801
|
+
return;
|
|
802
|
+
this.logger.debug('Starting video detection loop');
|
|
803
|
+
this.loopRunning = true;
|
|
804
|
+
this.reconnectCount = 0;
|
|
805
|
+
this.loopPromise = this.runDetectionLoop();
|
|
806
|
+
}
|
|
807
|
+
async stopVideoLoop() {
|
|
808
|
+
if (!this.loopRunning) {
|
|
809
|
+
if (this.videoStopPromise)
|
|
810
|
+
await this.videoStopPromise;
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
this.logger.debug('Stopping video detection loop');
|
|
814
|
+
this.loopRunning = false;
|
|
815
|
+
const doStop = async () => {
|
|
816
|
+
await this.frameSource.stop();
|
|
817
|
+
await this.loopPromise;
|
|
818
|
+
this.loopPromise = undefined;
|
|
819
|
+
};
|
|
820
|
+
this.videoStopPromise = doStop();
|
|
821
|
+
try {
|
|
822
|
+
await this.videoStopPromise;
|
|
823
|
+
}
|
|
824
|
+
finally {
|
|
825
|
+
this.videoStopPromise = undefined;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
startAudioLoop() {
|
|
829
|
+
if (this.audioLoopRunning || this.audioStopPromise)
|
|
830
|
+
return;
|
|
831
|
+
this.logger.debug('Starting audio detection loop');
|
|
832
|
+
this.audioLoopRunning = true;
|
|
833
|
+
this.audioReconnectCount = 0;
|
|
834
|
+
this.audioLoopPromise = this.runAudioDetectionLoop();
|
|
835
|
+
}
|
|
836
|
+
async stopAudioLoop() {
|
|
837
|
+
if (!this.audioLoopRunning) {
|
|
838
|
+
if (this.audioStopPromise)
|
|
839
|
+
await this.audioStopPromise;
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
this.logger.debug('Stopping audio detection loop');
|
|
843
|
+
this.audioLoopRunning = false;
|
|
844
|
+
const doStop = async () => {
|
|
845
|
+
await this.audioSource?.stop();
|
|
846
|
+
await this.audioLoopPromise;
|
|
847
|
+
this.audioLoopPromise = undefined;
|
|
848
|
+
};
|
|
849
|
+
this.audioStopPromise = doStop();
|
|
850
|
+
try {
|
|
851
|
+
await this.audioStopPromise;
|
|
852
|
+
}
|
|
853
|
+
finally {
|
|
854
|
+
this.audioStopPromise = undefined;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
hasFrameBasedSecondary() {
|
|
858
|
+
const face = this.singlePlugins.get(SensorType.Face);
|
|
859
|
+
if (face?.requiresFrames)
|
|
860
|
+
return true;
|
|
861
|
+
const lpd = this.singlePlugins.get(SensorType.LicensePlate);
|
|
862
|
+
if (lpd?.requiresFrames)
|
|
863
|
+
return true;
|
|
864
|
+
const clip = this.singlePlugins.get(SensorType.Clip);
|
|
865
|
+
if (clip?.requiresFrames)
|
|
866
|
+
return true;
|
|
867
|
+
const classifiers = this.multiPlugins.get(SensorType.Classifier);
|
|
868
|
+
if (classifiers) {
|
|
869
|
+
for (const p of classifiers.values()) {
|
|
870
|
+
if (p.requiresFrames)
|
|
871
|
+
return true;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return false;
|
|
875
|
+
}
|
|
876
|
+
needsAdHocLoop() {
|
|
877
|
+
const obj = this.singlePlugins.get(SensorType.Object);
|
|
878
|
+
if (!obj)
|
|
879
|
+
return false;
|
|
880
|
+
if (obj.requiresFrames)
|
|
881
|
+
return true;
|
|
882
|
+
return this.hasFrameBasedSecondary();
|
|
883
|
+
}
|
|
884
|
+
startAdHocVideoLoopIfNeeded() {
|
|
885
|
+
if (!this.loopRunning && this.needsAdHocLoop()) {
|
|
886
|
+
this.adHocVideoLoop = true;
|
|
887
|
+
this.logger.debug('Starting ad-hoc video loop for sensor cascade trigger');
|
|
888
|
+
this.startVideoLoop();
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
stopAdHocVideoLoopIfIdle() {
|
|
892
|
+
if (this.adHocVideoLoop && !this.shouldVideoBeActive()) {
|
|
893
|
+
this.adHocVideoLoop = false;
|
|
894
|
+
this.logger.debug('Stopping ad-hoc video loop — cascade ended');
|
|
895
|
+
this.stopVideoLoop();
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
fetchEventThumbnailAsync() {
|
|
899
|
+
void (async () => {
|
|
900
|
+
try {
|
|
901
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
902
|
+
try {
|
|
903
|
+
const handle = __addDisposableResource(env_1, await this.frameSource.fetchSnapshotFrame(), true);
|
|
904
|
+
if (!handle)
|
|
905
|
+
return;
|
|
906
|
+
const jpeg = await this.frameScaler.frameToJPEG(handle.frame, 320);
|
|
907
|
+
if (!jpeg)
|
|
908
|
+
return;
|
|
909
|
+
this.eventManager.publishEventThumbnail(jpeg);
|
|
910
|
+
}
|
|
911
|
+
catch (e_1) {
|
|
912
|
+
env_1.error = e_1;
|
|
913
|
+
env_1.hasError = true;
|
|
914
|
+
}
|
|
915
|
+
finally {
|
|
916
|
+
const result_1 = __disposeResources(env_1);
|
|
917
|
+
if (result_1)
|
|
918
|
+
await result_1;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
catch (e) {
|
|
922
|
+
this.logger.debug('event-thumb snapshot failed:', e);
|
|
923
|
+
}
|
|
924
|
+
})();
|
|
925
|
+
}
|
|
926
|
+
calculateDBFS(data, format) {
|
|
927
|
+
let sumSquares = 0;
|
|
928
|
+
let sampleCount = 0;
|
|
929
|
+
if (format === 'float32') {
|
|
930
|
+
const floatView = new Float32Array(data.buffer, data.byteOffset, data.byteLength / 4);
|
|
931
|
+
sampleCount = floatView.length;
|
|
932
|
+
for (let i = 0; i < sampleCount; i++)
|
|
933
|
+
sumSquares += floatView[i] * floatView[i];
|
|
934
|
+
}
|
|
935
|
+
else {
|
|
936
|
+
// PCM16: normalize [-32768, 32767] → [-1.0, 1.0]
|
|
937
|
+
const int16View = new Int16Array(data.buffer, data.byteOffset, data.byteLength / 2);
|
|
938
|
+
sampleCount = int16View.length;
|
|
939
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
940
|
+
const normalized = int16View[i] / 32768;
|
|
941
|
+
sumSquares += normalized * normalized;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
if (sampleCount === 0)
|
|
945
|
+
return -100;
|
|
946
|
+
const rms = Math.sqrt(sumSquares / sampleCount);
|
|
947
|
+
return rms > 0 ? 20 * Math.log10(Math.max(rms, 1e-10)) : -100;
|
|
948
|
+
}
|
|
949
|
+
async runAudioDetectionLoop() {
|
|
950
|
+
const audioPlugin = this.singlePlugins.get(SensorType.Audio);
|
|
951
|
+
if (!audioPlugin?.requiresFrames)
|
|
952
|
+
return;
|
|
953
|
+
const audioSpec = this.isAudioModelSpec(audioPlugin.modelSpec) ? audioPlugin.modelSpec : undefined;
|
|
954
|
+
const sampleRate = audioSpec?.input.sampleRate ?? 16000;
|
|
955
|
+
const channels = audioSpec?.input.channels ?? 1;
|
|
956
|
+
const format = audioSpec?.input.format ?? 'float32';
|
|
957
|
+
const samplesPerFrame = audioSpec?.input.samplesPerFrame;
|
|
958
|
+
const audioConfig = {
|
|
959
|
+
streamUrl: this.config.audioStreamUrl,
|
|
960
|
+
sampleRate,
|
|
961
|
+
channels,
|
|
962
|
+
format,
|
|
963
|
+
samplesPerFrame,
|
|
964
|
+
};
|
|
965
|
+
while (this.audioLoopRunning) {
|
|
966
|
+
try {
|
|
967
|
+
this.audioSource = new AudioSource(audioConfig, this.logger);
|
|
968
|
+
await this.audioSource.start();
|
|
969
|
+
this.logger.debug('Audio stream connected, processing audio frames...');
|
|
970
|
+
this.audioReconnectCount = 0;
|
|
971
|
+
let frameCount = 0;
|
|
972
|
+
let lastAudioFrameId = -1;
|
|
973
|
+
while (this.audioLoopRunning) {
|
|
974
|
+
const snap = await this.audioSource.nextFrame(lastAudioFrameId);
|
|
975
|
+
if (!snap)
|
|
976
|
+
break; // source ended (stop or EOF)
|
|
977
|
+
lastAudioFrameId = snap.id;
|
|
978
|
+
const rawFrame = snap.frame;
|
|
979
|
+
frameCount++;
|
|
980
|
+
try {
|
|
981
|
+
const frameData = rawFrame.data;
|
|
982
|
+
if (!frameData?.[0])
|
|
983
|
+
continue;
|
|
984
|
+
const rawData = frameData[0];
|
|
985
|
+
const dBFS = this.calculateDBFS(rawData, format);
|
|
986
|
+
if (dBFS < this.audioMinDecibels)
|
|
987
|
+
continue;
|
|
988
|
+
const audioFrame = {
|
|
989
|
+
cameraId: this.config.cameraId,
|
|
990
|
+
data: rawData,
|
|
991
|
+
sampleRate,
|
|
992
|
+
channels,
|
|
993
|
+
format,
|
|
994
|
+
timestamp: Date.now(),
|
|
995
|
+
};
|
|
996
|
+
const result = await audioPlugin.proxy.detectAudio(audioFrame);
|
|
997
|
+
if (!result)
|
|
998
|
+
continue;
|
|
999
|
+
// Frame-based audio detection: cascade trigger when detected (Motion's
|
|
1000
|
+
// dwell counterpart for audio is handled in ingestDetectionResult).
|
|
1001
|
+
if (result.detected && this.cascadeEnabled) {
|
|
1002
|
+
const audioTimeout = this.config.detectionSettings.audio.timeout;
|
|
1003
|
+
this.cascade.triggerMomentary(audioTimeout);
|
|
1004
|
+
}
|
|
1005
|
+
// Funnel through the unified ingest path — same as external audio writes.
|
|
1006
|
+
this.ingestDetectionResult(SensorType.Audio, audioPlugin.sensorId, {
|
|
1007
|
+
detected: result.detected,
|
|
1008
|
+
detections: result.detections ?? [],
|
|
1009
|
+
...(result.decibels !== undefined ? { decibels: result.decibels } : {}),
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
catch (error) {
|
|
1013
|
+
this.logger.error('Audio detection error:', error);
|
|
1014
|
+
}
|
|
1015
|
+
finally {
|
|
1016
|
+
try {
|
|
1017
|
+
rawFrame[Symbol.dispose]?.();
|
|
1018
|
+
}
|
|
1019
|
+
catch {
|
|
1020
|
+
// Best effort
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
await this.audioSource.stop();
|
|
1025
|
+
if (this.audioLoopRunning && frameCount === 0) {
|
|
1026
|
+
this.logger.debug('Audio stream ended without frames, waiting before reconnect...');
|
|
1027
|
+
await new Promise((resolve) => setTimeout(resolve, this.normalReconnectDelay));
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
catch (error) {
|
|
1031
|
+
if (!this.audioLoopRunning)
|
|
1032
|
+
break;
|
|
1033
|
+
await this.audioSource?.stop();
|
|
1034
|
+
this.audioReconnectCount = Math.min(this.audioReconnectCount + 1, this.maxReconnectCount);
|
|
1035
|
+
const delay = this.audioReconnectCount >= this.maxReconnectCount ? this.maxReconnectDelay : this.normalReconnectDelay;
|
|
1036
|
+
this.logger.warn(`Audio stream error, reconnecting in ${delay / 1000}s: ${error.message}`);
|
|
1037
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
await this.audioSource?.stop();
|
|
1041
|
+
this.audioSource = undefined;
|
|
1042
|
+
this.logger.debug('Audio detection loop ended');
|
|
1043
|
+
}
|
|
1044
|
+
async runDetectionLoop() {
|
|
1045
|
+
while (this.loopRunning) {
|
|
1046
|
+
try {
|
|
1047
|
+
await this.frameSource.start();
|
|
1048
|
+
this.frameScaler.updateHardwareContext(this.frameSource.hardwareContext);
|
|
1049
|
+
this.logger.debug('Stream connected, processing frames...');
|
|
1050
|
+
this.reconnectCount = 0;
|
|
1051
|
+
let frameCount = 0;
|
|
1052
|
+
let lastFrameId = -1;
|
|
1053
|
+
while (this.loopRunning) {
|
|
1054
|
+
const snap = await this.frameSource.nextFrame(lastFrameId);
|
|
1055
|
+
if (!snap)
|
|
1056
|
+
break; // source ended (stop or EOF)
|
|
1057
|
+
lastFrameId = snap.id;
|
|
1058
|
+
frameCount++;
|
|
1059
|
+
try {
|
|
1060
|
+
await this.processRawFrame(snap.frame);
|
|
1061
|
+
}
|
|
1062
|
+
finally {
|
|
1063
|
+
try {
|
|
1064
|
+
snap.frame[Symbol.dispose]?.();
|
|
1065
|
+
}
|
|
1066
|
+
catch {
|
|
1067
|
+
// Best effort
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
await this.frameSource.stop();
|
|
1072
|
+
this.frameScaler.clearCache();
|
|
1073
|
+
if (this.loopRunning && frameCount === 0) {
|
|
1074
|
+
this.logger.debug('Stream ended without frames, waiting before reconnect...');
|
|
1075
|
+
await new Promise((resolve) => setTimeout(resolve, this.normalReconnectDelay));
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
catch (error) {
|
|
1079
|
+
if (!this.loopRunning)
|
|
1080
|
+
break;
|
|
1081
|
+
await this.frameSource.stop();
|
|
1082
|
+
this.frameScaler.clearCache();
|
|
1083
|
+
this.reconnectCount = Math.min(this.reconnectCount + 1, this.maxReconnectCount);
|
|
1084
|
+
const delay = this.reconnectCount >= this.maxReconnectCount ? this.maxReconnectDelay : this.normalReconnectDelay;
|
|
1085
|
+
this.logger.warn(`Stream error, reconnecting in ${delay / 1000}s: ${error.message}`);
|
|
1086
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
await this.frameSource.stop();
|
|
1090
|
+
this.frameScaler.clearCache();
|
|
1091
|
+
this.logger.debug('Detection loop ended');
|
|
1092
|
+
}
|
|
1093
|
+
async processRawFrame(rawFrame) {
|
|
1094
|
+
if (!this.loopRunning || !this.hasAnyPlugins())
|
|
1095
|
+
return;
|
|
1096
|
+
try {
|
|
1097
|
+
await this.processDetection(rawFrame);
|
|
1098
|
+
}
|
|
1099
|
+
catch (error) {
|
|
1100
|
+
this.logger.error('Detection processing error:', error);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
async processDetection(rawFrame) {
|
|
1104
|
+
const t0 = Date.now();
|
|
1105
|
+
let motionDetected = false;
|
|
1106
|
+
let objectDetections = [];
|
|
1107
|
+
const results = { timestamp: t0 };
|
|
1108
|
+
// Refresh ReID counters every frame while cascade is active so dead
|
|
1109
|
+
// tracks never expire during the cascade window — exactly tied to
|
|
1110
|
+
// cascade lifecycle, no estimated timeout needed.
|
|
1111
|
+
if (this.cascade.isActive) {
|
|
1112
|
+
this.pipeline.refreshReid();
|
|
1113
|
+
}
|
|
1114
|
+
// PTZ-suppression gating:
|
|
1115
|
+
// - Motion: skipped entirely. Frame-diff is genuinely wrong while the camera
|
|
1116
|
+
// is repositioning (whole scene "moves") — the detector produces garbage.
|
|
1117
|
+
// - Object: runs through the full pipeline unchanged. Norfair is fed the
|
|
1118
|
+
// per-frame PTZ pose delta (via `consumePoseDelta()`) so Kalman
|
|
1119
|
+
// predictions stay aligned with the world frame across pans — track ids
|
|
1120
|
+
// survive camera motion instead of being lost-and-re-acquired every
|
|
1121
|
+
// cycle. The autotracker itself gates motor decisions on its own
|
|
1122
|
+
// `isPtzMoving` state, so it doesn't issue commands during a pan.
|
|
1123
|
+
const ptzSuppressed = this.ptzAutotracker.suppressionActive;
|
|
1124
|
+
// 1. Motion detection — runs every frame whenever a motion plugin is registered,
|
|
1125
|
+
// regardless of cascade state. Two reasons:
|
|
1126
|
+
// a) Motion sensor properties (bboxes shown in UI) need to stay fresh during cascade
|
|
1127
|
+
// b) Re-triggering cascade.triggerMomentary on each detected frame extends the cascade
|
|
1128
|
+
// naturally, so a sustained motion event keeps cascade alive as long as motion happens.
|
|
1129
|
+
// The cascade is the gate for OBJECT detection, not for motion.
|
|
1130
|
+
const motionPlugin = this.singlePlugins.get(SensorType.Motion);
|
|
1131
|
+
if (motionPlugin?.requiresFrames && !ptzSuppressed) {
|
|
1132
|
+
const motionFrame = await this.scaleForMotion(rawFrame);
|
|
1133
|
+
if (!this.loopRunning)
|
|
1134
|
+
return;
|
|
1135
|
+
if (motionFrame) {
|
|
1136
|
+
try {
|
|
1137
|
+
const result = await motionPlugin.proxy.detectMotion(motionFrame);
|
|
1138
|
+
if (!this.loopRunning)
|
|
1139
|
+
return;
|
|
1140
|
+
if (result.detections.length > 0) {
|
|
1141
|
+
const filtered = this.pipeline.runMergeAndZoneFilter(result.detections);
|
|
1142
|
+
motionDetected = filtered.length > 0;
|
|
1143
|
+
results.motion = { ...result, detections: filtered };
|
|
1144
|
+
}
|
|
1145
|
+
else {
|
|
1146
|
+
// Plugin reports no motion this frame — record empty so UI clears stale bboxes
|
|
1147
|
+
results.motion = { detected: false, detections: [] };
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
catch (error) {
|
|
1151
|
+
if (!this.loopRunning || isNoRespondersError(error))
|
|
1152
|
+
return;
|
|
1153
|
+
this.logger.error('Motion detection error:', error);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
else if (this.cascade.isActive) {
|
|
1158
|
+
// No frame-based motion plugin — cascade is the only motion-equivalent signal
|
|
1159
|
+
motionDetected = true;
|
|
1160
|
+
results.cascadeTriggered = true;
|
|
1161
|
+
}
|
|
1162
|
+
// Funnel motion result through unified ingest path (handles dwell + cascade + buffer + EventManager tick).
|
|
1163
|
+
// `detected` is re-derived from post-zone-filter detections: if the plugin reported
|
|
1164
|
+
// motion but the zone filter wiped all boxes, effective detected is false. The plugin's
|
|
1165
|
+
// own `detected` flag is ignored on purpose — zone filtering wins.
|
|
1166
|
+
if (results.motion && motionPlugin) {
|
|
1167
|
+
this.ingestDetectionResult(SensorType.Motion, motionPlugin.sensorId, {
|
|
1168
|
+
detected: motionDetected,
|
|
1169
|
+
detections: results.motion.detections,
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1172
|
+
// 2. Object detection — runs only when the cascade is active (i.e. some
|
|
1173
|
+
// wake source has fired: frame-based motion, external motion, audio, or
|
|
1174
|
+
// a configured sensor trigger). When cascade is disabled in the camera
|
|
1175
|
+
// config, runs unconditionally as an always-on detector.
|
|
1176
|
+
//
|
|
1177
|
+
// A motion plugin (frame-based OR external) must be registered for object
|
|
1178
|
+
// detection to ever fire — without one, no wake source exists for object,
|
|
1179
|
+
// so the cascade would never become active.
|
|
1180
|
+
const objectPlugin = this.singlePlugins.get(SensorType.Object);
|
|
1181
|
+
// Object detection runs during suppression too — the tracker stays alive
|
|
1182
|
+
// across pans via Norfair's camera-motion compensation so autotracker
|
|
1183
|
+
// keeps a stable lock. Without suppression: needs an active cascade (or
|
|
1184
|
+
// cascade disabled globally).
|
|
1185
|
+
const shouldDetectObjects = objectPlugin?.requiresFrames === true && (ptzSuppressed || !this.cascadeEnabled || this.cascade.isActive);
|
|
1186
|
+
if (shouldDetectObjects) {
|
|
1187
|
+
const objectFrame = await this.scaleForObject(rawFrame);
|
|
1188
|
+
if (!this.loopRunning)
|
|
1189
|
+
return;
|
|
1190
|
+
if (objectFrame) {
|
|
1191
|
+
try {
|
|
1192
|
+
const result = await objectPlugin.proxy.detectObjects(objectFrame);
|
|
1193
|
+
if (!this.loopRunning)
|
|
1194
|
+
return;
|
|
1195
|
+
// Full pipeline (always): NMS → merge → zone filter → track (with
|
|
1196
|
+
// appearance ReID) → line crossing. Runs even on empty-detection
|
|
1197
|
+
// frames so Norfair advances Kalman state and the autotracker sees
|
|
1198
|
+
// extrapolated positions instead of a momentary hole.
|
|
1199
|
+
//
|
|
1200
|
+
// The PTZ pose delta is handed to Norfair so Kalman predictions
|
|
1201
|
+
// are transformed into a world-stable frame — track ids survive
|
|
1202
|
+
// pans instead of going through LOST → REACQUIRE every cycle.
|
|
1203
|
+
const poseDelta = this.ptzAutotracker.consumePoseDelta();
|
|
1204
|
+
const pipelineResult = this.pipeline.process(result.detections, objectFrame, poseDelta);
|
|
1205
|
+
// Tracks for UI: matched always pass, extrapolated (Kalman-only)
|
|
1206
|
+
// are shown for smooth bbox display across single-frame detector
|
|
1207
|
+
// misses — but filtered when they've drifted too far off-frame.
|
|
1208
|
+
// When a fast-moving target walks off-screen, Norfair keeps
|
|
1209
|
+
// extrapolating based on the last-known velocity; without this
|
|
1210
|
+
// guard the UI ends up drawing ghost bboxes floating outside the
|
|
1211
|
+
// stream and the autotracker has no reason to chase them anyway.
|
|
1212
|
+
const visibleTracks = pipelineResult.tracked.filter((t) => {
|
|
1213
|
+
if (!t.trackLost)
|
|
1214
|
+
return true;
|
|
1215
|
+
const cx = t.box.x + t.box.width * 0.5;
|
|
1216
|
+
const cy = t.box.y + t.box.height * 0.5;
|
|
1217
|
+
return cx > -0.1 && cx < 1.1 && cy > -0.1 && cy < 1.1;
|
|
1218
|
+
});
|
|
1219
|
+
objectDetections = visibleTracks.filter((t) => !t.trackLost);
|
|
1220
|
+
results.object = { ...result, detections: visibleTracks };
|
|
1221
|
+
if (pipelineResult.crossings.length > 0)
|
|
1222
|
+
results.lineCrossings = pipelineResult.crossings;
|
|
1223
|
+
// Feed the autotracker with ALL tracked detections, incl. Kalman-
|
|
1224
|
+
// extrapolated ones. When the object detector misses a single frame
|
|
1225
|
+
// (normal with YOLO-style models), Norfair's extrapolation gives
|
|
1226
|
+
// the best estimate of where the target still is — hiding that
|
|
1227
|
+
// from the autotracker would cause a one-frame "target gone" blip
|
|
1228
|
+
// and flip it into LOST, only to REACQUIRE on the very next frame
|
|
1229
|
+
// when the detection returns. That churn is orthogonal to camera
|
|
1230
|
+
// motion and shouldn't drive state transitions. The autotracker
|
|
1231
|
+
// gates motor decisions on its own `isPtzMoving` flag, so during
|
|
1232
|
+
// suppression it observes without commanding.
|
|
1233
|
+
this.ptzAutotracker.handleObjectDetections(pipelineResult.tracked);
|
|
1234
|
+
}
|
|
1235
|
+
catch (error) {
|
|
1236
|
+
if (!this.loopRunning || isNoRespondersError(error))
|
|
1237
|
+
return;
|
|
1238
|
+
this.logger.error('Object detection error:', error);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
if (results.lineCrossings && results.lineCrossings.length > 0) {
|
|
1243
|
+
for (const c of results.lineCrossings) {
|
|
1244
|
+
this.logger.debug(`Line crossing: ${c.label}#${c.trackId} crossed "${c.lineName}" dir=${c.direction} conf=${c.confidence.toFixed(2)}`);
|
|
1245
|
+
}
|
|
1246
|
+
// Buffer line crossings so the EventManager snapshot picks them up
|
|
1247
|
+
this.currentDetectionState.lineCrossings = results.lineCrossings;
|
|
1248
|
+
}
|
|
1249
|
+
// Funnel object result through unified ingest path. Same rule as motion:
|
|
1250
|
+
// detected is re-derived from post-pipeline detections, the plugin's own
|
|
1251
|
+
// detected flag is ignored after pipeline filtering.
|
|
1252
|
+
if (results.object && objectPlugin) {
|
|
1253
|
+
this.ingestDetectionResult(SensorType.Object, objectPlugin.sensorId, {
|
|
1254
|
+
detected: objectDetections.length > 0,
|
|
1255
|
+
detections: results.object.detections,
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
if (!this.loopRunning)
|
|
1259
|
+
return;
|
|
1260
|
+
// 3. Secondary detectors + per-detection thumbnails. Result-collection only —
|
|
1261
|
+
// ingest happens via ingestResultsForAllSecondaries below so the loop tick
|
|
1262
|
+
// and the external-RPC path share the same secondary-processing helper.
|
|
1263
|
+
if (objectDetections.length > 0) {
|
|
1264
|
+
await this.runSecondariesAndThumbnails(rawFrame, objectDetections, results);
|
|
1265
|
+
}
|
|
1266
|
+
if (!this.loopRunning)
|
|
1267
|
+
return;
|
|
1268
|
+
// 4. Funnel secondary results through unified ingest path.
|
|
1269
|
+
this.ingestResultsForAllSecondaries(results);
|
|
1270
|
+
// 5. Single flush — one processResults per frame, AFTER all detectors + thumbnails.
|
|
1271
|
+
// This ensures segment-start messages have thumbnails and all secondary detection
|
|
1272
|
+
// data (faces, plates, classifiers, clips) is available when the segment opens.
|
|
1273
|
+
if (!this.loopRunning)
|
|
1274
|
+
return;
|
|
1275
|
+
const snapshot = this.buildSnapshot();
|
|
1276
|
+
if (results.thumbnails && results.thumbnails.length > 0) {
|
|
1277
|
+
snapshot.thumbnails = results.thumbnails;
|
|
1278
|
+
}
|
|
1279
|
+
// 5a. Event-level thumbnail — full-frame downscaled JPEG. Generated lazily
|
|
1280
|
+
// whenever the EventManager signals it still needs one. This covers two cases:
|
|
1281
|
+
// 1. Event was already started by a non-frame path (sensor trigger, motion
|
|
1282
|
+
// ingest from a plugin) — first frame after start fills it in.
|
|
1283
|
+
// 2. Event will be started by THIS frame's triggers — pre-encode so the
|
|
1284
|
+
// 'start' message carries the thumbnail inline.
|
|
1285
|
+
// We use `eventManagerWillStart` heuristically here: if there's a trigger
|
|
1286
|
+
// signal in the snapshot AND no active event yet, the event will be started
|
|
1287
|
+
// by this processResults call. Either way, attaching is harmless because
|
|
1288
|
+
// EventManager only consumes it if `needsEventThumbnail` is true.
|
|
1289
|
+
if (this.eventManager.needsThumbnail() || this.snapshotWillStartEvent(snapshot)) {
|
|
1290
|
+
try {
|
|
1291
|
+
const jpeg = await this.frameScaler.frameToJPEG(rawFrame, 320);
|
|
1292
|
+
if (jpeg)
|
|
1293
|
+
snapshot.eventThumbnail = jpeg;
|
|
1294
|
+
}
|
|
1295
|
+
catch (error) {
|
|
1296
|
+
this.logger.error('Event thumbnail generation error:', error);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
this.eventManager.processResults(snapshot);
|
|
1300
|
+
}
|
|
1301
|
+
snapshotWillStartEvent(snapshot) {
|
|
1302
|
+
if (this.eventManager.hasActiveEvent())
|
|
1303
|
+
return false;
|
|
1304
|
+
if (snapshot.motion?.detected)
|
|
1305
|
+
return true;
|
|
1306
|
+
if (snapshot.audio?.detected)
|
|
1307
|
+
return true;
|
|
1308
|
+
if (snapshot.cascadeTriggered)
|
|
1309
|
+
return true;
|
|
1310
|
+
if ((snapshot.sensorTriggers?.length ?? 0) > 0)
|
|
1311
|
+
return true;
|
|
1312
|
+
if ((snapshot.lineCrossings?.length ?? 0) > 0)
|
|
1313
|
+
return true;
|
|
1314
|
+
return false;
|
|
1315
|
+
}
|
|
1316
|
+
async resolveFaceIdentities(faces) {
|
|
1317
|
+
const withEmbeddings = faces.filter((f) => f.embedding?.length);
|
|
1318
|
+
if (!withEmbeddings.length)
|
|
1319
|
+
return;
|
|
1320
|
+
const facePlugin = this.singlePlugins.get(SensorType.Face);
|
|
1321
|
+
const embeddingModel = facePlugin?.modelSpec?.embeddingModel;
|
|
1322
|
+
if (!embeddingModel)
|
|
1323
|
+
return;
|
|
1324
|
+
const nvr = await this.getNvrProxy();
|
|
1325
|
+
if (!nvr)
|
|
1326
|
+
return;
|
|
1327
|
+
try {
|
|
1328
|
+
const embeddings = withEmbeddings.map((f) => f.embedding);
|
|
1329
|
+
const matches = await nvr.matchFaces(embeddings, embeddingModel);
|
|
1330
|
+
for (let i = 0; i < withEmbeddings.length; i++) {
|
|
1331
|
+
if (matches[i]) {
|
|
1332
|
+
withEmbeddings[i].identity = matches[i].identity;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
catch (error) {
|
|
1337
|
+
if (!this.loopRunning || isNoRespondersError(error))
|
|
1338
|
+
return;
|
|
1339
|
+
this.logger.error('Could not resolve face identities:', error);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
async scaleForMotion(rawFrame) {
|
|
1343
|
+
const motionPlugin = this.singlePlugins.get(SensorType.Motion);
|
|
1344
|
+
if (!motionPlugin?.requiresFrames)
|
|
1345
|
+
return undefined;
|
|
1346
|
+
const maxWidth = MOTION_WIDTH_MAP[this.motionResolution];
|
|
1347
|
+
const scaled = await this.frameScaler.scaleProportional(rawFrame, maxWidth, 'gray');
|
|
1348
|
+
return scaled ? this.frameScaler.toVideoFrameData(scaled) : undefined;
|
|
1349
|
+
}
|
|
1350
|
+
async scaleForObject(rawFrame) {
|
|
1351
|
+
const objectPlugin = this.singlePlugins.get(SensorType.Object);
|
|
1352
|
+
if (!objectPlugin?.requiresFrames)
|
|
1353
|
+
return undefined;
|
|
1354
|
+
const inputSpec = objectPlugin.modelSpec?.input;
|
|
1355
|
+
if (!this.isVideoInputSpec(inputSpec))
|
|
1356
|
+
return undefined;
|
|
1357
|
+
const scaled = await this.frameScaler.scaleToSpec(rawFrame, inputSpec);
|
|
1358
|
+
return scaled ? this.frameScaler.toVideoFrameData(scaled) : undefined;
|
|
1359
|
+
}
|
|
1360
|
+
async prepareSecondaryRegions(rawFrame, objectDetections) {
|
|
1361
|
+
const result = new Map();
|
|
1362
|
+
// Collect all active secondary plugins and their requirements
|
|
1363
|
+
const consumers = [];
|
|
1364
|
+
const facePlugin = this.singlePlugins.get(SensorType.Face);
|
|
1365
|
+
if (facePlugin && this.hasSecondaryModelSpec(facePlugin.modelSpec) && this.isVideoInputSpec(facePlugin.modelSpec.input)) {
|
|
1366
|
+
consumers.push({ key: 'face', triggerLabels: facePlugin.modelSpec.triggerLabels, input: facePlugin.modelSpec.input });
|
|
1367
|
+
}
|
|
1368
|
+
const lpdPlugin = this.singlePlugins.get(SensorType.LicensePlate);
|
|
1369
|
+
if (lpdPlugin && this.hasSecondaryModelSpec(lpdPlugin.modelSpec) && this.isVideoInputSpec(lpdPlugin.modelSpec.input)) {
|
|
1370
|
+
consumers.push({ key: 'lpd', triggerLabels: lpdPlugin.modelSpec.triggerLabels, input: lpdPlugin.modelSpec.input });
|
|
1371
|
+
}
|
|
1372
|
+
const clipPlugin = this.singlePlugins.get(SensorType.Clip);
|
|
1373
|
+
if (clipPlugin && this.hasSecondaryModelSpec(clipPlugin.modelSpec) && this.isVideoInputSpec(clipPlugin.modelSpec.input)) {
|
|
1374
|
+
consumers.push({ key: 'clip', triggerLabels: clipPlugin.modelSpec.triggerLabels, input: clipPlugin.modelSpec.input });
|
|
1375
|
+
}
|
|
1376
|
+
const classifierPlugins = this.multiPlugins.get(SensorType.Classifier);
|
|
1377
|
+
if (classifierPlugins) {
|
|
1378
|
+
for (const [pluginId, classifierPlugin] of classifierPlugins) {
|
|
1379
|
+
if (this.hasSecondaryModelSpec(classifierPlugin.modelSpec) && this.isVideoInputSpec(classifierPlugin.modelSpec.input)) {
|
|
1380
|
+
consumers.push({ key: `classifier:${pluginId}`, triggerLabels: classifierPlugin.modelSpec.triggerLabels, input: classifierPlugin.modelSpec.input });
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
if (consumers.length === 0)
|
|
1385
|
+
return result;
|
|
1386
|
+
// For each detection, determine which consumers need it and what sizes
|
|
1387
|
+
for (const detection of objectDetections) {
|
|
1388
|
+
const detLabel = detection.label.toLowerCase();
|
|
1389
|
+
const targets = [];
|
|
1390
|
+
for (const consumer of consumers) {
|
|
1391
|
+
if (consumer.triggerLabels.length === 0 || consumer.triggerLabels.some((l) => l.toLowerCase() === detLabel)) {
|
|
1392
|
+
targets.push({ key: consumer.key, width: consumer.input.width, height: consumer.input.height, format: consumer.input.format });
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
if (targets.length === 0)
|
|
1396
|
+
continue;
|
|
1397
|
+
// Deduplicate targets with identical dimensions (e.g. two classifiers at same size)
|
|
1398
|
+
// — keep first key, share the result
|
|
1399
|
+
const uniqueTargets = [];
|
|
1400
|
+
const dupeMap = new Map(); // sizeKey → [consumerKey, ...]
|
|
1401
|
+
for (const t of targets) {
|
|
1402
|
+
const sizeKey = `${t.width}x${t.height}_${t.format}`;
|
|
1403
|
+
const existing = dupeMap.get(sizeKey);
|
|
1404
|
+
if (existing) {
|
|
1405
|
+
existing.push(t.key);
|
|
1406
|
+
}
|
|
1407
|
+
else {
|
|
1408
|
+
dupeMap.set(sizeKey, [t.key]);
|
|
1409
|
+
uniqueTargets.push(t);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
const regions = await this.frameScaler.cropAndScaleMulti(rawFrame, detection, uniqueTargets);
|
|
1413
|
+
// Distribute results to all consumers (including those sharing dimensions)
|
|
1414
|
+
for (const [_sizeKey, consumerKeys] of dupeMap) {
|
|
1415
|
+
const primaryKey = consumerKeys[0];
|
|
1416
|
+
const region = regions.get(primaryKey);
|
|
1417
|
+
if (!region)
|
|
1418
|
+
continue;
|
|
1419
|
+
for (const key of consumerKeys) {
|
|
1420
|
+
const list = result.get(key);
|
|
1421
|
+
if (list) {
|
|
1422
|
+
list.push(region);
|
|
1423
|
+
}
|
|
1424
|
+
else {
|
|
1425
|
+
result.set(key, [region]);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
return result;
|
|
1431
|
+
}
|
|
1432
|
+
async runSecondaryDetection(type, results, fn) {
|
|
1433
|
+
let detections = undefined;
|
|
1434
|
+
try {
|
|
1435
|
+
detections = await fn();
|
|
1436
|
+
}
|
|
1437
|
+
catch (error) {
|
|
1438
|
+
if (!this.loopRunning || isNoRespondersError(error))
|
|
1439
|
+
return;
|
|
1440
|
+
const logType = type === SensorType.Face ? 'Face' : type === SensorType.LicensePlate ? 'License plate' : type === SensorType.Clip ? 'CLIP' : 'Classifier';
|
|
1441
|
+
this.logger.error(`${logType} detection error:`, error);
|
|
1442
|
+
}
|
|
1443
|
+
if (!detections)
|
|
1444
|
+
return;
|
|
1445
|
+
if (type === SensorType.Face) {
|
|
1446
|
+
results.face = detections;
|
|
1447
|
+
await this.resolveFaceIdentities(results.face.detections);
|
|
1448
|
+
}
|
|
1449
|
+
else if (type === SensorType.LicensePlate) {
|
|
1450
|
+
results.licensePlate = detections;
|
|
1451
|
+
}
|
|
1452
|
+
else if (type === SensorType.Clip) {
|
|
1453
|
+
results.clip = detections;
|
|
1454
|
+
const clipPlugin = this.singlePlugins.get(SensorType.Clip);
|
|
1455
|
+
results.clipEmbeddingModel = clipPlugin?.modelSpec?.embeddingModel;
|
|
1456
|
+
}
|
|
1457
|
+
else if (type === SensorType.Classifier) {
|
|
1458
|
+
results.classifiers ??= {};
|
|
1459
|
+
for (const { pluginId, result } of detections) {
|
|
1460
|
+
results.classifiers[pluginId] = result;
|
|
1461
|
+
}
|
|
1462
|
+
if (Object.keys(results.classifiers).length === 0)
|
|
1463
|
+
delete results.classifiers;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
ingestResultsForAllSecondaries(results) {
|
|
1467
|
+
if (results.face) {
|
|
1468
|
+
const facePlugin = this.singlePlugins.get(SensorType.Face);
|
|
1469
|
+
if (facePlugin) {
|
|
1470
|
+
this.ingestDetectionResult(SensorType.Face, facePlugin.sensorId, {
|
|
1471
|
+
detected: results.face.detected,
|
|
1472
|
+
detections: results.face.detections,
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
if (results.licensePlate) {
|
|
1477
|
+
const lpdPlugin = this.singlePlugins.get(SensorType.LicensePlate);
|
|
1478
|
+
if (lpdPlugin) {
|
|
1479
|
+
this.ingestDetectionResult(SensorType.LicensePlate, lpdPlugin.sensorId, {
|
|
1480
|
+
detected: results.licensePlate.detected,
|
|
1481
|
+
detections: results.licensePlate.detections,
|
|
1482
|
+
});
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
if (results.classifiers) {
|
|
1486
|
+
const classifierPlugins = this.multiPlugins.get(SensorType.Classifier);
|
|
1487
|
+
if (classifierPlugins) {
|
|
1488
|
+
for (const [pluginId, classifierResult] of Object.entries(results.classifiers)) {
|
|
1489
|
+
const plugin = classifierPlugins.get(pluginId);
|
|
1490
|
+
if (plugin) {
|
|
1491
|
+
this.ingestDetectionResult(SensorType.Classifier, plugin.sensorId, {
|
|
1492
|
+
detected: classifierResult.detected,
|
|
1493
|
+
detections: classifierResult.detections,
|
|
1494
|
+
}, pluginId);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
if (results.clip) {
|
|
1500
|
+
// Clip has no sensor properties — embeddings flow through buffer only.
|
|
1501
|
+
this.currentDetectionState.clip = results.clip;
|
|
1502
|
+
this.currentDetectionState.clipEmbeddingModel = results.clipEmbeddingModel;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
async runSecondariesAndThumbnails(rawFrame, objectDetections, results) {
|
|
1506
|
+
if (objectDetections.length === 0)
|
|
1507
|
+
return;
|
|
1508
|
+
const regionMap = await this.prepareSecondaryRegions(rawFrame, objectDetections);
|
|
1509
|
+
await Promise.allSettled([
|
|
1510
|
+
this.runSecondaryDetection(SensorType.Face, results, () => this.runFaceDetection(regionMap.get('face') ?? [])),
|
|
1511
|
+
this.runSecondaryDetection(SensorType.LicensePlate, results, () => this.runLicensePlateDetection(regionMap.get('lpd') ?? [])),
|
|
1512
|
+
this.runSecondaryDetection(SensorType.Classifier, results, () => this.runClassifierDetections(regionMap)),
|
|
1513
|
+
this.runSecondaryDetection(SensorType.Clip, results, () => this.runClipDetection(regionMap.get('clip') ?? [])),
|
|
1514
|
+
]);
|
|
1515
|
+
if (results.face?.detections.length) {
|
|
1516
|
+
const facePlugin = this.singlePlugins.get(SensorType.Face);
|
|
1517
|
+
results.faceEmbeddingModel = facePlugin?.modelSpec?.embeddingModel;
|
|
1518
|
+
this.currentDetectionState.faceEmbeddingModel = results.faceEmbeddingModel;
|
|
1519
|
+
}
|
|
1520
|
+
try {
|
|
1521
|
+
results.thumbnails = await this.generateThumbnails(rawFrame, objectDetections, results);
|
|
1522
|
+
}
|
|
1523
|
+
catch (error) {
|
|
1524
|
+
this.logger.error('Thumbnail generation error:', error);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
async runSecondariesFullFrame(rawFrame, results) {
|
|
1528
|
+
const regionMap = await this.prepareFullFrameRegions(rawFrame);
|
|
1529
|
+
if (regionMap.size > 0) {
|
|
1530
|
+
await Promise.allSettled([
|
|
1531
|
+
this.runSecondaryDetection(SensorType.Face, results, () => this.runFaceDetection(regionMap.get('face') ?? [])),
|
|
1532
|
+
this.runSecondaryDetection(SensorType.LicensePlate, results, () => this.runLicensePlateDetection(regionMap.get('lpd') ?? [])),
|
|
1533
|
+
this.runSecondaryDetection(SensorType.Classifier, results, () => this.runClassifierDetections(regionMap)),
|
|
1534
|
+
this.runSecondaryDetection(SensorType.Clip, results, () => this.runClipDetection(regionMap.get('clip') ?? [])),
|
|
1535
|
+
]);
|
|
1536
|
+
if (results.face?.detections.length) {
|
|
1537
|
+
const facePlugin = this.singlePlugins.get(SensorType.Face);
|
|
1538
|
+
results.faceEmbeddingModel = facePlugin?.modelSpec?.embeddingModel;
|
|
1539
|
+
this.currentDetectionState.faceEmbeddingModel = results.faceEmbeddingModel;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
try {
|
|
1543
|
+
return await this.frameScaler.frameToJPEG(rawFrame, 320);
|
|
1544
|
+
}
|
|
1545
|
+
catch (error) {
|
|
1546
|
+
this.logger.debug('Full-frame scene thumbnail failed:', error);
|
|
1547
|
+
return null;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
async prepareFullFrameRegions(rawFrame) {
|
|
1551
|
+
const result = new Map();
|
|
1552
|
+
const consumers = [];
|
|
1553
|
+
const facePlugin = this.singlePlugins.get(SensorType.Face);
|
|
1554
|
+
if (facePlugin?.requiresFrames && this.hasSecondaryModelSpec(facePlugin.modelSpec) && this.isVideoInputSpec(facePlugin.modelSpec.input)) {
|
|
1555
|
+
consumers.push({ key: 'face', triggerLabels: facePlugin.modelSpec.triggerLabels, input: facePlugin.modelSpec.input });
|
|
1556
|
+
}
|
|
1557
|
+
const lpdPlugin = this.singlePlugins.get(SensorType.LicensePlate);
|
|
1558
|
+
if (lpdPlugin?.requiresFrames && this.hasSecondaryModelSpec(lpdPlugin.modelSpec) && this.isVideoInputSpec(lpdPlugin.modelSpec.input)) {
|
|
1559
|
+
consumers.push({ key: 'lpd', triggerLabels: lpdPlugin.modelSpec.triggerLabels, input: lpdPlugin.modelSpec.input });
|
|
1560
|
+
}
|
|
1561
|
+
const clipPlugin = this.singlePlugins.get(SensorType.Clip);
|
|
1562
|
+
if (clipPlugin?.requiresFrames && this.hasSecondaryModelSpec(clipPlugin.modelSpec) && this.isVideoInputSpec(clipPlugin.modelSpec.input)) {
|
|
1563
|
+
consumers.push({ key: 'clip', triggerLabels: clipPlugin.modelSpec.triggerLabels, input: clipPlugin.modelSpec.input });
|
|
1564
|
+
}
|
|
1565
|
+
const classifierPlugins = this.multiPlugins.get(SensorType.Classifier);
|
|
1566
|
+
if (classifierPlugins) {
|
|
1567
|
+
for (const [pluginId, plugin] of classifierPlugins) {
|
|
1568
|
+
if (plugin.requiresFrames && this.hasSecondaryModelSpec(plugin.modelSpec) && this.isVideoInputSpec(plugin.modelSpec.input)) {
|
|
1569
|
+
consumers.push({ key: `classifier:${pluginId}`, triggerLabels: plugin.modelSpec.triggerLabels, input: plugin.modelSpec.input });
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
if (consumers.length === 0)
|
|
1574
|
+
return result;
|
|
1575
|
+
const frameWidth = rawFrame.width;
|
|
1576
|
+
const frameHeight = rawFrame.height;
|
|
1577
|
+
const fullFrameDetection = {
|
|
1578
|
+
label: 'person',
|
|
1579
|
+
confidence: 1.0,
|
|
1580
|
+
box: { x: 0, y: 0, width: 1, height: 1 },
|
|
1581
|
+
};
|
|
1582
|
+
for (const consumer of consumers) {
|
|
1583
|
+
const scaled = await this.frameScaler.scaleToSpec(rawFrame, consumer.input);
|
|
1584
|
+
if (!scaled)
|
|
1585
|
+
continue;
|
|
1586
|
+
const region = {
|
|
1587
|
+
frame: this.frameScaler.toVideoFrameData(scaled, `fullframe:${consumer.key}`),
|
|
1588
|
+
detection: fullFrameDetection,
|
|
1589
|
+
offset: { x: 0, y: 0 },
|
|
1590
|
+
cropSize: { width: frameWidth, height: frameHeight },
|
|
1591
|
+
originalSize: { width: frameWidth, height: frameHeight },
|
|
1592
|
+
};
|
|
1593
|
+
result.set(consumer.key, [region]);
|
|
1594
|
+
}
|
|
1595
|
+
return result;
|
|
1596
|
+
}
|
|
1597
|
+
prepareSecondaryFrames(croppedRegions) {
|
|
1598
|
+
return croppedRegions.map((r, i) => ({ ...r.frame, id: String(i), label: r.detection.label }));
|
|
1599
|
+
}
|
|
1600
|
+
async runFaceDetection(croppedRegions) {
|
|
1601
|
+
const facePlugin = this.singlePlugins.get(SensorType.Face);
|
|
1602
|
+
if (!facePlugin || croppedRegions.length === 0)
|
|
1603
|
+
return undefined;
|
|
1604
|
+
const batchResults = await facePlugin.proxy.detectFaces(this.prepareSecondaryFrames(croppedRegions));
|
|
1605
|
+
const allFaces = [];
|
|
1606
|
+
for (let i = 0; i < batchResults.length; i++) {
|
|
1607
|
+
const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
|
|
1608
|
+
for (const face of batchResults[i].detections) {
|
|
1609
|
+
const transformed = this.transformBoxToOriginal(face.box, croppedRegions[i]);
|
|
1610
|
+
allFaces.push({ ...face, box: transformed, parentTrackId });
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
if (allFaces.length === 0)
|
|
1614
|
+
return { detected: false, detections: [] };
|
|
1615
|
+
// NMS only — zone filter is skipped because face crops come from
|
|
1616
|
+
// object detections that already passed zone filtering in process().
|
|
1617
|
+
const deduped = this.pipeline.runNms(allFaces);
|
|
1618
|
+
return { detected: deduped.length > 0, detections: deduped };
|
|
1619
|
+
}
|
|
1620
|
+
async runLicensePlateDetection(croppedRegions) {
|
|
1621
|
+
const lpdPlugin = this.singlePlugins.get(SensorType.LicensePlate);
|
|
1622
|
+
if (!lpdPlugin || croppedRegions.length === 0)
|
|
1623
|
+
return undefined;
|
|
1624
|
+
const batchResults = await lpdPlugin.proxy.detectLicensePlates(this.prepareSecondaryFrames(croppedRegions));
|
|
1625
|
+
const allPlates = [];
|
|
1626
|
+
for (let i = 0; i < batchResults.length; i++) {
|
|
1627
|
+
const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
|
|
1628
|
+
for (const plate of batchResults[i].detections) {
|
|
1629
|
+
allPlates.push({ ...plate, box: this.transformBoxToOriginal(plate.box, croppedRegions[i]), parentTrackId });
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
if (allPlates.length === 0)
|
|
1633
|
+
return { detected: false, detections: [] };
|
|
1634
|
+
// NMS only — zone filter skipped (crops from already-filtered object boxes).
|
|
1635
|
+
const deduped = this.pipeline.runNms(allPlates);
|
|
1636
|
+
return { detected: deduped.length > 0, detections: deduped };
|
|
1637
|
+
}
|
|
1638
|
+
runClassifierDetections(regionMap) {
|
|
1639
|
+
const classifierPlugins = this.multiPlugins.get(SensorType.Classifier);
|
|
1640
|
+
if (!classifierPlugins || classifierPlugins.size === 0)
|
|
1641
|
+
return [];
|
|
1642
|
+
const promises = [];
|
|
1643
|
+
for (const [pluginId, classifierPlugin] of classifierPlugins) {
|
|
1644
|
+
const croppedRegions = regionMap.get(`classifier:${pluginId}`);
|
|
1645
|
+
if (!croppedRegions || croppedRegions.length === 0)
|
|
1646
|
+
continue;
|
|
1647
|
+
const runClassifier = async () => {
|
|
1648
|
+
const batchResults = await classifierPlugin.proxy.detectClassifications(this.prepareSecondaryFrames(croppedRegions));
|
|
1649
|
+
const allDetections = [];
|
|
1650
|
+
for (let i = 0; i < batchResults.length; i++) {
|
|
1651
|
+
const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
|
|
1652
|
+
for (const detection of batchResults[i].detections) {
|
|
1653
|
+
allDetections.push({ ...detection, box: this.transformBoxToOriginal(detection.box, croppedRegions[i]), parentTrackId });
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
if (allDetections.length === 0)
|
|
1657
|
+
return undefined;
|
|
1658
|
+
const deduped = this.pipeline.runNms(allDetections);
|
|
1659
|
+
if (deduped.length === 0)
|
|
1660
|
+
return undefined;
|
|
1661
|
+
return { pluginId, result: { detected: true, detections: deduped } };
|
|
1662
|
+
};
|
|
1663
|
+
promises.push(runClassifier());
|
|
1664
|
+
}
|
|
1665
|
+
return promises;
|
|
1666
|
+
}
|
|
1667
|
+
async runClipDetection(croppedRegions) {
|
|
1668
|
+
const clipPlugin = this.singlePlugins.get(SensorType.Clip);
|
|
1669
|
+
if (!clipPlugin || croppedRegions.length === 0)
|
|
1670
|
+
return undefined;
|
|
1671
|
+
const batchResults = await clipPlugin.proxy.detectEmbeddings(this.prepareSecondaryFrames(croppedRegions));
|
|
1672
|
+
const allEmbeddings = [];
|
|
1673
|
+
for (let i = 0; i < batchResults.length; i++) {
|
|
1674
|
+
if (batchResults[i].embeddings && batchResults[i].embeddings.length > 0) {
|
|
1675
|
+
const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
|
|
1676
|
+
for (const emb of batchResults[i].embeddings) {
|
|
1677
|
+
const transformed = this.transformBoxToOriginal(emb.box, croppedRegions[i]);
|
|
1678
|
+
allEmbeddings.push({ ...emb, box: transformed, parentTrackId });
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
if (allEmbeddings.length === 0)
|
|
1683
|
+
return undefined;
|
|
1684
|
+
const embeddingModel = clipPlugin.modelSpec?.embeddingModel ?? '';
|
|
1685
|
+
return { embeddings: allEmbeddings, embeddingModel };
|
|
1686
|
+
}
|
|
1687
|
+
async generateThumbnails(rawFrame, objectDetections, results) {
|
|
1688
|
+
const thumbnails = [];
|
|
1689
|
+
// Object thumbnails — objectDetections are TrackedDetection[] when tracker ran
|
|
1690
|
+
const objectCrops = await this.frameScaler.cropToJPEG(rawFrame, objectDetections);
|
|
1691
|
+
for (const crop of objectCrops) {
|
|
1692
|
+
const detection = objectDetections[crop.index];
|
|
1693
|
+
if (detection) {
|
|
1694
|
+
thumbnails.push({
|
|
1695
|
+
label: detection.label,
|
|
1696
|
+
score: detection.confidence,
|
|
1697
|
+
jpeg: crop.jpeg,
|
|
1698
|
+
area: detection.box.width * detection.box.height,
|
|
1699
|
+
onEdge: this.isOnEdge(detection.box),
|
|
1700
|
+
trackId: 'trackId' in detection ? detection.trackId : undefined,
|
|
1701
|
+
speed: 'trackSpeed' in detection ? detection.trackSpeed : undefined,
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
if (results.face?.detections) {
|
|
1706
|
+
const faceCrops = await this.frameScaler.cropToJPEG(rawFrame, results.face.detections, { padding: 0.1 });
|
|
1707
|
+
for (const crop of faceCrops) {
|
|
1708
|
+
const detection = results.face.detections[crop.index];
|
|
1709
|
+
if (detection) {
|
|
1710
|
+
// Set thumbnail on the detection itself so enrichSegment can inline it
|
|
1711
|
+
// for unknown faces (needed for face store persistence).
|
|
1712
|
+
detection.thumbnail ??= crop.jpeg;
|
|
1713
|
+
thumbnails.push({
|
|
1714
|
+
label: `face:${detection.identity ?? 'unknown'}`,
|
|
1715
|
+
score: detection.confidence,
|
|
1716
|
+
jpeg: crop.jpeg,
|
|
1717
|
+
area: detection.box.width * detection.box.height,
|
|
1718
|
+
onEdge: this.isOnEdge(detection.box),
|
|
1719
|
+
});
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
if (results.licensePlate?.detections) {
|
|
1724
|
+
const plateCrops = await this.frameScaler.cropToJPEG(rawFrame, results.licensePlate.detections, { padding: 0.1 });
|
|
1725
|
+
for (const crop of plateCrops) {
|
|
1726
|
+
const detection = results.licensePlate.detections[crop.index];
|
|
1727
|
+
if (detection) {
|
|
1728
|
+
thumbnails.push({
|
|
1729
|
+
label: `plate:${detection.plateText ?? 'unknown'}`,
|
|
1730
|
+
score: detection.confidence,
|
|
1731
|
+
jpeg: crop.jpeg,
|
|
1732
|
+
area: detection.box.width * detection.box.height,
|
|
1733
|
+
onEdge: this.isOnEdge(detection.box),
|
|
1734
|
+
});
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
if (results.classifiers) {
|
|
1739
|
+
for (const classifierResult of Object.values(results.classifiers)) {
|
|
1740
|
+
const clsCrops = await this.frameScaler.cropToJPEG(rawFrame, classifierResult.detections);
|
|
1741
|
+
for (const crop of clsCrops) {
|
|
1742
|
+
const detection = classifierResult.detections[crop.index];
|
|
1743
|
+
if (detection) {
|
|
1744
|
+
thumbnails.push({
|
|
1745
|
+
label: `class:${detection.label}`,
|
|
1746
|
+
score: detection.confidence,
|
|
1747
|
+
jpeg: crop.jpeg,
|
|
1748
|
+
area: detection.box.width * detection.box.height,
|
|
1749
|
+
onEdge: this.isOnEdge(detection.box),
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
return thumbnails;
|
|
1756
|
+
}
|
|
1757
|
+
transformBoxToOriginal(box, region) {
|
|
1758
|
+
// box coordinates are normalized (0-1) relative to the scaled frame (e.g. 320x320),
|
|
1759
|
+
// but must be mapped back through the original crop dimensions (before scaling)
|
|
1760
|
+
const pixelX = box.x * region.cropSize.width + region.offset.x;
|
|
1761
|
+
const pixelY = box.y * region.cropSize.height + region.offset.y;
|
|
1762
|
+
const pixelW = box.width * region.cropSize.width;
|
|
1763
|
+
const pixelH = box.height * region.cropSize.height;
|
|
1764
|
+
return {
|
|
1765
|
+
x: pixelX / region.originalSize.width,
|
|
1766
|
+
y: pixelY / region.originalSize.height,
|
|
1767
|
+
width: pixelW / region.originalSize.width,
|
|
1768
|
+
height: pixelH / region.originalSize.height,
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
getNvrProxy() {
|
|
1772
|
+
if (this.nvrProxy)
|
|
1773
|
+
return Promise.resolve(this.nvrProxy);
|
|
1774
|
+
this.nvrProxyPromise ??= this.resolveNvrProxy().finally(() => {
|
|
1775
|
+
this.nvrProxyPromise = undefined;
|
|
1776
|
+
});
|
|
1777
|
+
return this.nvrProxyPromise;
|
|
1778
|
+
}
|
|
1779
|
+
async resolveNvrProxy() {
|
|
1780
|
+
try {
|
|
1781
|
+
const coreManagerProxy = this.proxy.createProxy(NamespaceManager.coreManagerNamespaces().coreManagerRpc);
|
|
1782
|
+
const plugin = await coreManagerProxy.getPlugin('@camera.ui/camera-ui-nvr');
|
|
1783
|
+
if (!plugin) {
|
|
1784
|
+
return undefined;
|
|
1785
|
+
}
|
|
1786
|
+
const ns = NamespaceManager.pluginNamespaces(plugin.id);
|
|
1787
|
+
const connection = this.proxy.createProxy(ns.pluginChildRpc, { isolatedConnection: true });
|
|
1788
|
+
this.nvrProxy = connection.proxy;
|
|
1789
|
+
return this.nvrProxy;
|
|
1790
|
+
}
|
|
1791
|
+
catch (error) {
|
|
1792
|
+
this.logger.error('NVR proxy resolution failed:', error);
|
|
1793
|
+
return undefined;
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
__decorate([
|
|
1798
|
+
RPCMethod,
|
|
1799
|
+
__metadata("design:type", Function),
|
|
1800
|
+
__metadata("design:paramtypes", [Object]),
|
|
1801
|
+
__metadata("design:returntype", Promise)
|
|
1802
|
+
], DetectionCoordinator.prototype, "onSensorAdded", null);
|
|
1803
|
+
__decorate([
|
|
1804
|
+
RPCMethod,
|
|
1805
|
+
__metadata("design:type", Function),
|
|
1806
|
+
__metadata("design:paramtypes", [String]),
|
|
1807
|
+
__metadata("design:returntype", Promise)
|
|
1808
|
+
], DetectionCoordinator.prototype, "onSensorRemoved", null);
|
|
1809
|
+
__decorate([
|
|
1810
|
+
RPCMethod,
|
|
1811
|
+
__metadata("design:type", Function),
|
|
1812
|
+
__metadata("design:paramtypes", [String, Array]),
|
|
1813
|
+
__metadata("design:returntype", void 0)
|
|
1814
|
+
], DetectionCoordinator.prototype, "onSensorCapabilitiesChanged", null);
|
|
1815
|
+
__decorate([
|
|
1816
|
+
RPCMethod,
|
|
1817
|
+
__metadata("design:type", Function),
|
|
1818
|
+
__metadata("design:paramtypes", [String, String, Object]),
|
|
1819
|
+
__metadata("design:returntype", Promise)
|
|
1820
|
+
], DetectionCoordinator.prototype, "reportSensorWrite", null);
|
|
1821
|
+
__decorate([
|
|
1822
|
+
RPCMethod,
|
|
1823
|
+
__metadata("design:type", Function),
|
|
1824
|
+
__metadata("design:paramtypes", [String, String, String, Boolean, Number]),
|
|
1825
|
+
__metadata("design:returntype", void 0)
|
|
1826
|
+
], DetectionCoordinator.prototype, "reportSensorTrigger", null);
|
|
1827
|
+
__decorate([
|
|
1828
|
+
RPCMethod,
|
|
1829
|
+
__metadata("design:type", Function),
|
|
1830
|
+
__metadata("design:paramtypes", [Array]),
|
|
1831
|
+
__metadata("design:returntype", void 0)
|
|
1832
|
+
], DetectionCoordinator.prototype, "reconcileSensorTriggers", null);
|
|
1833
|
+
__decorate([
|
|
1834
|
+
RPCMethod,
|
|
1835
|
+
__metadata("design:type", Function),
|
|
1836
|
+
__metadata("design:paramtypes", [String]),
|
|
1837
|
+
__metadata("design:returntype", Boolean)
|
|
1838
|
+
], DetectionCoordinator.prototype, "hasPlugin", null);
|
|
1839
|
+
DetectionCoordinator = __decorate([
|
|
1840
|
+
RPCClass,
|
|
1841
|
+
__metadata("design:paramtypes", [Object, Object, Function])
|
|
1842
|
+
], DetectionCoordinator);
|
|
1843
|
+
export { DetectionCoordinator };
|
|
1844
|
+
//# sourceMappingURL=detection-coordinator.js.map
|