move_detect/edge/runtime.py
유창욱 1a40649d2f feat(edge): multi-camera daemon — run_loop steps N cameras with per-camera zone routing
run_loop now accepts a single runtime or a list; it steps every camera each tick
(one shared clock read), isolates a per-camera step exception, runs the periodic
sync/heartbeat/flush once, and routes zones per camera via a zones_for(cfg, rt)
callback. parse_cameras() reads CAMERAS='backend:device:camera_id,...' (single-camera
fallback when unset) and refuses to yield zero cameras. zones_from_config() gains a
camera_id filter; PipelineRuntime exposes camera_id. Single-camera behavior unchanged.
2026-07-12 23:01:40 +09:00

38 lines
1.5 KiB
Python

from edge.app import run_once
from edge.tracking import IouTracker
from edge.smoothing import TrackSmootherPool
from edge.detectors.fall import FallDetector
from edge.detectors.immobility import ImmobilityWatchdog
from edge.detectors.ghost import GhostIncidentDetector
from edge.detectors.zone import ZoneIntrusionDetector
from edge.engine import EventEngine
from edge.snapshot import RingBuffer, FaceBlurrer, Snapshotter
class PipelineRuntime:
def __init__(self, config, source, pose, sink):
self.config = config
self.camera_id = config.camera_id # for per-camera zone routing (multi-cam)
self.source = source
self.pose = pose
self.sink = sink
self.tracker = IouTracker()
self.pool = TrackSmootherPool()
self.zone_detector = ZoneIntrusionDetector([], config.zone)
self.engine = EventEngine(
FallDetector(config.fall),
ImmobilityWatchdog(config.immobility),
GhostIncidentDetector(config.ghost),
self.zone_detector,
config.engine,
)
self.ring = RingBuffer()
self.snapshotter = Snapshotter(FaceBlurrer())
def step(self, now: float) -> list:
return run_once(self.source, self.pose, self.tracker, self.pool,
self.engine, self.ring, self.snapshotter, self.sink,
now_fn=lambda: now)
def apply_zones(self, zones: list) -> None:
self.zone_detector.zones = list(zones)