Modularize bridge and improve control GUI
This commit is contained in:
@@ -1,72 +1,86 @@
|
||||
# Frigate Camera Control Bridge
|
||||
|
||||
## PL
|
||||
Generic sidecar for a single Frigate instance. The container reads Frigate
|
||||
configuration from `/api/config`, discovers cameras from `go2rtc` and direct
|
||||
`ffmpeg.inputs[].path` stream URLs, then exposes light and siren controls
|
||||
through Home Assistant MQTT Discovery plus an emergency HTTP fallback GUI.
|
||||
|
||||
Ten projekt jest uniwersalnym sidecarem dla pojedynczej instancji Frigate.
|
||||
Kontener pobiera konfiguracje Frigate przez `/api/config`, wykrywa kamery z
|
||||
`go2rtc` oraz z bezposrednich URL-i `ffmpeg.inputs[].path`, a potem wystawia
|
||||
sterowanie swiatlem/syrena przez MQTT Discovery dla Home Assistant i awaryjne
|
||||
GUI HTTP.
|
||||
## Design
|
||||
|
||||
Najwazniejsze zalozenia:
|
||||
- Ten sam obraz obsluguje Podman dzisiaj i Kubernetes pozniej.
|
||||
- Konfiguracja runtime jest przez zmienne srodowiskowe, bez montowania pliku
|
||||
konfiguracyjnego Frigate.
|
||||
- Sidecar czeka na Frigate przy starcie i ponawia odczyt `/api/config`.
|
||||
- Jesli `ffmpeg.inputs[].path` wskazuje na `rtsp://127.0.0.1:8554/...`,
|
||||
sidecar traktuje to jako brame go2rtc i szuka prawdziwego URL-a kamery w
|
||||
- One image works for Podman now and Kubernetes later.
|
||||
- Runtime configuration is environment-based; no Frigate config mount is needed.
|
||||
- The sidecar waits for Frigate startup and retries `/api/config`.
|
||||
- The sidecar periodically refreshes `/api/config`, so added or removed cameras
|
||||
can update MQTT Discovery without a container restart.
|
||||
- On startup it runs a safe `all-off` by default, sets switch entities to `OFF`,
|
||||
and publishes retained MQTT state.
|
||||
- Alarms and lights have default auto-off timers: siren 180s, red-blue/strobe
|
||||
300s, white light 600s. The GUI timer is rendered from a backend timestamp,
|
||||
so page refreshes do not reset it.
|
||||
- Siren `ON` actions require a browser confirmation in the fallback GUI.
|
||||
- If `ffmpeg.inputs[].path` points at `rtsp://127.0.0.1:8554/...`, the sidecar
|
||||
treats it as a go2rtc gateway and resolves the real camera URL from
|
||||
`go2rtc.streams`.
|
||||
- Aktualny Podman uzywa pliku env per sidecar, np.
|
||||
`/etc/frigate-camera-control-bridge/frigate-main.env`.
|
||||
- Kubernetes powinien podawac `MQTT_HOST`, `MQTT_USER`, `MQTT_PASSWORD`,
|
||||
`DEFAULT_CAMERA_USER`, `DEFAULT_CAMERA_PASSWORD` przez `Secret`/`ConfigMap`.
|
||||
- W trybie env brak tych wartosci jest bledem startu; sidecar nie szuka
|
||||
credentiali w Quadletach ani w konfiguracji Frigate.
|
||||
- GUI fallback domyslnie slucha na `5011`, bo `5001` jest juz uzywany przez
|
||||
czesc instancji Frigate.
|
||||
- Jezyki GUI sa standardowym gettext: `locale/<lang>/LC_MESSAGES/*.po` i `.mo`.
|
||||
- If Frigate uses a direct non-loopback stream URL in `ffmpeg.inputs[].path`,
|
||||
the sidecar uses that direct URL and does not resolve go2rtc in parallel.
|
||||
- In env mode, missing MQTT or camera credentials are startup errors; the
|
||||
sidecar does not look up credentials in Quadlets or Frigate config.
|
||||
- The fallback GUI listens on `5011` by default because `5001` may already be
|
||||
used by Frigate.
|
||||
- GUI languages use standard gettext files:
|
||||
`locale/<lang>/LC_MESSAGES/*.po` and `.mo`.
|
||||
|
||||
Podstawowe zmienne:
|
||||
## Environment
|
||||
|
||||
| Zmienna | Znaczenie |
|
||||
| Variable | Meaning |
|
||||
| --- | --- |
|
||||
| `FRIGATE_NAME` | Nazwa tej instancji, np. `frigate-main`. |
|
||||
| `FRIGATE_URL` | URL API Frigate, np. `http://frigate-main.example.test:5000`. |
|
||||
| `MQTT_HOST`, `MQTT_PORT` | Broker MQTT. |
|
||||
| `MQTT_USER`, `MQTT_PASSWORD` | Credentiale MQTT. |
|
||||
| `DEFAULT_CAMERA_USER`, `DEFAULT_CAMERA_PASSWORD` | Domyslne credentiale kamer odkrytych z Frigate. |
|
||||
| `BASE_TOPIC` | Bazowy topic MQTT, np. `frigate_camera_control/frigate-main`. |
|
||||
| `DISCOVERY_PREFIX` | Prefix Home Assistant MQTT Discovery, zwykle `homeassistant`. |
|
||||
| `UI_LANGUAGE` | Domyslny jezyk GUI i encji HA, domyslnie `en`. |
|
||||
| `HTTP_PORT` | Port GUI fallback, domyslnie `5011`. |
|
||||
| `HTTP_TOKEN` | Opcjonalny token dla GUI/API HTTP. |
|
||||
| `SNAPSHOT_RETRY_SECONDS` | Co ile probowac ponownie, gdy migawki brakuja, domyslnie `600`. |
|
||||
| `SNAPSHOT_REFRESH_SECONDS` | Co ile odswiezac poprawnie pobrane migawki, domyslnie `3600`. |
|
||||
| `SNAPSHOT_LIVE_ON_GUI` | Czy pobierac swieza migawke z Frigate przy otwieraniu GUI, domyslnie `true`. |
|
||||
| `FRIGATE_NAME` | Instance name, for example `frigate-main`. |
|
||||
| `FRIGATE_URL` | Frigate API URL, for example `http://frigate-main.example.test:5000`. |
|
||||
| `MQTT_HOST`, `MQTT_PORT` | MQTT broker. |
|
||||
| `MQTT_USER`, `MQTT_PASSWORD` | MQTT credentials. |
|
||||
| `DEFAULT_CAMERA_USER`, `DEFAULT_CAMERA_PASSWORD` | Default credentials for cameras discovered from Frigate. |
|
||||
| `BASE_TOPIC` | MQTT base topic, for example `frigate_camera_control/frigate-main`. |
|
||||
| `DISCOVERY_PREFIX` | Home Assistant MQTT Discovery prefix, usually `homeassistant`. |
|
||||
| `UI_LANGUAGE` | Default GUI and HA entity language, defaults to `en`. |
|
||||
| `HTTP_PORT` | Fallback GUI port, defaults to `5011`. |
|
||||
| `HTTP_TOKEN` | Optional HTTP GUI/API token. |
|
||||
| `FRIGATE_REFRESH_SECONDS` | Frigate config refresh interval, defaults to `300`; `0` disables it. |
|
||||
| `SNAPSHOT_RETRY_SECONDS` | Retry interval while a snapshot is missing, defaults to `600`. |
|
||||
| `SNAPSHOT_REFRESH_SECONDS` | Refresh interval after snapshots are available, defaults to `3600`. |
|
||||
| `SNAPSHOT_LIVE_ON_GUI` | Fetch a fresh Frigate snapshot when the GUI loads, defaults to `true`. |
|
||||
| `STARTUP_ALL_OFF` | Send safe OFF commands during startup, defaults to `true`. |
|
||||
| `AUTO_OFF_SIREN_SECONDS` | Siren auto-off, defaults to `180`. |
|
||||
| `AUTO_OFF_RED_BLUE_SECONDS` | Red-blue/strobe auto-off, defaults to `300`. |
|
||||
| `AUTO_OFF_WHITE_LIGHT_SECONDS` | White-light auto-off, defaults to `600`. |
|
||||
|
||||
Przyklad `/etc/frigate-camera-control-bridge/frigate-main.env`:
|
||||
|
||||
```bash
|
||||
MQTT_HOST=mqtt.example.test
|
||||
MQTT_PORT=1883
|
||||
MQTT_USER=...
|
||||
MQTT_PASSWORD=...
|
||||
DEFAULT_CAMERA_USER=admin
|
||||
DEFAULT_CAMERA_PASSWORD=...
|
||||
```
|
||||
|
||||
Budowanie:
|
||||
## Build
|
||||
|
||||
```bash
|
||||
docker build -t frigate-camera-control-bridge:1.0 .
|
||||
docker build -f Dockerfile.dev -t frigate-camera-control-bridge:dev .
|
||||
```
|
||||
|
||||
Przyklady uruchomienia:
|
||||
- Podman Quadlet: `examples/podman-quadlet/`
|
||||
- Kubernetes sidecar: `examples/kubernetes-sidecar.yaml`
|
||||
## Run
|
||||
|
||||
Lokalny test kontenera:
|
||||
Podman Quadlet example:
|
||||
|
||||
```text
|
||||
examples/podman-quadlet/
|
||||
```
|
||||
|
||||
Docker Compose example:
|
||||
|
||||
```text
|
||||
examples/docker-compose/
|
||||
```
|
||||
|
||||
Kubernetes sidecar example:
|
||||
|
||||
```text
|
||||
examples/kubernetes/
|
||||
```
|
||||
|
||||
Local check:
|
||||
|
||||
```bash
|
||||
docker run --rm \
|
||||
@@ -81,100 +95,7 @@ docker run --rm \
|
||||
frigate-camera-control-bridge:1.0 --check
|
||||
```
|
||||
|
||||
Jezyki:
|
||||
|
||||
1. Dodaj katalog `locale/de/LC_MESSAGES/`.
|
||||
2. Skopiuj `frigate_camera_control_bridge.po` z `locale/en/LC_MESSAGES/`.
|
||||
3. Przetlumacz `msgstr`.
|
||||
4. Uruchom `python3 tools/compile_gettext.py locale`.
|
||||
5. Po przebudowaniu obrazu GUI samo pokaze nowy jezyk.
|
||||
|
||||
Manualne komendy w kontenerze:
|
||||
|
||||
```bash
|
||||
/app/frigate-camera-control-bridge.py --list
|
||||
/app/frigate-camera-control-bridge.py --check
|
||||
/app/frigate-camera-control-bridge.py --all-off
|
||||
/app/frigate-camera-control-bridge.py --action frigate_main_camera_a_red_blue off
|
||||
```
|
||||
|
||||
HTTP fallback:
|
||||
|
||||
```text
|
||||
http://<ip-frigate>:5011/
|
||||
http://<ip-frigate>:5011/?lang=pl
|
||||
http://<ip-frigate>:5011/api/actions
|
||||
http://<ip-frigate>:5011/snapshot/<action_id>.jpg
|
||||
http://<ip-frigate>:5011/healthz
|
||||
http://<ip-frigate>:5011/readyz
|
||||
```
|
||||
|
||||
Jesli ustawiono `HTTP_TOKEN`, dodaj `?token=<token>` albo naglowek
|
||||
`X-Bridge-Token: <token>`.
|
||||
|
||||
## EN
|
||||
|
||||
This project is a generic sidecar for one Frigate instance. The container reads
|
||||
Frigate configuration from `/api/config`, discovers cameras from `go2rtc` and
|
||||
direct `ffmpeg.inputs[].path` stream URLs, then exposes light/siren controls
|
||||
through Home Assistant MQTT Discovery plus an emergency HTTP fallback GUI.
|
||||
|
||||
Main design points:
|
||||
- One image works for Podman now and Kubernetes later.
|
||||
- Runtime configuration is environment-based; no Frigate config mount is needed.
|
||||
- The sidecar waits for Frigate startup and retries `/api/config`.
|
||||
- If `ffmpeg.inputs[].path` points at `rtsp://127.0.0.1:8554/...`, the sidecar
|
||||
treats it as a go2rtc gateway and resolves the real camera URL from
|
||||
`go2rtc.streams`.
|
||||
- Current Podman deployment uses one env file per sidecar, for example:
|
||||
`/etc/frigate-camera-control-bridge/frigate-main.env`.
|
||||
- Kubernetes should pass `MQTT_HOST`, `MQTT_USER`, `MQTT_PASSWORD`,
|
||||
`DEFAULT_CAMERA_USER`, and `DEFAULT_CAMERA_PASSWORD` from a `Secret`/`ConfigMap`.
|
||||
- In env mode, missing values are startup errors; the sidecar does not look up
|
||||
credentials in Quadlets or Frigate config.
|
||||
- The fallback GUI listens on `5011` by default because `5001` is already used
|
||||
by some Frigate instances.
|
||||
- GUI languages use standard gettext files:
|
||||
`locale/<lang>/LC_MESSAGES/*.po` and `.mo`.
|
||||
|
||||
Core env vars:
|
||||
|
||||
| Variable | Meaning |
|
||||
| --- | --- |
|
||||
| `FRIGATE_NAME` | Instance name, for example `frigate-main`. |
|
||||
| `FRIGATE_URL` | Frigate API URL, for example `http://frigate-main.example.test:5000`. |
|
||||
| `MQTT_HOST`, `MQTT_PORT` | MQTT broker. |
|
||||
| `MQTT_USER`, `MQTT_PASSWORD` | MQTT credentials. |
|
||||
| `DEFAULT_CAMERA_USER`, `DEFAULT_CAMERA_PASSWORD` | Default credentials for cameras discovered from Frigate. |
|
||||
| `BASE_TOPIC` | MQTT base topic, for example `frigate_camera_control/frigate-main`. |
|
||||
| `DISCOVERY_PREFIX` | Home Assistant MQTT Discovery prefix, usually `homeassistant`. |
|
||||
| `UI_LANGUAGE` | Default GUI and HA entity language, defaults to `en`. |
|
||||
| `HTTP_PORT` | Fallback GUI port, defaults to `5011`. |
|
||||
| `HTTP_TOKEN` | Optional HTTP GUI/API token. |
|
||||
| `SNAPSHOT_RETRY_SECONDS` | Retry interval while a snapshot is missing, defaults to `600`. |
|
||||
| `SNAPSHOT_REFRESH_SECONDS` | Refresh interval after snapshots are available, defaults to `3600`. |
|
||||
| `SNAPSHOT_LIVE_ON_GUI` | Fetch a fresh Frigate snapshot when the GUI loads, defaults to `true`. |
|
||||
|
||||
Build:
|
||||
|
||||
```bash
|
||||
docker build -t frigate-camera-control-bridge:1.0 .
|
||||
docker build -f Dockerfile.dev -t frigate-camera-control-bridge:dev .
|
||||
```
|
||||
|
||||
Run examples:
|
||||
- Podman Quadlet: `examples/podman-quadlet/`
|
||||
- Kubernetes sidecar: `examples/kubernetes-sidecar.yaml`
|
||||
|
||||
Development container:
|
||||
|
||||
```bash
|
||||
docker run --rm -it \
|
||||
-v "$PWD":/workspace \
|
||||
frigate-camera-control-bridge:dev
|
||||
```
|
||||
|
||||
HTTP fallback:
|
||||
## HTTP GUI
|
||||
|
||||
```text
|
||||
http://<frigate-ip>:5011/
|
||||
@@ -185,10 +106,30 @@ http://<frigate-ip>:5011/healthz
|
||||
http://<frigate-ip>:5011/readyz
|
||||
```
|
||||
|
||||
Kubernetes sidecar notes:
|
||||
If `HTTP_TOKEN` is set, pass `?token=<token>` or the `X-Bridge-Token` header.
|
||||
|
||||
## Manual Commands
|
||||
|
||||
```bash
|
||||
/app/frigate-camera-control-bridge.py --list
|
||||
/app/frigate-camera-control-bridge.py --check
|
||||
/app/frigate-camera-control-bridge.py --all-off
|
||||
/app/frigate-camera-control-bridge.py --action frigate_main_camera_a_red_blue off
|
||||
```
|
||||
|
||||
## Languages
|
||||
|
||||
1. Add `locale/de/LC_MESSAGES/`.
|
||||
2. Copy `frigate_camera_control_bridge.po` from `locale/en/LC_MESSAGES/`.
|
||||
3. Translate `msgstr`.
|
||||
4. Run `python3 tools/compile_gettext.py locale`.
|
||||
5. Rebuild the image. The GUI will discover the new language automatically.
|
||||
|
||||
## Kubernetes Notes
|
||||
|
||||
- Put the bridge container in the same pod as Frigate, or point `FRIGATE_URL`
|
||||
at the Frigate service.
|
||||
- Use `readinessProbe` on `/readyz`.
|
||||
- Pass secrets through env vars from `Secret`.
|
||||
- Keep `/var/lib/frigate-camera-control-bridge` on a small persistent volume if
|
||||
you want stale Home Assistant discovery cleanup to survive pod recreation.
|
||||
stale Home Assistant discovery cleanup should survive pod recreation.
|
||||
|
||||
Reference in New Issue
Block a user