feat(v1): settings camera connection test and preview
Settings tab gains a camera group (host/port/channel/user/masked password), a background connection-test worker that probes one frame off the GUI thread and shows it in a preview, and a save button that writes the structured source to the untracked config.local.json. 60 tests pass; Qt shell compiles and needs a Windows smoke. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -114,6 +114,38 @@ def _resolve_path(config_path: Path, value: Any, field_name: str) -> Path:
|
||||
return (config_path.parent / raw_path).resolve()
|
||||
|
||||
|
||||
def write_local_camera_source(
|
||||
config_path: Path,
|
||||
source_id: str,
|
||||
host: str,
|
||||
port: int,
|
||||
channel: str,
|
||||
username: str,
|
||||
password: str,
|
||||
mode: str = "stream",
|
||||
) -> Path:
|
||||
"""Persist a structured camera source into an untracked local config file.
|
||||
|
||||
Only ever call this on ``config.local.json`` (git-ignored). Credentials are
|
||||
written in plaintext by design of the chosen policy; the public example must
|
||||
never receive them.
|
||||
"""
|
||||
|
||||
path = Path(config_path)
|
||||
data = json.loads(path.read_text(encoding="utf-8")) if path.exists() else {}
|
||||
data["source"] = {
|
||||
"id": str(source_id),
|
||||
"host": str(host),
|
||||
"port": int(port),
|
||||
"channel": str(channel),
|
||||
"username": str(username),
|
||||
"password": str(password),
|
||||
"mode": mode,
|
||||
}
|
||||
path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
return path
|
||||
|
||||
|
||||
def load_config(path: Path) -> AppConfig:
|
||||
"""Load one public/local configuration pair without persisting credentials.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user