@camstack/addon-pipeline 1.2.64 → 1.2.65
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/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DkDAcqBW.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BCyIjQkw.mjs} +1 -1
- package/dist/stream-broker/{hostInit-C-peB-6a.mjs → hostInit-DqLdTCfo.mjs} +1 -1
- package/dist/stream-broker/index.js +118 -21
- package/dist/stream-broker/index.mjs +118 -21
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/package.json +1 -1
- package/python/__pycache__/inference_pool.cpython-312.pyc +0 -0
- package/python/__pycache__/inference_pool.cpython-313.pyc +0 -0
- package/python/__pycache__/inference_pool.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_backpressure.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_coreml_cache.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_device_selection.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_layout.cpython-314.pyc +0 -0
- package/python/__pycache__/test_inference_pool_preprocess.cpython-314.pyc +0 -0
- package/python/__pycache__/yamnet_audio.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/__init__.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/_safety.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/arcface.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/clip.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/ctc.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/rfdetr.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/saliency.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/scrfd.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/softmax.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/ssd.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/test_clip.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_clip.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_ctc.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/test_rfdetr.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_saliency.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_saliency.cpython-313-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_softmax.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolo_nms.cpython-312-pytest-9.1.1.pyc +0 -0
- package/python/postprocessors/__pycache__/test_yolo_nms.cpython-39.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yamnet.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-314.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo.cpython-39.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-312.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-313.pyc +0 -0
- package/python/postprocessors/__pycache__/yolo_seg.cpython-314.pyc +0 -0
|
@@ -14700,9 +14700,67 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
14700
14700
|
setProfileMapPersister(persister) {
|
|
14701
14701
|
this.profileMapPersister = persister;
|
|
14702
14702
|
}
|
|
14703
|
-
|
|
14703
|
+
/**
|
|
14704
|
+
* Rehydrate the persisted profile map, then reconcile it against the live
|
|
14705
|
+
* device registry — a blob written before a camera was deleted otherwise
|
|
14706
|
+
* resurrects that camera's slots on every boot.
|
|
14707
|
+
*
|
|
14708
|
+
* Call AFTER `setProfileMapPersister` / `setApiAccess`: the prune persists
|
|
14709
|
+
* what it drops, and reads the registry to decide what to drop.
|
|
14710
|
+
*/
|
|
14711
|
+
async loadPersistedProfileMap(entries) {
|
|
14704
14712
|
this.assignments.clear();
|
|
14705
14713
|
for (const [k, v] of entries) this.assignments.set(k, v);
|
|
14714
|
+
await this.pruneAssignmentsForRemovedDevices();
|
|
14715
|
+
}
|
|
14716
|
+
/**
|
|
14717
|
+
* Drop assignments for devices the registry no longer knows.
|
|
14718
|
+
*
|
|
14719
|
+
* Deletion decided by a fallible read, so every way the read can be WRONG
|
|
14720
|
+
* skips the prune outright (D49): no api yet, a failed enumeration, or an
|
|
14721
|
+
* empty enumeration standing next to persisted assignments — that last one
|
|
14722
|
+
* is device-restore not having run, and believing it would wipe the whole
|
|
14723
|
+
* fleet's slot map on one bad boot. Nothing here is retried: the next boot
|
|
14724
|
+
* reads the same blob, and A3 already removes a device at the moment it is
|
|
14725
|
+
* deleted.
|
|
14726
|
+
*/
|
|
14727
|
+
async pruneAssignmentsForRemovedDevices() {
|
|
14728
|
+
const persistedCount = this.assignments.size;
|
|
14729
|
+
if (persistedCount === 0) return;
|
|
14730
|
+
const api = this.api;
|
|
14731
|
+
if (!api) {
|
|
14732
|
+
this.logger.warn("profile-map prune skipped — no api access", { meta: { persistedCount } });
|
|
14733
|
+
return;
|
|
14734
|
+
}
|
|
14735
|
+
let devices;
|
|
14736
|
+
try {
|
|
14737
|
+
devices = await api.deviceManager.listAll.query({});
|
|
14738
|
+
} catch (err) {
|
|
14739
|
+
this.logger.warn("profile-map prune skipped — deviceManager.listAll failed", { meta: {
|
|
14740
|
+
persistedCount,
|
|
14741
|
+
error: require_dist.errMsg(err)
|
|
14742
|
+
} });
|
|
14743
|
+
return;
|
|
14744
|
+
}
|
|
14745
|
+
if (devices.length === 0) {
|
|
14746
|
+
this.logger.warn("profile-map prune skipped — device enumeration came back empty", { meta: { persistedCount } });
|
|
14747
|
+
return;
|
|
14748
|
+
}
|
|
14749
|
+
const known = new Set(devices.map((d) => d.id));
|
|
14750
|
+
const dropped = [...this.assignments.keys()].filter((deviceId) => !known.has(deviceId));
|
|
14751
|
+
if (dropped.length === 0) {
|
|
14752
|
+
this.logger.debug("profile-map prune: every persisted device still exists", { meta: { persistedCount } });
|
|
14753
|
+
return;
|
|
14754
|
+
}
|
|
14755
|
+
for (const deviceId of dropped) {
|
|
14756
|
+
this.assignments.delete(deviceId);
|
|
14757
|
+
this.logger.debug("profile-map prune dropped a device that no longer exists", { tags: { deviceId } });
|
|
14758
|
+
}
|
|
14759
|
+
this.persistProfileMap();
|
|
14760
|
+
this.logger.info("profile-map prune — dropped assignments for devices that no longer exist", { meta: {
|
|
14761
|
+
dropped,
|
|
14762
|
+
remaining: this.assignments.size
|
|
14763
|
+
} });
|
|
14706
14764
|
}
|
|
14707
14765
|
getRtspRestreamProvider() {
|
|
14708
14766
|
return this.rtspProvider;
|
|
@@ -15146,12 +15204,32 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
15146
15204
|
}
|
|
15147
15205
|
async retractDeviceNow(deviceId, opts) {
|
|
15148
15206
|
const existing = this.cameraStreams.get(deviceId);
|
|
15149
|
-
if (
|
|
15150
|
-
for (const camStreamId of Array.from(existing.keys())) await this.retractCameraStream({
|
|
15207
|
+
if (existing) for (const camStreamId of Array.from(existing.keys())) await this.retractCameraStream({
|
|
15151
15208
|
deviceId,
|
|
15152
15209
|
camStreamId,
|
|
15153
15210
|
preserveAssignment: opts.preserveAssignments === true
|
|
15154
15211
|
});
|
|
15212
|
+
if (opts.purgeAssignments === true) this.purgeDeviceAssignments(deviceId);
|
|
15213
|
+
}
|
|
15214
|
+
/**
|
|
15215
|
+
* Forget a device's profile-slot assignments and persist the shrunk map.
|
|
15216
|
+
*
|
|
15217
|
+
* Reachable only from the PERMANENT-removal path. A deleted device that
|
|
15218
|
+
* keeps its entry stays in `listAllProfileSlots` for the life of the
|
|
15219
|
+
* process AND is written straight back into the persisted `profileMap`
|
|
15220
|
+
* blob, so it returns at every boot — which is how 3217/3218 outlived
|
|
15221
|
+
* their cameras.
|
|
15222
|
+
*/
|
|
15223
|
+
purgeDeviceAssignments(deviceId) {
|
|
15224
|
+
const existing = this.assignments.get(deviceId);
|
|
15225
|
+
if (!existing) return;
|
|
15226
|
+
const profiles = require_dist.CAM_PROFILE_ORDER.filter((profile) => existing.map[profile] !== void 0);
|
|
15227
|
+
this.assignments.delete(deviceId);
|
|
15228
|
+
this.persistProfileMap();
|
|
15229
|
+
this.logger.info("device removed — dropping its profile-slot assignments", {
|
|
15230
|
+
tags: { deviceId },
|
|
15231
|
+
meta: { profiles }
|
|
15232
|
+
});
|
|
15155
15233
|
}
|
|
15156
15234
|
async runDeviceCatalogOperation(deviceId, operation) {
|
|
15157
15235
|
const previous = this.deviceCatalogOperations.get(deviceId) ?? Promise.resolve();
|
|
@@ -33606,6 +33684,17 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
|
|
|
33606
33684
|
});
|
|
33607
33685
|
});
|
|
33608
33686
|
const profileMapState = this.state("profileMap", ProfileMapSchema, {});
|
|
33687
|
+
const profileMapPersister = (assignments) => {
|
|
33688
|
+
const obj = {};
|
|
33689
|
+
for (const [deviceId, assignment] of assignments) obj[`${deviceId}`] = {
|
|
33690
|
+
map: { ...assignment.map },
|
|
33691
|
+
auto: assignment.auto
|
|
33692
|
+
};
|
|
33693
|
+
profileMapState.set(obj).catch((err) => {
|
|
33694
|
+
this.ctx.logger.warn("Failed to persist profile map", { meta: { error: require_dist.errMsg(err) } });
|
|
33695
|
+
});
|
|
33696
|
+
};
|
|
33697
|
+
this.brokerManager.setProfileMapPersister(profileMapPersister);
|
|
33609
33698
|
try {
|
|
33610
33699
|
const obj = await profileMapState.get();
|
|
33611
33700
|
const loaded = /* @__PURE__ */ new Map();
|
|
@@ -33622,22 +33711,11 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
|
|
|
33622
33711
|
auto: val.auto
|
|
33623
33712
|
});
|
|
33624
33713
|
}
|
|
33625
|
-
this.brokerManager.loadPersistedProfileMap(loaded);
|
|
33714
|
+
await this.brokerManager.loadPersistedProfileMap(loaded);
|
|
33626
33715
|
this.ctx.logger.info("Loaded persisted profile map", { meta: { deviceCount: loaded.size } });
|
|
33627
33716
|
} catch (err) {
|
|
33628
33717
|
this.ctx.logger.warn("Failed to load profile map", { meta: { error: require_dist.errMsg(err) } });
|
|
33629
33718
|
}
|
|
33630
|
-
const profileMapPersister = (assignments) => {
|
|
33631
|
-
const obj = {};
|
|
33632
|
-
for (const [deviceId, assignment] of assignments) obj[`${deviceId}`] = {
|
|
33633
|
-
map: { ...assignment.map },
|
|
33634
|
-
auto: assignment.auto
|
|
33635
|
-
};
|
|
33636
|
-
profileMapState.set(obj).catch((err) => {
|
|
33637
|
-
this.ctx.logger.warn("Failed to persist profile map", { meta: { error: require_dist.errMsg(err) } });
|
|
33638
|
-
});
|
|
33639
|
-
};
|
|
33640
|
-
this.brokerManager.setProfileMapPersister(profileMapPersister);
|
|
33641
33719
|
const probeSnapshotsState = this.state("probeSnapshots", ProbedSnapshotMapSchema, {});
|
|
33642
33720
|
this.probeSnapshotsState = probeSnapshotsState;
|
|
33643
33721
|
try {
|
|
@@ -33719,12 +33797,7 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
|
|
|
33719
33797
|
});
|
|
33720
33798
|
this.subscribe({ category: require_dist.EventCategory.DeviceUnregistered }, (event) => {
|
|
33721
33799
|
const deviceId = event.data.deviceId;
|
|
33722
|
-
if (typeof deviceId === "number") this.
|
|
33723
|
-
this.ctx.logger.warn("device retract failed", {
|
|
33724
|
-
tags: { deviceId },
|
|
33725
|
-
meta: { error: require_dist.errMsg(err) }
|
|
33726
|
-
});
|
|
33727
|
-
});
|
|
33800
|
+
if (typeof deviceId === "number") this.handleDeviceRemoved(deviceId);
|
|
33728
33801
|
});
|
|
33729
33802
|
this.subscribe({ category: require_dist.EventCategory.StreamParamsChanged }, (event) => {
|
|
33730
33803
|
const deviceId = event.data.deviceId;
|
|
@@ -33926,6 +33999,30 @@ var StreamBrokerAddon = class extends require_dist.BaseAddon {
|
|
|
33926
33999
|
this.brokerManager = null;
|
|
33927
34000
|
}
|
|
33928
34001
|
/**
|
|
34002
|
+
* A device was PERMANENTLY removed (`DeviceUnregistered`).
|
|
34003
|
+
*
|
|
34004
|
+
* Retracts its cam-streams AND purges its profile-slot assignments.
|
|
34005
|
+
* `preserveAssignments` alone is the provider-restart contract — the streams
|
|
34006
|
+
* come back and the operator's manual slot choices must survive — but a
|
|
34007
|
+
* DELETED device that keeps its assignments stays in `listAllProfileSlots`
|
|
34008
|
+
* for the life of the process and is written straight back into the
|
|
34009
|
+
* persisted `profileMap` blob, so it returns at every boot. Live ids
|
|
34010
|
+
* 3217/3218 outlived their cameras exactly that way.
|
|
34011
|
+
*/
|
|
34012
|
+
async handleDeviceRemoved(deviceId) {
|
|
34013
|
+
try {
|
|
34014
|
+
await this.brokerManager?.retractDevice(deviceId, {
|
|
34015
|
+
preserveAssignments: true,
|
|
34016
|
+
purgeAssignments: true
|
|
34017
|
+
});
|
|
34018
|
+
} catch (err) {
|
|
34019
|
+
this.ctx.logger.warn("device retract failed", {
|
|
34020
|
+
tags: { deviceId },
|
|
34021
|
+
meta: { error: require_dist.errMsg(err) }
|
|
34022
|
+
});
|
|
34023
|
+
}
|
|
34024
|
+
}
|
|
34025
|
+
/**
|
|
33929
34026
|
* Emit one `stream-broker.metrics-snapshot` event per active broker.
|
|
33930
34027
|
* BrokerStats already aggregates everything UI consumers need
|
|
33931
34028
|
* (status, fps, bitrate, codec, subscriber count). Skipped when no
|
|
@@ -14694,9 +14694,67 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
14694
14694
|
setProfileMapPersister(persister) {
|
|
14695
14695
|
this.profileMapPersister = persister;
|
|
14696
14696
|
}
|
|
14697
|
-
|
|
14697
|
+
/**
|
|
14698
|
+
* Rehydrate the persisted profile map, then reconcile it against the live
|
|
14699
|
+
* device registry — a blob written before a camera was deleted otherwise
|
|
14700
|
+
* resurrects that camera's slots on every boot.
|
|
14701
|
+
*
|
|
14702
|
+
* Call AFTER `setProfileMapPersister` / `setApiAccess`: the prune persists
|
|
14703
|
+
* what it drops, and reads the registry to decide what to drop.
|
|
14704
|
+
*/
|
|
14705
|
+
async loadPersistedProfileMap(entries) {
|
|
14698
14706
|
this.assignments.clear();
|
|
14699
14707
|
for (const [k, v] of entries) this.assignments.set(k, v);
|
|
14708
|
+
await this.pruneAssignmentsForRemovedDevices();
|
|
14709
|
+
}
|
|
14710
|
+
/**
|
|
14711
|
+
* Drop assignments for devices the registry no longer knows.
|
|
14712
|
+
*
|
|
14713
|
+
* Deletion decided by a fallible read, so every way the read can be WRONG
|
|
14714
|
+
* skips the prune outright (D49): no api yet, a failed enumeration, or an
|
|
14715
|
+
* empty enumeration standing next to persisted assignments — that last one
|
|
14716
|
+
* is device-restore not having run, and believing it would wipe the whole
|
|
14717
|
+
* fleet's slot map on one bad boot. Nothing here is retried: the next boot
|
|
14718
|
+
* reads the same blob, and A3 already removes a device at the moment it is
|
|
14719
|
+
* deleted.
|
|
14720
|
+
*/
|
|
14721
|
+
async pruneAssignmentsForRemovedDevices() {
|
|
14722
|
+
const persistedCount = this.assignments.size;
|
|
14723
|
+
if (persistedCount === 0) return;
|
|
14724
|
+
const api = this.api;
|
|
14725
|
+
if (!api) {
|
|
14726
|
+
this.logger.warn("profile-map prune skipped — no api access", { meta: { persistedCount } });
|
|
14727
|
+
return;
|
|
14728
|
+
}
|
|
14729
|
+
let devices;
|
|
14730
|
+
try {
|
|
14731
|
+
devices = await api.deviceManager.listAll.query({});
|
|
14732
|
+
} catch (err) {
|
|
14733
|
+
this.logger.warn("profile-map prune skipped — deviceManager.listAll failed", { meta: {
|
|
14734
|
+
persistedCount,
|
|
14735
|
+
error: errMsg(err)
|
|
14736
|
+
} });
|
|
14737
|
+
return;
|
|
14738
|
+
}
|
|
14739
|
+
if (devices.length === 0) {
|
|
14740
|
+
this.logger.warn("profile-map prune skipped — device enumeration came back empty", { meta: { persistedCount } });
|
|
14741
|
+
return;
|
|
14742
|
+
}
|
|
14743
|
+
const known = new Set(devices.map((d) => d.id));
|
|
14744
|
+
const dropped = [...this.assignments.keys()].filter((deviceId) => !known.has(deviceId));
|
|
14745
|
+
if (dropped.length === 0) {
|
|
14746
|
+
this.logger.debug("profile-map prune: every persisted device still exists", { meta: { persistedCount } });
|
|
14747
|
+
return;
|
|
14748
|
+
}
|
|
14749
|
+
for (const deviceId of dropped) {
|
|
14750
|
+
this.assignments.delete(deviceId);
|
|
14751
|
+
this.logger.debug("profile-map prune dropped a device that no longer exists", { tags: { deviceId } });
|
|
14752
|
+
}
|
|
14753
|
+
this.persistProfileMap();
|
|
14754
|
+
this.logger.info("profile-map prune — dropped assignments for devices that no longer exist", { meta: {
|
|
14755
|
+
dropped,
|
|
14756
|
+
remaining: this.assignments.size
|
|
14757
|
+
} });
|
|
14700
14758
|
}
|
|
14701
14759
|
getRtspRestreamProvider() {
|
|
14702
14760
|
return this.rtspProvider;
|
|
@@ -15140,12 +15198,32 @@ var StreamBrokerManager = class StreamBrokerManager {
|
|
|
15140
15198
|
}
|
|
15141
15199
|
async retractDeviceNow(deviceId, opts) {
|
|
15142
15200
|
const existing = this.cameraStreams.get(deviceId);
|
|
15143
|
-
if (
|
|
15144
|
-
for (const camStreamId of Array.from(existing.keys())) await this.retractCameraStream({
|
|
15201
|
+
if (existing) for (const camStreamId of Array.from(existing.keys())) await this.retractCameraStream({
|
|
15145
15202
|
deviceId,
|
|
15146
15203
|
camStreamId,
|
|
15147
15204
|
preserveAssignment: opts.preserveAssignments === true
|
|
15148
15205
|
});
|
|
15206
|
+
if (opts.purgeAssignments === true) this.purgeDeviceAssignments(deviceId);
|
|
15207
|
+
}
|
|
15208
|
+
/**
|
|
15209
|
+
* Forget a device's profile-slot assignments and persist the shrunk map.
|
|
15210
|
+
*
|
|
15211
|
+
* Reachable only from the PERMANENT-removal path. A deleted device that
|
|
15212
|
+
* keeps its entry stays in `listAllProfileSlots` for the life of the
|
|
15213
|
+
* process AND is written straight back into the persisted `profileMap`
|
|
15214
|
+
* blob, so it returns at every boot — which is how 3217/3218 outlived
|
|
15215
|
+
* their cameras.
|
|
15216
|
+
*/
|
|
15217
|
+
purgeDeviceAssignments(deviceId) {
|
|
15218
|
+
const existing = this.assignments.get(deviceId);
|
|
15219
|
+
if (!existing) return;
|
|
15220
|
+
const profiles = CAM_PROFILE_ORDER.filter((profile) => existing.map[profile] !== void 0);
|
|
15221
|
+
this.assignments.delete(deviceId);
|
|
15222
|
+
this.persistProfileMap();
|
|
15223
|
+
this.logger.info("device removed — dropping its profile-slot assignments", {
|
|
15224
|
+
tags: { deviceId },
|
|
15225
|
+
meta: { profiles }
|
|
15226
|
+
});
|
|
15149
15227
|
}
|
|
15150
15228
|
async runDeviceCatalogOperation(deviceId, operation) {
|
|
15151
15229
|
const previous = this.deviceCatalogOperations.get(deviceId) ?? Promise.resolve();
|
|
@@ -33597,6 +33675,17 @@ var StreamBrokerAddon = class extends BaseAddon {
|
|
|
33597
33675
|
});
|
|
33598
33676
|
});
|
|
33599
33677
|
const profileMapState = this.state("profileMap", ProfileMapSchema, {});
|
|
33678
|
+
const profileMapPersister = (assignments) => {
|
|
33679
|
+
const obj = {};
|
|
33680
|
+
for (const [deviceId, assignment] of assignments) obj[`${deviceId}`] = {
|
|
33681
|
+
map: { ...assignment.map },
|
|
33682
|
+
auto: assignment.auto
|
|
33683
|
+
};
|
|
33684
|
+
profileMapState.set(obj).catch((err) => {
|
|
33685
|
+
this.ctx.logger.warn("Failed to persist profile map", { meta: { error: errMsg(err) } });
|
|
33686
|
+
});
|
|
33687
|
+
};
|
|
33688
|
+
this.brokerManager.setProfileMapPersister(profileMapPersister);
|
|
33600
33689
|
try {
|
|
33601
33690
|
const obj = await profileMapState.get();
|
|
33602
33691
|
const loaded = /* @__PURE__ */ new Map();
|
|
@@ -33613,22 +33702,11 @@ var StreamBrokerAddon = class extends BaseAddon {
|
|
|
33613
33702
|
auto: val.auto
|
|
33614
33703
|
});
|
|
33615
33704
|
}
|
|
33616
|
-
this.brokerManager.loadPersistedProfileMap(loaded);
|
|
33705
|
+
await this.brokerManager.loadPersistedProfileMap(loaded);
|
|
33617
33706
|
this.ctx.logger.info("Loaded persisted profile map", { meta: { deviceCount: loaded.size } });
|
|
33618
33707
|
} catch (err) {
|
|
33619
33708
|
this.ctx.logger.warn("Failed to load profile map", { meta: { error: errMsg(err) } });
|
|
33620
33709
|
}
|
|
33621
|
-
const profileMapPersister = (assignments) => {
|
|
33622
|
-
const obj = {};
|
|
33623
|
-
for (const [deviceId, assignment] of assignments) obj[`${deviceId}`] = {
|
|
33624
|
-
map: { ...assignment.map },
|
|
33625
|
-
auto: assignment.auto
|
|
33626
|
-
};
|
|
33627
|
-
profileMapState.set(obj).catch((err) => {
|
|
33628
|
-
this.ctx.logger.warn("Failed to persist profile map", { meta: { error: errMsg(err) } });
|
|
33629
|
-
});
|
|
33630
|
-
};
|
|
33631
|
-
this.brokerManager.setProfileMapPersister(profileMapPersister);
|
|
33632
33710
|
const probeSnapshotsState = this.state("probeSnapshots", ProbedSnapshotMapSchema, {});
|
|
33633
33711
|
this.probeSnapshotsState = probeSnapshotsState;
|
|
33634
33712
|
try {
|
|
@@ -33710,12 +33788,7 @@ var StreamBrokerAddon = class extends BaseAddon {
|
|
|
33710
33788
|
});
|
|
33711
33789
|
this.subscribe({ category: EventCategory.DeviceUnregistered }, (event) => {
|
|
33712
33790
|
const deviceId = event.data.deviceId;
|
|
33713
|
-
if (typeof deviceId === "number") this.
|
|
33714
|
-
this.ctx.logger.warn("device retract failed", {
|
|
33715
|
-
tags: { deviceId },
|
|
33716
|
-
meta: { error: errMsg(err) }
|
|
33717
|
-
});
|
|
33718
|
-
});
|
|
33791
|
+
if (typeof deviceId === "number") this.handleDeviceRemoved(deviceId);
|
|
33719
33792
|
});
|
|
33720
33793
|
this.subscribe({ category: EventCategory.StreamParamsChanged }, (event) => {
|
|
33721
33794
|
const deviceId = event.data.deviceId;
|
|
@@ -33917,6 +33990,30 @@ var StreamBrokerAddon = class extends BaseAddon {
|
|
|
33917
33990
|
this.brokerManager = null;
|
|
33918
33991
|
}
|
|
33919
33992
|
/**
|
|
33993
|
+
* A device was PERMANENTLY removed (`DeviceUnregistered`).
|
|
33994
|
+
*
|
|
33995
|
+
* Retracts its cam-streams AND purges its profile-slot assignments.
|
|
33996
|
+
* `preserveAssignments` alone is the provider-restart contract — the streams
|
|
33997
|
+
* come back and the operator's manual slot choices must survive — but a
|
|
33998
|
+
* DELETED device that keeps its assignments stays in `listAllProfileSlots`
|
|
33999
|
+
* for the life of the process and is written straight back into the
|
|
34000
|
+
* persisted `profileMap` blob, so it returns at every boot. Live ids
|
|
34001
|
+
* 3217/3218 outlived their cameras exactly that way.
|
|
34002
|
+
*/
|
|
34003
|
+
async handleDeviceRemoved(deviceId) {
|
|
34004
|
+
try {
|
|
34005
|
+
await this.brokerManager?.retractDevice(deviceId, {
|
|
34006
|
+
preserveAssignments: true,
|
|
34007
|
+
purgeAssignments: true
|
|
34008
|
+
});
|
|
34009
|
+
} catch (err) {
|
|
34010
|
+
this.ctx.logger.warn("device retract failed", {
|
|
34011
|
+
tags: { deviceId },
|
|
34012
|
+
meta: { error: errMsg(err) }
|
|
34013
|
+
});
|
|
34014
|
+
}
|
|
34015
|
+
}
|
|
34016
|
+
/**
|
|
33920
34017
|
* Emit one `stream-broker.metrics-snapshot` event per active broker.
|
|
33921
34018
|
* BrokerStats already aggregates everything UI consumers need
|
|
33922
34019
|
* (status, fps, bitrate, codec, subscriber count). Skipped when no
|
|
@@ -30,7 +30,7 @@ async function d(e) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function f() {
|
|
33
|
-
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-
|
|
33
|
+
return l ||= d(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BCyIjQkw.mjs")).catch((e) => {
|
|
34
34
|
throw l = void 0, e;
|
|
35
35
|
}), l;
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.65",
|
|
4
4
|
"description": "Pipeline bundle — runner, detection, motion, audio + stream broker. Multi-entry npm package shipping pipeline addons under a single bundle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|