@camstack/core 0.1.15 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon/addon-api-factory.d.ts +36 -0
- package/dist/addon/addon-api-factory.d.ts.map +1 -0
- package/dist/addon-routes/addon-route-registry.d.ts +38 -0
- package/dist/addon-routes/addon-route-registry.d.ts.map +1 -0
- package/dist/auth/api-key-manager.d.ts +27 -0
- package/dist/auth/api-key-manager.d.ts.map +1 -0
- package/dist/auth/auth-manager.d.ts +47 -0
- package/dist/auth/auth-manager.d.ts.map +1 -0
- package/dist/auth/parse-record.d.ts +19 -0
- package/dist/auth/parse-record.d.ts.map +1 -0
- package/dist/auth/scoped-token-manager.d.ts +18 -0
- package/dist/auth/scoped-token-manager.d.ts.map +1 -0
- package/dist/auth/user-manager.d.ts +34 -0
- package/dist/auth/user-manager.d.ts.map +1 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +54 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts.map +1 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +223 -217
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js.map +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +216 -7
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs.map +1 -1
- package/dist/builtins/addon-pages-aggregator/index.d.ts +2 -0
- package/dist/builtins/addon-pages-aggregator/index.d.ts.map +1 -0
- package/dist/builtins/addon-pages-aggregator/index.js +6 -221
- package/dist/builtins/addon-pages-aggregator/index.mjs +2 -9
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +33 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +199 -197
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js.map +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +192 -7
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs.map +1 -1
- package/dist/builtins/addon-widgets-aggregator/index.d.ts +2 -0
- package/dist/builtins/addon-widgets-aggregator/index.d.ts.map +1 -0
- package/dist/builtins/addon-widgets-aggregator/index.js +6 -201
- package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -9
- package/dist/builtins/alerts/alerts.addon.d.ts +82 -0
- package/dist/builtins/alerts/alerts.addon.d.ts.map +1 -0
- package/dist/builtins/alerts/alerts.addon.js +590 -430
- package/dist/builtins/alerts/alerts.addon.js.map +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +595 -7
- package/dist/builtins/alerts/alerts.addon.mjs.map +1 -1
- package/dist/builtins/alerts/index.d.ts +2 -0
- package/dist/builtins/alerts/index.d.ts.map +1 -0
- package/dist/builtins/alerts/index.js +3 -443
- package/dist/builtins/alerts/index.mjs +2 -8
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts +8 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js +56 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.js.map +1 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs +50 -0
- package/dist/builtins/auth-orchestrator/auth-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/auth-orchestrator/index.d.ts +2 -0
- package/dist/builtins/auth-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/auth-orchestrator/index.js +7 -0
- package/dist/builtins/auth-orchestrator/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +148 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +7639 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js.map +1 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +7627 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +24 -0
- package/dist/builtins/backup-orchestrator/cron-helpers.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts +73 -0
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/download-helpers.d.ts +13 -0
- package/dist/builtins/backup-orchestrator/download-helpers.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/index.d.ts +3 -0
- package/dist/builtins/backup-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/backup-orchestrator/index.js +7 -0
- package/dist/builtins/backup-orchestrator/index.mjs +2 -0
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts +78 -0
- package/dist/builtins/backup-orchestrator/manifest-store.d.ts.map +1 -0
- package/dist/builtins/console-logging/console-destination.d.ts +14 -0
- package/dist/builtins/console-logging/console-destination.d.ts.map +1 -0
- package/dist/builtins/console-logging/console-logging.addon.d.ts +26 -0
- package/dist/builtins/console-logging/console-logging.addon.d.ts.map +1 -0
- package/dist/builtins/console-logging/index.d.ts +4 -0
- package/dist/builtins/console-logging/index.d.ts.map +1 -0
- package/dist/builtins/console-logging/index.js +99 -235
- package/dist/builtins/console-logging/index.js.map +1 -1
- package/dist/builtins/console-logging/index.mjs +95 -9
- package/dist/builtins/console-logging/index.mjs.map +1 -1
- package/dist/builtins/device-manager/device-event-propagator.d.ts +27 -0
- package/dist/builtins/device-manager/device-event-propagator.d.ts.map +1 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts +259 -0
- package/dist/builtins/device-manager/device-manager.addon.d.ts.map +1 -0
- package/dist/builtins/device-manager/device-manager.addon.js +2125 -2127
- package/dist/builtins/device-manager/device-manager.addon.js.map +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +2145 -7
- package/dist/builtins/device-manager/device-manager.addon.mjs.map +1 -1
- package/dist/builtins/device-manager/index.d.ts +3 -0
- package/dist/builtins/device-manager/index.d.ts.map +1 -0
- package/dist/builtins/device-manager/index.js +6 -2156
- package/dist/builtins/device-manager/index.mjs +2 -10
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +45 -0
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts.map +1 -0
- package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +16 -0
- package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts.map +1 -0
- package/dist/builtins/hub-forwarder/index.d.ts +4 -0
- package/dist/builtins/hub-forwarder/index.d.ts.map +1 -0
- package/dist/builtins/hub-forwarder/index.js +150 -291
- package/dist/builtins/hub-forwarder/index.js.map +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +145 -9
- package/dist/builtins/hub-forwarder/index.mjs.map +1 -1
- package/dist/builtins/local-auth/auth-schema.d.ts +12 -0
- package/dist/builtins/local-auth/auth-schema.d.ts.map +1 -0
- package/dist/builtins/local-auth/index.d.ts +2 -0
- package/dist/builtins/local-auth/index.d.ts.map +1 -0
- package/dist/builtins/local-auth/index.js +3 -623
- package/dist/builtins/local-auth/index.mjs +2 -8
- package/dist/builtins/local-auth/local-auth.addon.d.ts +17 -0
- package/dist/builtins/local-auth/local-auth.addon.d.ts.map +1 -0
- package/dist/builtins/local-auth/local-auth.addon.js +6861 -589
- package/dist/builtins/local-auth/local-auth.addon.js.map +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +6883 -7
- package/dist/builtins/local-auth/local-auth.addon.mjs.map +1 -1
- package/dist/builtins/local-network/index.d.ts +3 -0
- package/dist/builtins/local-network/index.d.ts.map +1 -0
- package/dist/builtins/local-network/index.js +9 -0
- package/dist/builtins/local-network/index.mjs +2 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +102 -0
- package/dist/builtins/local-network/local-network.addon.d.ts.map +1 -0
- package/dist/builtins/local-network/local-network.addon.js +404 -0
- package/dist/builtins/local-network/local-network.addon.js.map +1 -0
- package/dist/builtins/local-network/local-network.addon.mjs +392 -0
- package/dist/builtins/local-network/local-network.addon.mjs.map +1 -0
- package/dist/builtins/mesh-orchestrator/index.d.ts +2 -0
- package/dist/builtins/mesh-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/mesh-orchestrator/index.js +7 -0
- package/dist/builtins/mesh-orchestrator/index.mjs +2 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts +9 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js +83 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.js.map +1 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs +77 -0
- package/dist/builtins/mesh-orchestrator/mesh-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/native-metrics/index.d.ts +3 -0
- package/dist/builtins/native-metrics/index.d.ts.map +1 -0
- package/dist/builtins/native-metrics/native-metrics-provider.d.ts +49 -0
- package/dist/builtins/native-metrics/native-metrics-provider.d.ts.map +1 -0
- package/dist/builtins/native-metrics/native-metrics.addon.d.ts +74 -0
- package/dist/builtins/native-metrics/native-metrics.addon.d.ts.map +1 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js +887 -861
- package/dist/builtins/native-metrics/native-metrics.addon.js.map +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +914 -5
- package/dist/builtins/native-metrics/native-metrics.addon.mjs.map +1 -1
- package/dist/builtins/platform-probe/index.d.ts +12 -0
- package/dist/builtins/platform-probe/index.d.ts.map +1 -0
- package/dist/builtins/platform-probe/index.js +539 -0
- package/dist/builtins/platform-probe/index.js.map +1 -0
- package/dist/builtins/platform-probe/index.mjs +530 -0
- package/dist/builtins/platform-probe/index.mjs.map +1 -0
- package/dist/builtins/platform-probe/inference-config-resolver.d.ts +30 -0
- package/dist/builtins/platform-probe/inference-config-resolver.d.ts.map +1 -0
- package/dist/builtins/platform-probe/platform-scorer.d.ts +22 -0
- package/dist/builtins/platform-probe/platform-scorer.d.ts.map +1 -0
- package/dist/builtins/remote-access-orchestrator/index.d.ts +2 -0
- package/dist/builtins/remote-access-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/remote-access-orchestrator/index.js +7 -0
- package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +9 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +72 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js.map +1 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +66 -0
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/snapshot/index.d.ts +3 -0
- package/dist/builtins/snapshot/index.d.ts.map +1 -0
- package/dist/builtins/snapshot/index.js +481 -491
- package/dist/builtins/snapshot/index.js.map +1 -1
- package/dist/builtins/snapshot/index.mjs +475 -464
- package/dist/builtins/snapshot/index.mjs.map +1 -1
- package/dist/builtins/snapshot/snapshot.addon.d.ts +121 -0
- package/dist/builtins/snapshot/snapshot.addon.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/config-store.d.ts +9 -0
- package/dist/builtins/sqlite-storage/config-store.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/device-store.d.ts +24 -0
- package/dist/builtins/sqlite-storage/device-store.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +87 -0
- package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +312 -56
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js.map +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +305 -7
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs.map +1 -1
- package/dist/builtins/sqlite-storage/index.d.ts +12 -0
- package/dist/builtins/sqlite-storage/index.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/index.js +229 -1001
- package/dist/builtins/sqlite-storage/index.js.map +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +268 -26
- package/dist/builtins/sqlite-storage/index.mjs.map +1 -1
- package/dist/builtins/sqlite-storage/integration-registry.d.ts +28 -0
- package/dist/builtins/sqlite-storage/integration-registry.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/settings-store.d.ts +40 -0
- package/dist/builtins/sqlite-storage/settings-store.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sql-schema.d.ts +33 -0
- package/dist/builtins/sqlite-storage/sql-schema.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +94 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +15 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts.map +1 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +586 -653
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js.map +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +582 -7
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs.map +1 -1
- package/dist/builtins/storage-orchestrator/index.d.ts +7 -0
- package/dist/builtins/storage-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/storage-orchestrator/index.js +9 -0
- package/dist/builtins/storage-orchestrator/index.mjs +2 -0
- package/dist/builtins/storage-orchestrator/location-store.d.ts +50 -0
- package/dist/builtins/storage-orchestrator/location-store.d.ts.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +60 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +755 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +746 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +121 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts.map +1 -0
- package/dist/builtins/system-backup/system-backup.service.d.ts +138 -0
- package/dist/builtins/system-backup/system-backup.service.d.ts.map +1 -0
- package/dist/builtins/system-config/index.d.ts +2 -0
- package/dist/builtins/system-config/index.d.ts.map +1 -0
- package/dist/builtins/system-config/index.js +6 -188
- package/dist/builtins/system-config/index.mjs +2 -10
- package/dist/builtins/system-config/system-config.addon.d.ts +11 -0
- package/dist/builtins/system-config/system-config.addon.d.ts.map +1 -0
- package/dist/builtins/system-config/system-config.addon.js +227 -180
- package/dist/builtins/system-config/system-config.addon.js.map +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +226 -7
- package/dist/builtins/system-config/system-config.addon.mjs.map +1 -1
- package/dist/builtins/turn-orchestrator/index.d.ts +2 -0
- package/dist/builtins/turn-orchestrator/index.d.ts.map +1 -0
- package/dist/builtins/turn-orchestrator/index.js +7 -0
- package/dist/builtins/turn-orchestrator/index.mjs +2 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts +10 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.d.ts.map +1 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js +78 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.js.map +1 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs +72 -0
- package/dist/builtins/turn-orchestrator/turn-orchestrator.addon.mjs.map +1 -0
- package/dist/builtins/winston-logging/index.d.ts +4 -0
- package/dist/builtins/winston-logging/index.d.ts.map +1 -0
- package/dist/builtins/winston-logging/index.js +153 -300
- package/dist/builtins/winston-logging/index.js.map +1 -1
- package/dist/builtins/winston-logging/index.mjs +144 -9
- package/dist/builtins/winston-logging/index.mjs.map +1 -1
- package/dist/builtins/winston-logging/winston-destination.d.ts +22 -0
- package/dist/builtins/winston-logging/winston-destination.d.ts.map +1 -0
- package/dist/builtins/winston-logging/winston-logging.addon.d.ts +20 -0
- package/dist/builtins/winston-logging/winston-logging.addon.d.ts.map +1 -0
- package/dist/chunk-C13QxCFV.js +50 -0
- package/dist/chunk-hT5z_Zn9.mjs +35 -0
- package/dist/download/model-download-service.d.ts +42 -0
- package/dist/download/model-download-service.d.ts.map +1 -0
- package/dist/download/model-downloader.d.ts +32 -0
- package/dist/download/model-downloader.d.ts.map +1 -0
- package/dist/events/event-bus.d.ts +11 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/system-event-bus.d.ts +15 -0
- package/dist/events/system-event-bus.d.ts.map +1 -0
- package/dist/feature/feature-manager.d.ts +12 -0
- package/dist/feature/feature-manager.d.ts.map +1 -0
- package/dist/formatter-C-5An4Bl.mjs +164 -0
- package/dist/formatter-C-5An4Bl.mjs.map +1 -0
- package/dist/formatter-Dr_6NNZc.js +169 -0
- package/dist/formatter-Dr_6NNZc.js.map +1 -0
- package/dist/index.d.ts +76 -1696
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7780 -8035
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7707 -2148
- package/dist/index.mjs.map +1 -1
- package/dist/lifecycle/lifecycle-state-machine.d.ts +29 -0
- package/dist/lifecycle/lifecycle-state-machine.d.ts.map +1 -0
- package/dist/logging/formatter.d.ts +31 -0
- package/dist/logging/formatter.d.ts.map +1 -0
- package/dist/logging/log-manager.d.ts +52 -0
- package/dist/logging/log-manager.d.ts.map +1 -0
- package/dist/logging/log-ring-buffer.d.ts +48 -0
- package/dist/logging/log-ring-buffer.d.ts.map +1 -0
- package/dist/logging/scoped-logger.d.ts +18 -0
- package/dist/logging/scoped-logger.d.ts.map +1 -0
- package/dist/network/network-quality.d.ts +12 -0
- package/dist/network/network-quality.d.ts.map +1 -0
- package/dist/notification/notification-service.d.ts +38 -0
- package/dist/notification/notification-service.d.ts.map +1 -0
- package/dist/notification/toast-service.d.ts +23 -0
- package/dist/notification/toast-service.d.ts.map +1 -0
- package/dist/pipeline/engine-manager-resolver.d.ts +16 -0
- package/dist/pipeline/engine-manager-resolver.d.ts.map +1 -0
- package/dist/pipeline/pipeline-runner.d.ts +9 -0
- package/dist/pipeline/pipeline-runner.d.ts.map +1 -0
- package/dist/pipeline/pipeline-validator.d.ts +14 -0
- package/dist/pipeline/pipeline-validator.d.ts.map +1 -0
- package/dist/process/resource-monitor.d.ts +12 -0
- package/dist/process/resource-monitor.d.ts.map +1 -0
- package/dist/python/python-env-manager.d.ts +13 -0
- package/dist/python/python-env-manager.d.ts.map +1 -0
- package/dist/repl/interfaces.d.ts +32 -0
- package/dist/repl/interfaces.d.ts.map +1 -0
- package/dist/repl/repl-engine.d.ts +9 -0
- package/dist/repl/repl-engine.d.ts.map +1 -0
- package/dist/resource-monitor-CmuWlmap.js +76 -0
- package/dist/resource-monitor-CmuWlmap.js.map +1 -0
- package/dist/resource-monitor-DcQdKGYU.mjs +59 -0
- package/dist/resource-monitor-DcQdKGYU.mjs.map +1 -0
- package/dist/storage/fs-storage-backend.d.ts +41 -0
- package/dist/storage/fs-storage-backend.d.ts.map +1 -0
- package/dist/storage/storage-location-manager.d.ts +24 -0
- package/dist/storage/storage-location-manager.d.ts.map +1 -0
- package/dist/storage/storage-manager.d.ts +77 -0
- package/dist/storage/storage-manager.d.ts.map +1 -0
- package/dist/tls/cert-manager.d.ts +27 -0
- package/dist/tls/cert-manager.d.ts.map +1 -0
- package/dist/tls/index.d.ts +2 -0
- package/dist/tls/index.d.ts.map +1 -0
- package/package.json +119 -23
- package/dist/builtins/addon-pages-aggregator/index.js.map +0 -1
- package/dist/builtins/addon-pages-aggregator/index.mjs.map +0 -1
- package/dist/builtins/addon-widgets-aggregator/index.js.map +0 -1
- package/dist/builtins/addon-widgets-aggregator/index.mjs.map +0 -1
- package/dist/builtins/alerts/index.js.map +0 -1
- package/dist/builtins/alerts/index.mjs.map +0 -1
- package/dist/builtins/device-manager/index.js.map +0 -1
- package/dist/builtins/device-manager/index.mjs.map +0 -1
- package/dist/builtins/local-auth/index.js.map +0 -1
- package/dist/builtins/local-auth/index.mjs.map +0 -1
- package/dist/builtins/local-backup/index.js +0 -173
- package/dist/builtins/local-backup/index.js.map +0 -1
- package/dist/builtins/local-backup/index.mjs +0 -10
- package/dist/builtins/local-backup/index.mjs.map +0 -1
- package/dist/builtins/system-config/index.js.map +0 -1
- package/dist/builtins/system-config/index.mjs.map +0 -1
- package/dist/chunk-2CIYKDRN.mjs +0 -1
- package/dist/chunk-2CIYKDRN.mjs.map +0 -1
- package/dist/chunk-2F76X6NL.mjs +0 -136
- package/dist/chunk-2F76X6NL.mjs.map +0 -1
- package/dist/chunk-2QUFBZ7M.mjs +0 -1
- package/dist/chunk-2QUFBZ7M.mjs.map +0 -1
- package/dist/chunk-3BK2Y7GY.mjs +0 -593
- package/dist/chunk-3BK2Y7GY.mjs.map +0 -1
- package/dist/chunk-4OOHFJHT.mjs +0 -421
- package/dist/chunk-4OOHFJHT.mjs.map +0 -1
- package/dist/chunk-4XHB7IHT.mjs +0 -809
- package/dist/chunk-4XHB7IHT.mjs.map +0 -1
- package/dist/chunk-6M2HSSTQ.mjs +0 -98
- package/dist/chunk-6M2HSSTQ.mjs.map +0 -1
- package/dist/chunk-7FI7SQS7.mjs +0 -135
- package/dist/chunk-7FI7SQS7.mjs.map +0 -1
- package/dist/chunk-ED57RCQE.mjs +0 -171
- package/dist/chunk-ED57RCQE.mjs.map +0 -1
- package/dist/chunk-FZN56HGQ.mjs +0 -626
- package/dist/chunk-FZN56HGQ.mjs.map +0 -1
- package/dist/chunk-GL4OOB25.mjs +0 -51
- package/dist/chunk-GL4OOB25.mjs.map +0 -1
- package/dist/chunk-KDG2NTDB.mjs +0 -137
- package/dist/chunk-KDG2NTDB.mjs.map +0 -1
- package/dist/chunk-NRBQWBDM.mjs +0 -191
- package/dist/chunk-NRBQWBDM.mjs.map +0 -1
- package/dist/chunk-O4V246GG.mjs +0 -2137
- package/dist/chunk-O4V246GG.mjs.map +0 -1
- package/dist/chunk-QT57H266.mjs +0 -163
- package/dist/chunk-QT57H266.mjs.map +0 -1
- package/dist/chunk-QX4RH25I.mjs +0 -141
- package/dist/chunk-QX4RH25I.mjs.map +0 -1
- package/dist/chunk-TB562PZX.mjs +0 -86
- package/dist/chunk-TB562PZX.mjs.map +0 -1
- package/dist/chunk-TDYPZXK5.mjs +0 -1
- package/dist/chunk-TDYPZXK5.mjs.map +0 -1
- package/dist/chunk-UJI4LN5P.mjs +0 -36
- package/dist/chunk-UJI4LN5P.mjs.map +0 -1
- package/dist/chunk-W6RTHQGP.mjs +0 -1
- package/dist/chunk-W6RTHQGP.mjs.map +0 -1
- package/dist/chunk-ZELBCPDC.mjs +0 -369
- package/dist/chunk-ZELBCPDC.mjs.map +0 -1
- package/dist/index.d.mts +0 -1696
- package/dist/resource-monitor-UZUGPIAU.mjs +0 -9
- package/dist/resource-monitor-UZUGPIAU.mjs.map +0 -1
- package/dist/storage-location-manager-HFNB3PCS.mjs +0 -7
- package/dist/storage-location-manager-HFNB3PCS.mjs.map +0 -1
|
@@ -1,477 +1,488 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { BaseAddon, DeviceFeature, DeviceType, errMsg, snapshotCapability, streamQualityLabel } from "@camstack/types";
|
|
3
|
+
//#region src/builtins/snapshot/snapshot.addon.ts
|
|
4
|
+
/** Default cache window for non-battery cams (seconds). 10s feels live. */
|
|
5
5
|
var NON_BATTERY_DEFAULT_MAX_AGE_S = 10;
|
|
6
|
+
/** Default cache window for battery cams (seconds). 1h ≈ "don't wake the cam unless asked". */
|
|
6
7
|
var BATTERY_DEFAULT_MAX_AGE_S = 3600;
|
|
8
|
+
/**
|
|
9
|
+
* SnapshotAddon — wrapper over the `snapshot` capability.
|
|
10
|
+
*
|
|
11
|
+
* Activated per-device (toggleable by user; default active). When active,
|
|
12
|
+
* caches fresh snapshots in memory. On cache miss, delegates to the native
|
|
13
|
+
* provider for this device via `ctx.getNativeProvider(snapshotCapability, id)`.
|
|
14
|
+
*
|
|
15
|
+
* No silent fallback — if the native fails, propagate the error up. Stale
|
|
16
|
+
* cache is returned ONLY when the native throws AND a stale entry exists,
|
|
17
|
+
* and the failure is logged so the fallback is never silent.
|
|
18
|
+
*
|
|
19
|
+
* Frame-grab fallback: when the native provider is absent (or returns null /
|
|
20
|
+
* throws), we ask the `stream-broker` capability for the device's RTSP
|
|
21
|
+
* restream URL and pipe one JPEG out of ffmpeg. stream-broker intentionally
|
|
22
|
+
* does NOT expose a `grabFrame` method — the orchestration (native-first,
|
|
23
|
+
* ffmpeg fallback, caching) is this addon's concern; stream-broker only
|
|
24
|
+
* publishes stream endpoints.
|
|
25
|
+
*/
|
|
7
26
|
var SnapshotAddon = class extends BaseAddon {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
if ("snapshotDebug" in patch) {
|
|
396
|
-
next["snapshotDebug"] = patch["snapshotDebug"] === true;
|
|
397
|
-
}
|
|
398
|
-
if ("snapshotMaxAgeS" in patch) {
|
|
399
|
-
const v = patch["snapshotMaxAgeS"];
|
|
400
|
-
if (typeof v === "number" && Number.isFinite(v) && v >= 0) {
|
|
401
|
-
next["snapshotMaxAgeS"] = v;
|
|
402
|
-
} else {
|
|
403
|
-
delete next["snapshotMaxAgeS"];
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
await this.ctx.settings.writeDeviceStore(deviceId, next);
|
|
407
|
-
this.cache.delete(deviceId);
|
|
408
|
-
return { success: true };
|
|
409
|
-
}
|
|
27
|
+
cache = /* @__PURE__ */ new Map();
|
|
28
|
+
constructor() {
|
|
29
|
+
super({ staleTtlMs: 6e4 });
|
|
30
|
+
}
|
|
31
|
+
async onInitialize() {
|
|
32
|
+
this.ctx.logger.info("Snapshot wrapper initialized");
|
|
33
|
+
return [{
|
|
34
|
+
capability: snapshotCapability,
|
|
35
|
+
provider: {
|
|
36
|
+
getSnapshot: (input) => this.getSnapshot(input),
|
|
37
|
+
invalidateCache: (input) => this.invalidateCache(input),
|
|
38
|
+
getDeviceSettingsContribution: (input) => this.buildDeviceSettingsContribution(input.deviceId),
|
|
39
|
+
getDeviceLiveContribution: async () => null,
|
|
40
|
+
applyDeviceSettingsPatch: (input) => this.saveDeviceSettingsPatch(input.deviceId, input.patch),
|
|
41
|
+
getStatus: async (input) => this.getStatus(input.deviceId)
|
|
42
|
+
},
|
|
43
|
+
kind: "wrapper",
|
|
44
|
+
defaultActive: true
|
|
45
|
+
}];
|
|
46
|
+
}
|
|
47
|
+
async onShutdown() {
|
|
48
|
+
this.cache.clear();
|
|
49
|
+
}
|
|
50
|
+
globalSettingsSchema() {
|
|
51
|
+
return this.schema({ sections: [{
|
|
52
|
+
id: "snapshot-cache",
|
|
53
|
+
title: "Snapshot Cache",
|
|
54
|
+
description: "Stale fallback when live capture fails. Per-device freshness is configured under Device → Snapshot → Max cache age.",
|
|
55
|
+
columns: 1,
|
|
56
|
+
fields: [this.field({
|
|
57
|
+
type: "number",
|
|
58
|
+
key: "staleTtlMs",
|
|
59
|
+
label: "Stale fallback TTL (ms)",
|
|
60
|
+
description: "If live capture fails, cached snapshot younger than this is still returned.",
|
|
61
|
+
min: 0,
|
|
62
|
+
max: 36e5,
|
|
63
|
+
step: 1e3,
|
|
64
|
+
default: 6e4
|
|
65
|
+
})]
|
|
66
|
+
}] });
|
|
67
|
+
}
|
|
68
|
+
async getSnapshot(input) {
|
|
69
|
+
const { deviceId, force } = input;
|
|
70
|
+
const meta = await this.lookupDeviceMeta(deviceId);
|
|
71
|
+
const deviceName = meta?.name;
|
|
72
|
+
const isBatteryDevice = meta?.isBattery ?? false;
|
|
73
|
+
const log = this.ctx.logger.withTags({
|
|
74
|
+
deviceId,
|
|
75
|
+
...deviceName ? { deviceName } : {}
|
|
76
|
+
});
|
|
77
|
+
const now = Date.now();
|
|
78
|
+
const hit = this.cache.get(deviceId);
|
|
79
|
+
const prefs = await this.readDeviceSettings(deviceId).catch(() => ({}));
|
|
80
|
+
const rawPref = prefs.snapshotStreamId;
|
|
81
|
+
const effectiveStreamId = input.streamId ?? (rawPref && rawPref !== "auto" ? rawPref : void 0);
|
|
82
|
+
if (prefs.snapshotDebug) log.info("debug on", {
|
|
83
|
+
tags: { deviceId },
|
|
84
|
+
meta: { stream: effectiveStreamId ?? "auto" }
|
|
85
|
+
});
|
|
86
|
+
const defaultMaxAgeS = isBatteryDevice ? BATTERY_DEFAULT_MAX_AGE_S : NON_BATTERY_DEFAULT_MAX_AGE_S;
|
|
87
|
+
const effectiveMaxAgeMs = (typeof prefs.snapshotMaxAgeS === "number" && prefs.snapshotMaxAgeS >= 0 ? prefs.snapshotMaxAgeS : defaultMaxAgeS) * 1e3;
|
|
88
|
+
if (!force && hit && now - hit.ts < effectiveMaxAgeMs) {
|
|
89
|
+
if (prefs.snapshotDebug) log.debug("snapshot: cache hit", {
|
|
90
|
+
tags: { deviceId },
|
|
91
|
+
meta: {
|
|
92
|
+
ageMs: now - hit.ts,
|
|
93
|
+
maxAgeMs: effectiveMaxAgeMs,
|
|
94
|
+
isBattery: isBatteryDevice
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
return hit.data;
|
|
98
|
+
}
|
|
99
|
+
let nativeError = null;
|
|
100
|
+
let nativeAbsent = false;
|
|
101
|
+
try {
|
|
102
|
+
const native = this.ctx.getNativeProvider(snapshotCapability, deviceId);
|
|
103
|
+
if (native) {
|
|
104
|
+
const result = await native.getSnapshot(input);
|
|
105
|
+
if (result) {
|
|
106
|
+
this.cache.set(deviceId, {
|
|
107
|
+
data: result,
|
|
108
|
+
ts: now,
|
|
109
|
+
streamId: effectiveStreamId ?? null
|
|
110
|
+
});
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
} else nativeAbsent = true;
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const msg = errMsg(err);
|
|
116
|
+
if (isAbsentNativeError(msg)) {
|
|
117
|
+
nativeAbsent = true;
|
|
118
|
+
log.debug("native snapshot absent", {
|
|
119
|
+
tags: { deviceId },
|
|
120
|
+
meta: { error: msg }
|
|
121
|
+
});
|
|
122
|
+
} else {
|
|
123
|
+
nativeError = err;
|
|
124
|
+
log.warn("native snapshot failed", {
|
|
125
|
+
tags: { deviceId },
|
|
126
|
+
meta: { error: msg }
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!(isBatteryDevice && nativeAbsent && !await this.hasStreamingBrokerForDevice(deviceId))) try {
|
|
131
|
+
const fallback = await this.grabFrameFromBroker(deviceId, effectiveStreamId);
|
|
132
|
+
if (fallback) {
|
|
133
|
+
this.cache.set(deviceId, {
|
|
134
|
+
data: fallback,
|
|
135
|
+
ts: now,
|
|
136
|
+
streamId: effectiveStreamId ?? null
|
|
137
|
+
});
|
|
138
|
+
return fallback;
|
|
139
|
+
}
|
|
140
|
+
} catch (err) {
|
|
141
|
+
log.warn("stream-broker snapshot fallback failed", {
|
|
142
|
+
tags: { deviceId },
|
|
143
|
+
meta: { error: errMsg(err) }
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
else log.debug("snapshot: skipping broker fallback — battery device with absent native and no streaming broker", { tags: { deviceId } });
|
|
147
|
+
if (hit) {
|
|
148
|
+
const ageMs = now - hit.ts;
|
|
149
|
+
if (ageMs > this.config.staleTtlMs) log.warn("snapshot: all live paths failed — serving stale cache", {
|
|
150
|
+
tags: { deviceId },
|
|
151
|
+
meta: { ageMs }
|
|
152
|
+
});
|
|
153
|
+
return hit.data;
|
|
154
|
+
}
|
|
155
|
+
if (nativeError) throw nativeError;
|
|
156
|
+
if (nativeAbsent) return null;
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Tell apart "native provider isn't registered for this device" from
|
|
161
|
+
* "native provider ran and threw a real error". The former is the steady
|
|
162
|
+
* state for cameras without a vendor snapshot endpoint and should not
|
|
163
|
+
* propagate as a 500; the latter should.
|
|
164
|
+
*/
|
|
165
|
+
/**
|
|
166
|
+
* Pull one JPEG from the device's stream-broker RTSP restream using
|
|
167
|
+
* a short-lived ffmpeg invocation.
|
|
168
|
+
*
|
|
169
|
+
* Stream selection strategy (picks the broker that won't stall):
|
|
170
|
+
* 1. Explicit `preferredStreamId` (user set in per-device settings)
|
|
171
|
+
* — always honoured, even if currently idle. Operator choice
|
|
172
|
+
* wins.
|
|
173
|
+
* 2. Auto: highest-quality broker currently in `streaming` state.
|
|
174
|
+
* This is the whole point — prefer the stream that has active
|
|
175
|
+
* subscribers (usually `low` for detection, but `mid`/`high`
|
|
176
|
+
* if WebRTC is watching) so ffmpeg hits a warm pipe and
|
|
177
|
+
* doesn't race the broker's resume.
|
|
178
|
+
* 3. Fallback: highest-quality enabled entry regardless of status
|
|
179
|
+
* (will wake a suspended broker — retry-guarded against the
|
|
180
|
+
* cold-start error).
|
|
181
|
+
*
|
|
182
|
+
* The stream-broker auto-suspends idle streams on the "no demand"
|
|
183
|
+
* signal; snapshots used to default to `high` which was often the
|
|
184
|
+
* first to go idle, racing every snapshot with a broker resume.
|
|
185
|
+
* Now we ask the orchestrator of streams which one is warm and grab
|
|
186
|
+
* from there.
|
|
187
|
+
*/
|
|
188
|
+
async grabFrameFromBroker(deviceId, preferredStreamId) {
|
|
189
|
+
const dev = await this.ctx.fetchDevice(deviceId);
|
|
190
|
+
const prefix = `${deviceId}/`;
|
|
191
|
+
const [deviceEntries, profileSlots] = await Promise.all([dev.cameraStreams?.getRtspEntries({}) ?? [], dev.cameraStreams?.getBrokerStreams({}) ?? []]);
|
|
192
|
+
const usable = deviceEntries.filter((e) => e.enabled && !!e.url);
|
|
193
|
+
if (usable.length === 0) return null;
|
|
194
|
+
if (preferredStreamId && preferredStreamId !== "auto") {
|
|
195
|
+
const explicit = usable.find((e) => e.brokerId === `${prefix}${preferredStreamId}`);
|
|
196
|
+
if (explicit) {
|
|
197
|
+
const grabbed = await this.runGrabWithResumeRetry(explicit.url, deviceId);
|
|
198
|
+
if (grabbed) return grabbed;
|
|
199
|
+
this.ctx.logger.debug("grabFrame: explicit stream failed — falling back to auto", { meta: { preferredStreamId } });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const ranked = [...usable].sort((a, b) => qualityRank(b.brokerId, prefix) - qualityRank(a.brokerId, prefix));
|
|
203
|
+
const statusByBrokerId = /* @__PURE__ */ new Map();
|
|
204
|
+
for (const slot of profileSlots) statusByBrokerId.set(slot.brokerId, slot.status);
|
|
205
|
+
const statuses = ranked.map((e) => ({
|
|
206
|
+
entry: e,
|
|
207
|
+
status: statusByBrokerId.get(e.brokerId) ?? "idle"
|
|
208
|
+
}));
|
|
209
|
+
const warm = statuses.find((s) => s.status === "streaming");
|
|
210
|
+
if (warm) {
|
|
211
|
+
const grabbed = await this.runGrabWithResumeRetry(warm.entry.url, deviceId);
|
|
212
|
+
if (grabbed) return grabbed;
|
|
213
|
+
}
|
|
214
|
+
for (const { entry } of statuses) {
|
|
215
|
+
const grabbed = await this.runGrabWithResumeRetry(entry.url, deviceId).catch(() => null);
|
|
216
|
+
if (grabbed) return grabbed;
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Ffmpeg grab with one retry on the broker-cold-start error
|
|
222
|
+
* signature. Covers the window between "client connected" and
|
|
223
|
+
* "first keyframe" when a suspended broker resumes.
|
|
224
|
+
*/
|
|
225
|
+
async runGrabWithResumeRetry(url, deviceId) {
|
|
226
|
+
let buf;
|
|
227
|
+
try {
|
|
228
|
+
buf = await runFfmpegFrameGrab(url, 15e3);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
if (isBrokerColdError(errMsg(err))) {
|
|
231
|
+
this.ctx.logger.debug("grabFrame: broker-resume race — retrying in 1500ms", { tags: { deviceId } });
|
|
232
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
233
|
+
buf = await runFfmpegFrameGrab(url, 15e3);
|
|
234
|
+
} else throw err;
|
|
235
|
+
}
|
|
236
|
+
if (buf.length === 0) return null;
|
|
237
|
+
return {
|
|
238
|
+
base64: buf.toString("base64"),
|
|
239
|
+
contentType: "image/jpeg"
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
async invalidateCache(input) {
|
|
243
|
+
this.cache.delete(input.deviceId);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Non-throwing probe of the device's battery cap. Returns true only
|
|
247
|
+
* when a battery native is registered AND its current status says
|
|
248
|
+
* `sleeping: true`. Any error (no provider, native absent, getStatus
|
|
249
|
+
* missing, RPC timeout) is swallowed and treated as "awake" — we'd
|
|
250
|
+
* rather pay a wake-up than strand the caller on a cache that's
|
|
251
|
+
* semantically stale. Debug-logged for observability.
|
|
252
|
+
*/
|
|
253
|
+
/**
|
|
254
|
+
* True when at least one of the device's brokers is actively
|
|
255
|
+
* streaming (status === 'streaming'). Used by the battery-cam guard
|
|
256
|
+
* around `grabFrameFromBroker` to allow the fallback ONLY when
|
|
257
|
+
* grabbing a frame is free (a consumer is already keeping the
|
|
258
|
+
* stream warm). When everything is suspended, the fallback would
|
|
259
|
+
* dial the camera and wake it — defeats the sleeping cache.
|
|
260
|
+
*/
|
|
261
|
+
async hasStreamingBrokerForDevice(deviceId) {
|
|
262
|
+
try {
|
|
263
|
+
return (await (await this.ctx.fetchDevice(deviceId)).cameraStreams?.getBrokerStreams({}) ?? []).some((s) => s.status === "streaming");
|
|
264
|
+
} catch {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Diagnostic status for the `status` auto-injected cap method. Reports
|
|
270
|
+
* the cache bookkeeping for this device — when the last snapshot was
|
|
271
|
+
* captured, how stale the cached image is, its size, and which stream
|
|
272
|
+
* was used. Returns null when the device has never been captured
|
|
273
|
+
* (cache miss) since the addon started.
|
|
274
|
+
*/
|
|
275
|
+
async getStatus(deviceId) {
|
|
276
|
+
const hit = this.cache.get(deviceId);
|
|
277
|
+
if (!hit) return null;
|
|
278
|
+
return {
|
|
279
|
+
lastCapturedAt: hit.ts,
|
|
280
|
+
cacheAgeMs: Date.now() - hit.ts,
|
|
281
|
+
lastBytes: hit.data.base64.length,
|
|
282
|
+
lastStreamId: hit.streamId
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
async readDeviceSettings(deviceId) {
|
|
286
|
+
if (!this.ctx.settings) return {};
|
|
287
|
+
const raw = await this.ctx.settings.readDeviceStore(deviceId);
|
|
288
|
+
const rawAge = raw["snapshotMaxAgeS"];
|
|
289
|
+
const maxAgeS = typeof rawAge === "number" && rawAge >= 0 && Number.isFinite(rawAge) ? rawAge : void 0;
|
|
290
|
+
return {
|
|
291
|
+
snapshotStreamId: typeof raw["snapshotStreamId"] === "string" ? raw["snapshotStreamId"] : void 0,
|
|
292
|
+
snapshotDebug: raw["snapshotDebug"] === true,
|
|
293
|
+
...maxAgeS !== void 0 ? { snapshotMaxAgeS: maxAgeS } : {}
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
async buildDeviceSettingsContribution(deviceId) {
|
|
297
|
+
const meta = await this.lookupDeviceMeta(deviceId);
|
|
298
|
+
if (meta && meta.type !== DeviceType.Camera) return null;
|
|
299
|
+
const current = await this.readDeviceSettings(deviceId);
|
|
300
|
+
const streamOptions = await this.getStreamOptions(deviceId);
|
|
301
|
+
const isBattery = await this.isDeviceBattery(deviceId);
|
|
302
|
+
const defaultMaxAgeS = isBattery ? BATTERY_DEFAULT_MAX_AGE_S : NON_BATTERY_DEFAULT_MAX_AGE_S;
|
|
303
|
+
return { sections: [{
|
|
304
|
+
id: "snapshot-preferences",
|
|
305
|
+
title: "Snapshot",
|
|
306
|
+
tab: "snapshot",
|
|
307
|
+
order: 60,
|
|
308
|
+
fields: [
|
|
309
|
+
{
|
|
310
|
+
type: "select",
|
|
311
|
+
key: "snapshotStreamId",
|
|
312
|
+
label: "Preferred stream",
|
|
313
|
+
description: "Stream used when grabbing a snapshot",
|
|
314
|
+
options: streamOptions,
|
|
315
|
+
required: true,
|
|
316
|
+
value: current.snapshotStreamId || "auto"
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
type: "number",
|
|
320
|
+
key: "snapshotMaxAgeS",
|
|
321
|
+
label: "Max cache age (s)",
|
|
322
|
+
description: `Serve cached snapshot up to this age before re-capturing. Default ${defaultMaxAgeS}s for ${isBattery ? "battery cams (avoids gratuitous wake-ups)" : "non-battery cams (live-feel)"}. The UI refresh button always forces a fresh capture regardless of this value.`,
|
|
323
|
+
min: 0,
|
|
324
|
+
max: 24 * 3600,
|
|
325
|
+
step: 1,
|
|
326
|
+
value: current.snapshotMaxAgeS ?? defaultMaxAgeS
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
type: "boolean",
|
|
330
|
+
key: "snapshotDebug",
|
|
331
|
+
label: "Debug logging",
|
|
332
|
+
description: "Log stream selection and timing details for this device.",
|
|
333
|
+
value: current.snapshotDebug ?? false
|
|
334
|
+
}
|
|
335
|
+
]
|
|
336
|
+
}] };
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Single-trip device lookup against device-manager. Returns the
|
|
340
|
+
* fields the wrapper actually consults — name (logging) + battery
|
|
341
|
+
* flag (cache window + broker-fallback gate). Sourced from the
|
|
342
|
+
* device-manager registry rather than the battery cap so the answer
|
|
343
|
+
* survives a momentarily-unreachable provider (the very condition
|
|
344
|
+
* we're trying to be resilient to).
|
|
345
|
+
*
|
|
346
|
+
* Logged at debug + null return on failure: every call site already
|
|
347
|
+
* has a sensible fallback path (cache hit, conservative default, …),
|
|
348
|
+
* so we don't want a transient device-manager hiccup to throw.
|
|
349
|
+
*/
|
|
350
|
+
async lookupDeviceMeta(deviceId) {
|
|
351
|
+
const api = this.ctx.api;
|
|
352
|
+
if (!api) return null;
|
|
353
|
+
try {
|
|
354
|
+
const found = await api.deviceManager.getDevice.query({ deviceId });
|
|
355
|
+
if (!found) return null;
|
|
356
|
+
const features = found.features ?? [];
|
|
357
|
+
const rawType = found.type;
|
|
358
|
+
return {
|
|
359
|
+
...found.name ? { name: found.name } : {},
|
|
360
|
+
isBattery: features.includes(DeviceFeature.BatteryOperated),
|
|
361
|
+
...rawType ? { type: rawType } : {}
|
|
362
|
+
};
|
|
363
|
+
} catch (err) {
|
|
364
|
+
this.ctx.logger.debug("deviceManager.getDevice failed during snapshot", {
|
|
365
|
+
tags: { deviceId },
|
|
366
|
+
meta: { error: err instanceof Error ? err.message : String(err) }
|
|
367
|
+
});
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/** Settings-UI helper — battery flag drives the default max-age in the field description. */
|
|
372
|
+
async isDeviceBattery(deviceId) {
|
|
373
|
+
return (await this.lookupDeviceMeta(deviceId))?.isBattery ?? false;
|
|
374
|
+
}
|
|
375
|
+
async getStreamOptions(deviceId) {
|
|
376
|
+
const prefix = `${deviceId}/`;
|
|
377
|
+
try {
|
|
378
|
+
return [{
|
|
379
|
+
value: "auto",
|
|
380
|
+
label: "Auto"
|
|
381
|
+
}, ...(await (await this.ctx.fetchDevice(deviceId)).cameraStreams?.getRtspEntries({}) ?? []).filter((e) => e.enabled).map((e) => e.brokerId.slice(prefix.length)).map((id) => ({
|
|
382
|
+
value: id,
|
|
383
|
+
label: streamQualityLabel(id)
|
|
384
|
+
}))];
|
|
385
|
+
} catch (err) {
|
|
386
|
+
this.ctx.logger.error("getStreamOptions failed", {
|
|
387
|
+
tags: { deviceId },
|
|
388
|
+
meta: { error: errMsg(err) }
|
|
389
|
+
});
|
|
390
|
+
return [{
|
|
391
|
+
value: "auto",
|
|
392
|
+
label: "Auto"
|
|
393
|
+
}];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
async saveDeviceSettingsPatch(deviceId, patch) {
|
|
397
|
+
if (!this.ctx.settings) throw new Error("[snapshot] settings store unavailable — cannot persist per-device settings");
|
|
398
|
+
const next = { ...await this.ctx.settings.readDeviceStore(deviceId) };
|
|
399
|
+
if ("snapshotStreamId" in patch) {
|
|
400
|
+
const v = patch["snapshotStreamId"];
|
|
401
|
+
next["snapshotStreamId"] = typeof v === "string" && v.trim().length > 0 ? v.trim() : "";
|
|
402
|
+
}
|
|
403
|
+
if ("snapshotDebug" in patch) next["snapshotDebug"] = patch["snapshotDebug"] === true;
|
|
404
|
+
if ("snapshotMaxAgeS" in patch) {
|
|
405
|
+
const v = patch["snapshotMaxAgeS"];
|
|
406
|
+
if (typeof v === "number" && Number.isFinite(v) && v >= 0) next["snapshotMaxAgeS"] = v;
|
|
407
|
+
else delete next["snapshotMaxAgeS"];
|
|
408
|
+
}
|
|
409
|
+
await this.ctx.settings.writeDeviceStore(deviceId, next);
|
|
410
|
+
this.cache.delete(deviceId);
|
|
411
|
+
return { success: true };
|
|
412
|
+
}
|
|
410
413
|
};
|
|
411
414
|
function isAbsentNativeError(msg) {
|
|
412
|
-
|
|
415
|
+
return msg.includes("no provider for") || msg.includes("no native provider for capability");
|
|
413
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* Quality ordering for broker picker: `high` > `mid` > `low` > other.
|
|
419
|
+
* The streamId is the suffix after `${deviceId}/` in the brokerId.
|
|
420
|
+
* Unknown labels fall through to 0 so they land at the bottom of the
|
|
421
|
+
* preference list without crashing.
|
|
422
|
+
*/
|
|
414
423
|
function qualityRank(brokerId, prefix) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
return 0;
|
|
424
|
+
const normalized = (brokerId.startsWith(prefix) ? brokerId.slice(prefix.length) : brokerId).toLowerCase();
|
|
425
|
+
if (normalized.includes("high") || normalized === "main" || normalized === "hd") return 3;
|
|
426
|
+
if (normalized.includes("mid") || normalized === "medium") return 2;
|
|
427
|
+
if (normalized.includes("low") || normalized === "sub" || normalized === "sd") return 1;
|
|
428
|
+
return 0;
|
|
421
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* Detect ffmpeg failure signatures that indicate the broker wasn't
|
|
432
|
+
* streaming yet when we tried to read its RTSP restream — a race
|
|
433
|
+
* window that closes as soon as the broker lands its first keyframe.
|
|
434
|
+
* Used by `grabFrameFromBroker` to retry once instead of giving up.
|
|
435
|
+
*/
|
|
422
436
|
function isBrokerColdError(msg) {
|
|
423
|
-
|
|
437
|
+
return msg.includes("Invalid data found when processing input") || msg.includes("Error opening input") || msg.includes("Connection refused") || msg.includes("No route to host");
|
|
424
438
|
}
|
|
425
439
|
function runFfmpegFrameGrab(url, timeoutMs) {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
child.on("error", (e) => reject(e));
|
|
471
|
-
});
|
|
440
|
+
return new Promise((resolve, reject) => {
|
|
441
|
+
execFile("ffmpeg", [
|
|
442
|
+
"-loglevel",
|
|
443
|
+
"error",
|
|
444
|
+
"-rtsp_transport",
|
|
445
|
+
"tcp",
|
|
446
|
+
"-fflags",
|
|
447
|
+
"+discardcorrupt",
|
|
448
|
+
"-skip_frame",
|
|
449
|
+
"nokey",
|
|
450
|
+
"-i",
|
|
451
|
+
url,
|
|
452
|
+
"-vf",
|
|
453
|
+
"select=eq(pict_type\\,I)",
|
|
454
|
+
"-vsync",
|
|
455
|
+
"vfr",
|
|
456
|
+
"-frames:v",
|
|
457
|
+
"1",
|
|
458
|
+
"-q:v",
|
|
459
|
+
"3",
|
|
460
|
+
"-f",
|
|
461
|
+
"image2pipe",
|
|
462
|
+
"-vcodec",
|
|
463
|
+
"mjpeg",
|
|
464
|
+
"pipe:1"
|
|
465
|
+
], {
|
|
466
|
+
encoding: "buffer",
|
|
467
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
468
|
+
timeout: timeoutMs
|
|
469
|
+
}, (err, stdout, stderr) => {
|
|
470
|
+
if (err) {
|
|
471
|
+
const errWithMeta = err;
|
|
472
|
+
const stderrText = Buffer.isBuffer(stderr) ? stderr.toString("utf8").trim() : String(stderr ?? "").trim();
|
|
473
|
+
const parts = [err instanceof Error ? err.message : String(err)];
|
|
474
|
+
if (errWithMeta.killed) parts.push("killed=true");
|
|
475
|
+
if (errWithMeta.code !== void 0) parts.push(`code=${String(errWithMeta.code)}`);
|
|
476
|
+
if (errWithMeta.signal) parts.push(`signal=${errWithMeta.signal}`);
|
|
477
|
+
if (stderrText) parts.push(`stderr: ${stderrText.slice(0, 500)}`);
|
|
478
|
+
reject(new Error(parts.join(" — ")));
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
resolve(Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout));
|
|
482
|
+
}).on("error", (e) => reject(e));
|
|
483
|
+
});
|
|
472
484
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
};
|
|
485
|
+
//#endregion
|
|
486
|
+
export { SnapshotAddon, SnapshotAddon as default };
|
|
487
|
+
|
|
477
488
|
//# sourceMappingURL=index.mjs.map
|