Add pet detection, wildlife, and activity config models
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
aae857ec53
commit
6e3ef1dcdc
@ -1,6 +1,7 @@
|
|||||||
"""Tests for config loading and validation."""
|
"""Tests for config loading and validation."""
|
||||||
|
|
||||||
from vigilar.config import CameraConfig, VigilarConfig
|
from vigilar.config import CameraConfig, VigilarConfig
|
||||||
|
from vigilar.config import PetsConfig, WildlifeThreatMap, WildlifeSizeHeuristics, PetActivityConfig
|
||||||
|
|
||||||
|
|
||||||
def test_default_config():
|
def test_default_config():
|
||||||
@ -33,3 +34,61 @@ def test_camera_sensitivity_bounds():
|
|||||||
import pytest
|
import pytest
|
||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
CameraConfig(id="test", display_name="Test", rtsp_url="rtsp://localhost", motion_sensitivity=1.5)
|
CameraConfig(id="test", display_name="Test", rtsp_url="rtsp://localhost", motion_sensitivity=1.5)
|
||||||
|
|
||||||
|
|
||||||
|
class TestPetsConfig:
|
||||||
|
def test_defaults(self):
|
||||||
|
cfg = PetsConfig()
|
||||||
|
assert cfg.enabled is False
|
||||||
|
assert cfg.model == "yolov8s"
|
||||||
|
assert cfg.confidence_threshold == 0.5
|
||||||
|
assert cfg.pet_id_threshold == 0.7
|
||||||
|
assert cfg.pet_id_low_confidence == 0.5
|
||||||
|
assert cfg.min_training_images == 20
|
||||||
|
assert cfg.crop_retention_days == 7
|
||||||
|
|
||||||
|
def test_custom_values(self):
|
||||||
|
cfg = PetsConfig(enabled=True, model="yolov8m", confidence_threshold=0.6)
|
||||||
|
assert cfg.enabled is True
|
||||||
|
assert cfg.model == "yolov8m"
|
||||||
|
assert cfg.confidence_threshold == 0.6
|
||||||
|
|
||||||
|
|
||||||
|
class TestWildlifeThreatMap:
|
||||||
|
def test_defaults(self):
|
||||||
|
tm = WildlifeThreatMap()
|
||||||
|
assert "bear" in tm.predator
|
||||||
|
assert "bird" in tm.passive
|
||||||
|
|
||||||
|
def test_custom_mapping(self):
|
||||||
|
tm = WildlifeThreatMap(predator=["bear", "wolf"], nuisance=["raccoon"])
|
||||||
|
assert "wolf" in tm.predator
|
||||||
|
assert "raccoon" in tm.nuisance
|
||||||
|
|
||||||
|
|
||||||
|
class TestWildlifeSizeHeuristics:
|
||||||
|
def test_defaults(self):
|
||||||
|
sh = WildlifeSizeHeuristics()
|
||||||
|
assert sh.small == 0.02
|
||||||
|
assert sh.medium == 0.08
|
||||||
|
assert sh.large == 0.15
|
||||||
|
|
||||||
|
|
||||||
|
class TestPetActivityConfig:
|
||||||
|
def test_defaults(self):
|
||||||
|
cfg = PetActivityConfig()
|
||||||
|
assert cfg.daily_digest is True
|
||||||
|
assert cfg.highlight_clips is True
|
||||||
|
assert cfg.zoomie_threshold == 0.8
|
||||||
|
|
||||||
|
|
||||||
|
class TestCameraConfigLocation:
|
||||||
|
def test_default_location_is_interior(self):
|
||||||
|
from vigilar.config import CameraConfig
|
||||||
|
cfg = CameraConfig(id="test", display_name="Test", rtsp_url="rtsp://x")
|
||||||
|
assert cfg.location == "INTERIOR"
|
||||||
|
|
||||||
|
def test_exterior_location(self):
|
||||||
|
from vigilar.config import CameraConfig
|
||||||
|
cfg = CameraConfig(id="test", display_name="Test", rtsp_url="rtsp://x", location="EXTERIOR")
|
||||||
|
assert cfg.location == "EXTERIOR"
|
||||||
|
|||||||
@ -43,6 +43,7 @@ class CameraConfig(BaseModel):
|
|||||||
resolution_capture: list[int] = Field(default_factory=lambda: [1920, 1080])
|
resolution_capture: list[int] = Field(default_factory=lambda: [1920, 1080])
|
||||||
resolution_motion: list[int] = Field(default_factory=lambda: [640, 360])
|
resolution_motion: list[int] = Field(default_factory=lambda: [640, 360])
|
||||||
zones: list["CameraZone"] = Field(default_factory=list)
|
zones: list["CameraZone"] = Field(default_factory=list)
|
||||||
|
location: str = "INTERIOR" # EXTERIOR | INTERIOR | TRANSITION
|
||||||
|
|
||||||
|
|
||||||
# --- Sensor Config ---
|
# --- Sensor Config ---
|
||||||
@ -239,6 +240,48 @@ class HealthConfig(BaseModel):
|
|||||||
daily_digest_time: str = "08:00"
|
daily_digest_time: str = "08:00"
|
||||||
|
|
||||||
|
|
||||||
|
# --- Pet Detection Config ---
|
||||||
|
|
||||||
|
class WildlifeThreatMap(BaseModel):
|
||||||
|
predator: list[str] = Field(default_factory=lambda: ["bear"])
|
||||||
|
nuisance: list[str] = Field(default_factory=list)
|
||||||
|
passive: list[str] = Field(default_factory=lambda: ["bird", "horse", "cow", "sheep"])
|
||||||
|
|
||||||
|
|
||||||
|
class WildlifeSizeHeuristics(BaseModel):
|
||||||
|
small: float = 0.02 # < 2% of frame → nuisance
|
||||||
|
medium: float = 0.08 # 2-8% → predator
|
||||||
|
large: float = 0.15 # > 8% → passive (deer-sized)
|
||||||
|
|
||||||
|
|
||||||
|
class WildlifeConfig(BaseModel):
|
||||||
|
threat_map: WildlifeThreatMap = Field(default_factory=WildlifeThreatMap)
|
||||||
|
size_heuristics: WildlifeSizeHeuristics = Field(default_factory=WildlifeSizeHeuristics)
|
||||||
|
|
||||||
|
|
||||||
|
class PetActivityConfig(BaseModel):
|
||||||
|
daily_digest: bool = True
|
||||||
|
highlight_clips: bool = True
|
||||||
|
zoomie_threshold: float = 0.8
|
||||||
|
|
||||||
|
|
||||||
|
class PetsConfig(BaseModel):
|
||||||
|
enabled: bool = False
|
||||||
|
model: str = "yolov8s"
|
||||||
|
model_path: str = "/var/vigilar/models/yolov8s.pt"
|
||||||
|
confidence_threshold: float = 0.5
|
||||||
|
pet_id_enabled: bool = True
|
||||||
|
pet_id_model_path: str = "/var/vigilar/models/pet_id.pt"
|
||||||
|
pet_id_threshold: float = 0.7
|
||||||
|
pet_id_low_confidence: float = 0.5
|
||||||
|
training_dir: str = "/var/vigilar/pets/training"
|
||||||
|
crop_staging_dir: str = "/var/vigilar/pets/staging"
|
||||||
|
crop_retention_days: int = 7
|
||||||
|
min_training_images: int = 20
|
||||||
|
wildlife: WildlifeConfig = Field(default_factory=WildlifeConfig)
|
||||||
|
activity: PetActivityConfig = Field(default_factory=PetActivityConfig)
|
||||||
|
|
||||||
|
|
||||||
# --- Rule Config ---
|
# --- Rule Config ---
|
||||||
|
|
||||||
class RuleCondition(BaseModel):
|
class RuleCondition(BaseModel):
|
||||||
@ -284,6 +327,7 @@ class VigilarConfig(BaseModel):
|
|||||||
detection: DetectionConfig = Field(default_factory=DetectionConfig)
|
detection: DetectionConfig = Field(default_factory=DetectionConfig)
|
||||||
vehicles: VehicleConfig = Field(default_factory=VehicleConfig)
|
vehicles: VehicleConfig = Field(default_factory=VehicleConfig)
|
||||||
health: HealthConfig = Field(default_factory=HealthConfig)
|
health: HealthConfig = Field(default_factory=HealthConfig)
|
||||||
|
pets: PetsConfig = Field(default_factory=PetsConfig)
|
||||||
cameras: list[CameraConfig] = Field(default_factory=list)
|
cameras: list[CameraConfig] = Field(default_factory=list)
|
||||||
sensors: list[SensorConfig] = Field(default_factory=list)
|
sensors: list[SensorConfig] = Field(default_factory=list)
|
||||||
sensor_gpio: SensorGPIOConfig = Field(default_factory=SensorGPIOConfig, alias="sensors.gpio")
|
sensor_gpio: SensorGPIOConfig = Field(default_factory=SensorGPIOConfig, alias="sensors.gpio")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user