cameras: split camera enable (Вкл) from REC (record-to-disk)
Add a separate `record` field so a camera can be registered but fully
off, or on but not recording:
- enabled (Вкл): camera on/off. Disabled = no go2rtc stream (no live),
no recording; entry is just stored. build_streams/sync_all/reconcile
skip disabled cameras; live grid shows "камера выключена".
- record (REC): write segments to disk. Recorder runs only when
enabled AND record.
Unified POST /api/cameras/{id}/toggle {enabled?, record?} (replaces the
/record endpoint); go2rtc is touched only when `enabled` changes, so
flipping REC doesn't blip live. Camera table gets Вкл + Запись toggle
columns; add/edit forms get both switches.
load_config migrates the old schema (no `record` key): old `enabled`
meant "record" with live always on -> enabled=True, record=old enabled.
VERSION -> 0.0.126.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+24
-13
@@ -18,6 +18,7 @@ class Camera:
|
||||
password: str
|
||||
main_path: str
|
||||
sub_path: str | None = None
|
||||
record: bool = True # REC: писать на диск. enabled — камера вообще включена (live+запись)
|
||||
|
||||
def rtsp_url(self, path: str) -> str:
|
||||
return f"rtsp://{self.user}:{self.password}@{self.ip}:554{path}"
|
||||
@@ -70,27 +71,37 @@ def load_config(path: str | None = None) -> Config:
|
||||
|
||||
storage = Storage(**(raw.get("storage") or {}))
|
||||
live = Live(**(raw.get("live") or {}))
|
||||
cameras = [
|
||||
Camera(
|
||||
id=c["id"],
|
||||
name=c.get("name", c["id"]),
|
||||
enabled=c.get("enabled", True),
|
||||
ip=c["ip"],
|
||||
user=c["user"],
|
||||
password=c["password"],
|
||||
main_path=c["main_path"],
|
||||
sub_path=c.get("sub_path"),
|
||||
)
|
||||
for c in (raw.get("cameras") or [])
|
||||
]
|
||||
cameras = [_camera_from_raw(c) for c in (raw.get("cameras") or [])]
|
||||
return Config(storage=storage, live=live, cameras=cameras)
|
||||
|
||||
|
||||
def _camera_from_raw(c: dict) -> Camera:
|
||||
# Миграция со старой схемы: раньше `enabled` означал «писать на диск» (live был всегда),
|
||||
# отдельного «камера выключена» не существовало. Старый файл (без ключа record) трактуем
|
||||
# так: запись = старый enabled, а сама камера включена. Новый файл (с record) — как есть.
|
||||
if "record" in c:
|
||||
enabled, record = bool(c.get("enabled", True)), bool(c["record"])
|
||||
else:
|
||||
enabled, record = True, bool(c.get("enabled", True))
|
||||
return Camera(
|
||||
id=c["id"],
|
||||
name=c.get("name", c["id"]),
|
||||
enabled=enabled,
|
||||
record=record,
|
||||
ip=c["ip"],
|
||||
user=c["user"],
|
||||
password=c["password"],
|
||||
main_path=c["main_path"],
|
||||
sub_path=c.get("sub_path"),
|
||||
)
|
||||
|
||||
|
||||
def camera_to_yaml(c: Camera) -> dict:
|
||||
return {
|
||||
"id": c.id,
|
||||
"name": c.name,
|
||||
"enabled": c.enabled,
|
||||
"record": c.record,
|
||||
"ip": c.ip,
|
||||
"user": c.user,
|
||||
"password": c.password,
|
||||
|
||||
Reference in New Issue
Block a user