from collections import deque from edge.models import Keypoint, BBox from edge.tracking import Track, TrackFrame from edge.events import EventType from edge.detectors.fall import FallDetector, FallConfig from edge.detectors.immobility import ImmobilityWatchdog, ImmobilityConfig from edge.detectors.ghost import GhostIncidentDetector, GhostConfig from edge.detectors.zone import ZoneIntrusionDetector, ZoneConfig from edge.engine import EventEngine, EngineConfig def _lying_kps(): kps = [Keypoint(150, 300, 0.9) for _ in range(17)] kps[5] = Keypoint(100, 300, 0.9); kps[6] = Keypoint(100, 310, 0.9) kps[11] = Keypoint(200, 300, 0.9); kps[12] = Keypoint(200, 310, 0.9) kps[0] = Keypoint(90, 320, 0.9) return kps def _lying_track(track, t): track.frames.append(TrackFrame(t, BBox(90, 290, 210, 320), _lying_kps())) return track def _engine(): return EventEngine( FallDetector(FallConfig(prone_confirm_s=0.5)), ImmobilityWatchdog(ImmobilityConfig(immobile_s=999)), GhostIncidentDetector(GhostConfig()), ZoneIntrusionDetector([], ZoneConfig()), EngineConfig(camera_id="cam-01", cooldown_s=30.0), ) def test_fall_produces_fall_event(): eng = _engine() tr = Track(1, deque(maxlen=90)) _lying_track(tr, 0.0) eng.process([tr], [], now=0.0) _lying_track(tr, 0.6) events = eng.process([tr], [], now=0.6) types = [e.event_type for e in events] assert EventType.FALL in types assert events[0].camera_id == "cam-01" def test_cooldown_suppresses_duplicate(): eng = _engine() tr = Track(1, deque(maxlen=90)) _lying_track(tr, 0.0); eng.process([tr], [], now=0.0) _lying_track(tr, 0.6); eng.process([tr], [], now=0.6) # FALL 1회 _lying_track(tr, 0.7) again = eng.process([tr], [], now=0.7) assert all(e.event_type != EventType.FALL for e in again) def test_allow_cooldown_primitive(): eng = _engine() # EngineConfig(camera_id="cam-01", cooldown_s=30.0) key = ("FALL", 1) assert eng._allow(key, now=0.0) is True # first time allowed assert eng._allow(key, now=5.0) is False # within cooldown -> suppressed assert eng._allow(key, now=40.0) is True # after cooldown_s elapsed -> allowed again # a different key is independent assert eng._allow(("FALL", 2), now=5.0) is True