Initial scaffold: React+TS+Vite frontend, FastAPI backend, config system

This commit is contained in:
root
2026-02-25 21:57:36 -06:00
commit 11eab66e9d
45 changed files with 4508 additions and 0 deletions

83
backend/config.py Normal file
View File

@@ -0,0 +1,83 @@
import yaml
from pathlib import Path
from pydantic import BaseModel
CONFIG_PATH = Path(__file__).parent.parent / "config.yaml"
class Go2RTCConfig(BaseModel):
url: str = "http://localhost:1985"
class FrigateConfig(BaseModel):
url: str = "http://localhost:5000"
class MQTTConfig(BaseModel):
host: str = "localhost"
port: int = 1883
topic_prefix: str = "frigate"
username: str = ""
password: str = ""
class CameraConfig(BaseModel):
name: str
display_name: str = ""
enabled: bool = True
order: int = 0
class AlertConfig(BaseModel):
enabled: bool = False
auto_dismiss_seconds: int = 30
suppression_seconds: int = 60
cameras: list[str] = []
detection_types: list[str] = ["person"]
class GridConfig(BaseModel):
columns: int | None = None
aspect_ratio: str = "16:9"
gap: int = 4
class AppConfig(BaseModel):
title: str = "Camera Viewer"
go2rtc: Go2RTCConfig = Go2RTCConfig()
frigate: FrigateConfig = FrigateConfig()
mqtt: MQTTConfig = MQTTConfig()
cameras: list[CameraConfig] = []
alerts: AlertConfig = AlertConfig()
grid: GridConfig = GridConfig()
_config: AppConfig | None = None
def load_config() -> AppConfig:
global _config
if not CONFIG_PATH.exists():
_config = AppConfig()
return _config
with open(CONFIG_PATH) as f:
data = yaml.safe_load(f) or {}
_config = AppConfig(**data)
return _config
def save_config(config: AppConfig) -> None:
global _config
_config = config
data = config.model_dump()
with open(CONFIG_PATH, "w") as f:
yaml.dump(data, f, default_flow_style=False, sort_keys=False)
def get_config() -> AppConfig:
global _config
if _config is None:
return load_config()
return _config