Differentiate PET_ESCAPE and UNKNOWN_ANIMAL events by zone and identity
Replace the flat pet/detected handler with context-aware classification: unknown animals (no pet_id) → UNKNOWN_ANIMAL/WARNING, known pets in exterior/transition zones → PET_ESCAPE/ALERT, known pets indoors → PET_DETECTED/INFO. Adds four new unit tests covering all three paths. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
713d16d445
commit
c77f732ac7
@ -340,12 +340,60 @@ class TestPetEventClassification:
|
|||||||
processor = EventProcessor.__new__(EventProcessor)
|
processor = EventProcessor.__new__(EventProcessor)
|
||||||
etype, sev, source = processor._classify_event(
|
etype, sev, source = processor._classify_event(
|
||||||
"vigilar/camera/kitchen/pet/detected",
|
"vigilar/camera/kitchen/pet/detected",
|
||||||
{"pet_name": "Angel", "confidence": 0.92},
|
{"pet_id": "p1", "pet_name": "Angel", "confidence": 0.92, "camera_location": "INTERIOR"}, # noqa: E501
|
||||||
)
|
)
|
||||||
assert etype == EventType.PET_DETECTED
|
assert etype == EventType.PET_DETECTED
|
||||||
assert sev == Severity.INFO
|
assert sev == Severity.INFO
|
||||||
assert source == "kitchen"
|
assert source == "kitchen"
|
||||||
|
|
||||||
|
def test_pet_escape_exterior(self):
|
||||||
|
"""Known pet in exterior zone → PET_ESCAPE/ALERT."""
|
||||||
|
from vigilar.events.processor import EventProcessor
|
||||||
|
from vigilar.constants import EventType, Severity
|
||||||
|
processor = EventProcessor.__new__(EventProcessor)
|
||||||
|
etype, sev, source = processor._classify_event(
|
||||||
|
"vigilar/camera/front/pet/detected",
|
||||||
|
{"pet_id": "p1", "pet_name": "Angel", "camera_location": "EXTERIOR"},
|
||||||
|
)
|
||||||
|
assert etype == EventType.PET_ESCAPE
|
||||||
|
assert sev == Severity.ALERT
|
||||||
|
|
||||||
|
def test_pet_escape_transition(self):
|
||||||
|
"""Known pet in transition zone → PET_ESCAPE/ALERT."""
|
||||||
|
from vigilar.events.processor import EventProcessor
|
||||||
|
from vigilar.constants import EventType, Severity
|
||||||
|
processor = EventProcessor.__new__(EventProcessor)
|
||||||
|
etype, sev, source = processor._classify_event(
|
||||||
|
"vigilar/camera/garage/pet/detected",
|
||||||
|
{"pet_id": "p1", "pet_name": "Milo", "camera_location": "TRANSITION"},
|
||||||
|
)
|
||||||
|
assert etype == EventType.PET_ESCAPE
|
||||||
|
assert sev == Severity.ALERT
|
||||||
|
|
||||||
|
def test_unknown_animal(self):
|
||||||
|
"""No pet_id → UNKNOWN_ANIMAL/WARNING."""
|
||||||
|
from vigilar.events.processor import EventProcessor
|
||||||
|
from vigilar.constants import EventType, Severity
|
||||||
|
processor = EventProcessor.__new__(EventProcessor)
|
||||||
|
etype, sev, source = processor._classify_event(
|
||||||
|
"vigilar/camera/kitchen/pet/detected",
|
||||||
|
{"species": "cat", "camera_location": "INTERIOR"},
|
||||||
|
)
|
||||||
|
assert etype == EventType.UNKNOWN_ANIMAL
|
||||||
|
assert sev == Severity.WARNING
|
||||||
|
|
||||||
|
def test_known_pet_interior(self):
|
||||||
|
"""Known pet in interior → PET_DETECTED/INFO."""
|
||||||
|
from vigilar.events.processor import EventProcessor
|
||||||
|
from vigilar.constants import EventType, Severity
|
||||||
|
processor = EventProcessor.__new__(EventProcessor)
|
||||||
|
etype, sev, source = processor._classify_event(
|
||||||
|
"vigilar/camera/kitchen/pet/detected",
|
||||||
|
{"pet_id": "p1", "pet_name": "Angel", "camera_location": "INTERIOR"},
|
||||||
|
)
|
||||||
|
assert etype == EventType.PET_DETECTED
|
||||||
|
assert sev == Severity.INFO
|
||||||
|
|
||||||
def test_wildlife_predator_event(self):
|
def test_wildlife_predator_event(self):
|
||||||
from vigilar.events.processor import EventProcessor
|
from vigilar.events.processor import EventProcessor
|
||||||
from vigilar.constants import EventType, Severity
|
from vigilar.constants import EventType, Severity
|
||||||
|
|||||||
@ -129,6 +129,15 @@ class EventProcessor:
|
|||||||
|
|
||||||
# Pet detection
|
# Pet detection
|
||||||
if suffix == "pet/detected":
|
if suffix == "pet/detected":
|
||||||
|
pet_id = payload.get("pet_id")
|
||||||
|
camera_location = payload.get("camera_location", "INTERIOR")
|
||||||
|
|
||||||
|
if not pet_id:
|
||||||
|
return EventType.UNKNOWN_ANIMAL, Severity.WARNING, camera_id
|
||||||
|
|
||||||
|
if camera_location in ("EXTERIOR", "TRANSITION"):
|
||||||
|
return EventType.PET_ESCAPE, Severity.ALERT, camera_id
|
||||||
|
|
||||||
return EventType.PET_DETECTED, Severity.INFO, camera_id
|
return EventType.PET_DETECTED, Severity.INFO, camera_id
|
||||||
|
|
||||||
# Wildlife detection — severity depends on threat_level in payload
|
# Wildlife detection — severity depends on threat_level in payload
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user