Phase 1 (Foundation): project skeleton, TOML config + Pydantic validation, MQTT bus wrapper, SQLite schema (9 tables), Click CLI, process supervisor. Phase 2 (Camera): RTSP capture via OpenCV, MOG2 motion detection with configurable sensitivity/zones, adaptive FPS recording (2fps idle/30fps motion) via FFmpeg subprocess, HLS live streaming, pre-motion ring buffer. Phase 3 (Web UI): Flask + Bootstrap 5 dark theme, 6 blueprints, Jinja2 templates (dashboard, kiosk 2x2 grid, events, sensors, recordings, settings), PWA with service worker + Web Push, full admin settings UI with config persistence. Remote Access: WireGuard tunnel configs, nginx reverse proxy with HLS caching + rate limiting, bandwidth-optimized remote HLS stream (426x240 @ 500kbps), DO droplet setup script, certbot TLS. 29 tests passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
166 lines
3.5 KiB
TOML
166 lines
3.5 KiB
TOML
[system]
|
|
name = "Vigilar Home Security"
|
|
timezone = "America/New_York"
|
|
data_dir = "/var/vigilar/data"
|
|
recordings_dir = "/var/vigilar/recordings"
|
|
hls_dir = "/var/vigilar/hls"
|
|
log_level = "INFO"
|
|
# arm_pin_hash = "" # Set via: vigilar config set-pin
|
|
|
|
[mqtt]
|
|
host = "127.0.0.1"
|
|
port = 1883
|
|
|
|
[web]
|
|
host = "0.0.0.0"
|
|
port = 49735
|
|
# tls_cert = "/etc/vigilar/certs/cert.pem"
|
|
# tls_key = "/etc/vigilar/certs/key.pem"
|
|
username = "admin"
|
|
# password_hash = "" # Set via: vigilar config set-password
|
|
|
|
[zigbee2mqtt]
|
|
mqtt_topic_prefix = "zigbee2mqtt"
|
|
|
|
[ups]
|
|
enabled = true
|
|
nut_host = "127.0.0.1"
|
|
nut_port = 3493
|
|
ups_name = "ups"
|
|
poll_interval_s = 30
|
|
low_battery_threshold_pct = 20
|
|
critical_runtime_threshold_s = 300
|
|
shutdown_delay_s = 60
|
|
|
|
[storage]
|
|
encrypt_recordings = true
|
|
key_file = "/etc/vigilar/secrets/storage.key"
|
|
max_disk_usage_gb = 200
|
|
free_space_floor_gb = 10
|
|
|
|
[remote]
|
|
enabled = false
|
|
upload_bandwidth_mbps = 22.0
|
|
remote_hls_resolution = [426, 240]
|
|
remote_hls_fps = 10
|
|
remote_hls_bitrate_kbps = 500
|
|
max_remote_viewers = 4
|
|
tunnel_ip = "10.99.0.2"
|
|
|
|
[alerts.local]
|
|
enabled = true
|
|
syslog = true
|
|
desktop_notify = false
|
|
|
|
[alerts.web_push]
|
|
enabled = true
|
|
vapid_private_key_file = "/etc/vigilar/secrets/vapid_private.pem"
|
|
vapid_claim_email = "mailto:admin@vigilar.local"
|
|
|
|
[alerts.email]
|
|
enabled = false
|
|
# smtp_host = "mail.lan"
|
|
# smtp_port = 587
|
|
# from_addr = "vigilar@home.lan"
|
|
# to_addr = "admin@home.lan"
|
|
# use_tls = true
|
|
|
|
[alerts.webhook]
|
|
enabled = false
|
|
# url = ""
|
|
# secret = ""
|
|
|
|
# --- Cameras ---
|
|
# Add one [[cameras]] block per camera.
|
|
|
|
[[cameras]]
|
|
id = "front_door"
|
|
display_name = "Front Door"
|
|
rtsp_url = "rtsp://192.168.1.101:554/stream1"
|
|
enabled = true
|
|
record_continuous = false
|
|
record_on_motion = true
|
|
motion_sensitivity = 0.7
|
|
motion_min_area_px = 500
|
|
pre_motion_buffer_s = 5
|
|
post_motion_buffer_s = 30
|
|
idle_fps = 2
|
|
motion_fps = 30
|
|
retention_days = 30
|
|
resolution_capture = [1920, 1080]
|
|
resolution_motion = [640, 360]
|
|
|
|
[[cameras]]
|
|
id = "backyard"
|
|
display_name = "Backyard"
|
|
rtsp_url = "rtsp://192.168.1.102:554/stream1"
|
|
enabled = true
|
|
record_continuous = false
|
|
record_on_motion = true
|
|
motion_sensitivity = 0.7
|
|
retention_days = 30
|
|
|
|
[[cameras]]
|
|
id = "side_yard"
|
|
display_name = "Side Yard"
|
|
rtsp_url = "rtsp://192.168.1.103:554/stream1"
|
|
enabled = true
|
|
record_on_motion = true
|
|
motion_sensitivity = 0.7
|
|
retention_days = 30
|
|
|
|
[[cameras]]
|
|
id = "garage"
|
|
display_name = "Garage"
|
|
rtsp_url = "rtsp://192.168.1.104:554/stream1"
|
|
enabled = true
|
|
record_on_motion = true
|
|
motion_sensitivity = 0.7
|
|
retention_days = 30
|
|
|
|
# --- Sensors ---
|
|
# Add one [[sensors]] block per sensor.
|
|
|
|
[[sensors]]
|
|
id = "front_door_contact"
|
|
display_name = "Front Door Contact"
|
|
type = "CONTACT"
|
|
protocol = "ZIGBEE"
|
|
device_address = "0x00158d0001a2b3c4"
|
|
location = "Front Door"
|
|
|
|
[[sensors]]
|
|
id = "pir_living_room"
|
|
display_name = "Living Room PIR"
|
|
type = "MOTION"
|
|
protocol = "ZIGBEE"
|
|
device_address = "0x00158d0001deadbe"
|
|
location = "Living Room"
|
|
|
|
[sensors.gpio]
|
|
bounce_time_ms = 50
|
|
|
|
# --- Rules ---
|
|
|
|
[[rules]]
|
|
id = "intruder_alert"
|
|
description = "Motion detected when armed away"
|
|
conditions = [
|
|
{type = "arm_state", value = "ARMED_AWAY"},
|
|
{type = "sensor_event", sensor_id = "pir_living_room", event = "MOTION_ACTIVE"},
|
|
]
|
|
logic = "AND"
|
|
actions = ["alert_all", "record_all_cameras"]
|
|
cooldown_s = 120
|
|
|
|
[[rules]]
|
|
id = "door_opened_armed"
|
|
description = "Door contact opened while armed"
|
|
conditions = [
|
|
{type = "arm_state", value = "ARMED_AWAY"},
|
|
{type = "sensor_event", sensor_id = "front_door_contact", event = "CONTACT_OPEN"},
|
|
]
|
|
logic = "AND"
|
|
actions = ["alert_all"]
|
|
cooldown_s = 60
|