mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-26 19:06:34 +00:00
fix(kiosk): cleanup cameras removed from layouts
ONVIF: only subscribe to cameras actually in layout cells, not all bundle cameras. Purge warm camera pool entries for cameras removed from the bundle entirely — immediate stop, no cooling period. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7b9ba13e3a
commit
69e6ce1cbc
1 changed files with 46 additions and 6 deletions
|
|
@ -778,13 +778,25 @@ fn render_bundle(
|
||||||
// Restart GPIO workers (always — even if list is empty, this drops the old set).
|
// Restart GPIO workers (always — even if list is empty, this drops the old set).
|
||||||
gpio::start_workers(&bundle.gpio_bindings, server_url, kiosk_key);
|
gpio::start_workers(&bundle.gpio_bindings, server_url, kiosk_key);
|
||||||
|
|
||||||
// (Re)start ONVIF event subscriptions for all ONVIF cameras in the bundle.
|
// Collect camera IDs actually referenced in layout cells.
|
||||||
// Workers self-terminate when a new start() call replaces the generation.
|
|
||||||
// Prefer per-kiosk encryption key over shared cluster key.
|
|
||||||
let decrypt_key = server::load_encrypt_key().or_else(|| server::load_cluster_key());
|
|
||||||
onvif_events::start(&bundle.cameras, decrypt_key.as_deref(), server_url, kiosk_key);
|
|
||||||
|
|
||||||
let displays = bundle.normalized_displays();
|
let displays = bundle.normalized_displays();
|
||||||
|
let layout_cam_ids: std::collections::HashSet<u32> = displays
|
||||||
|
.iter()
|
||||||
|
.flat_map(|d| d.layouts.iter())
|
||||||
|
.flat_map(|l| l.cells.iter())
|
||||||
|
.filter_map(|c| c.camera_id)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Only subscribe to ONVIF events for cameras in layouts (not all bundle cameras).
|
||||||
|
let layout_cameras: Vec<_> = bundle.cameras.iter()
|
||||||
|
.filter(|c| layout_cam_ids.contains(&c.id))
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
let decrypt_key = server::load_encrypt_key().or_else(|| server::load_cluster_key());
|
||||||
|
onvif_events::start(&layout_cameras, decrypt_key.as_deref(), server_url, kiosk_key);
|
||||||
|
|
||||||
|
// Purge warm camera pool entries for cameras no longer in the bundle at all.
|
||||||
|
purge_removed_cameras(&bundle.cameras);
|
||||||
if displays.is_empty() {
|
if displays.is_empty() {
|
||||||
warn!("bundle has no displays");
|
warn!("bundle has no displays");
|
||||||
show_logo(pairing_window);
|
show_logo(pairing_window);
|
||||||
|
|
@ -1526,6 +1538,34 @@ fn recompute_pool_states(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove warm camera entries for cameras no longer in the bundle.
|
||||||
|
/// Immediately stops pipelines — no cooling period.
|
||||||
|
fn purge_removed_cameras(bundle_cameras: &[crate::bundle::BundleCamera]) {
|
||||||
|
let valid_ids: std::collections::HashSet<u32> = bundle_cameras.iter().map(|c| c.id).collect();
|
||||||
|
let mut to_remove: Vec<PoolKey> = Vec::new();
|
||||||
|
let mut to_stop: Vec<gstreamer::Pipeline> = Vec::new();
|
||||||
|
|
||||||
|
WARM_CAMERAS.with(|w| {
|
||||||
|
let mut warm = w.borrow_mut();
|
||||||
|
for (key, entry) in warm.iter() {
|
||||||
|
if !valid_ids.contains(&key.0) {
|
||||||
|
to_remove.push(*key);
|
||||||
|
to_stop.push(entry.pipeline.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k in &to_remove {
|
||||||
|
warm.remove(k);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for pipe in &to_stop {
|
||||||
|
pipeline::stop(pipe);
|
||||||
|
}
|
||||||
|
if !to_remove.is_empty() {
|
||||||
|
info!("purged {} camera pipelines no longer in bundle", to_remove.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Drop any Cooling entries whose timer has expired. Called from the
|
/// Drop any Cooling entries whose timer has expired. Called from the
|
||||||
/// 1s watchdog tick.
|
/// 1s watchdog tick.
|
||||||
fn expire_cooling_pipelines() {
|
fn expire_cooling_pipelines() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue