Add camera_location filtering to alert profile matching

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Aaron D. Lee 2026-04-03 13:20:37 -04:00
parent e48ba305ea
commit 53daf58c78
2 changed files with 64 additions and 3 deletions

View File

@ -75,3 +75,56 @@ class TestActionForEvent:
action, recipients = get_action_for_event(profile, "person", "front_door")
assert action == "quiet_log"
assert recipients == "none"
class TestPetAlertRouting:
def test_known_pet_exterior_gets_push(self):
rules = [
AlertProfileRule(detection_type="known_pet", camera_location="EXTERIOR",
action="push_and_record", recipients="all"),
AlertProfileRule(detection_type="known_pet", camera_location="INTERIOR",
action="quiet_log", recipients="none"),
]
profile = _make_profile("Away", ["EMPTY"], rules=rules)
action, recipients = get_action_for_event(profile, "known_pet", "front_entrance",
camera_location="EXTERIOR")
assert action == "push_and_record"
def test_known_pet_interior_gets_quiet_log(self):
rules = [
AlertProfileRule(detection_type="known_pet", camera_location="EXTERIOR",
action="push_and_record", recipients="all"),
AlertProfileRule(detection_type="known_pet", camera_location="INTERIOR",
action="quiet_log", recipients="none"),
]
profile = _make_profile("Home", ["ALL_HOME"], rules=rules)
action, recipients = get_action_for_event(profile, "known_pet", "kitchen",
camera_location="INTERIOR")
assert action == "quiet_log"
def test_wildlife_predator_gets_urgent(self):
rules = [
AlertProfileRule(detection_type="wildlife_predator",
action="push_and_record", recipients="all"),
]
profile = _make_profile("Always", ["EMPTY", "ALL_HOME"], rules=rules)
action, _ = get_action_for_event(profile, "wildlife_predator", "front",
camera_location="EXTERIOR")
assert action == "push_and_record"
def test_camera_location_any_matches_all(self):
rules = [
AlertProfileRule(detection_type="wildlife_predator", camera_location="any",
action="push_and_record", recipients="all"),
]
profile = _make_profile("Always", ["EMPTY"], rules=rules)
action, _ = get_action_for_event(profile, "wildlife_predator", "kitchen",
camera_location="INTERIOR")
assert action == "push_and_record"
def test_backward_compatible_without_camera_location(self):
"""Existing calls without camera_location still work."""
rules = [AlertProfileRule(detection_type="person", action="push_and_record", recipients="all")]
profile = _make_profile("Away", ["EMPTY"], rules=rules)
action, _ = get_action_for_event(profile, "person", "front_door")
assert action == "push_and_record"

View File

@ -46,11 +46,19 @@ def get_action_for_event(
profile: AlertProfileConfig,
detection_type: str,
camera_id: str,
camera_location: str | None = None,
) -> tuple[str, str]:
for rule in profile.rules:
if rule.detection_type != detection_type:
continue
if rule.camera_location not in ("any", camera_id):
continue
return rule.action, rule.recipients
# Check camera_location match
if rule.camera_location == "any":
return rule.action, rule.recipients
if rule.camera_location == camera_id:
return rule.action, rule.recipients
if camera_location and rule.camera_location == camera_location:
return rule.action, rule.recipients
if not camera_location and rule.camera_location == "any":
return rule.action, rule.recipients
continue
return "quiet_log", "none"