ci / smoke (push) Canceled after 0s
Legacy manual batch start locked until plate entered: - POST /api/batch/start manual branch returns 400 missing_plate when plate empty (strip + uppercase, no format regex) - operator + monitoring start modals gain required plate input, confirm button disabled until filled - operator plate tile also shows for manual batches (was do_manual only) - do_manual unchanged (plate from DOs)
152 lines
8.2 KiB
Markdown
152 lines
8.2 KiB
Markdown
# Configuration
|
||
|
||
Canonical source: **`config.yaml`** (repo root) — stream, models, counting knobs,
|
||
batch, output paths, camera. Loaded once at startup via `src/config_loader.py`
|
||
(stdlib dataclasses + pyyaml, no heavy deps). Secrets & deployment-only values
|
||
stay in `.env`. Zone polygons stay in `zones.json`. Tracker hyperparams stay in
|
||
`cfg/tracker.yaml`.
|
||
|
||
```
|
||
config.yaml canonical: stream/models/counting/batch/output/camera
|
||
.env secrets + deployment: RTSP_URL, dashboard host/ports/secret/site
|
||
zones.json geometry: palet/truck/counting polygons + left/right limits
|
||
cfg/tracker.yaml tracker hyperparams (FastTrack/ByteTrack tuning)
|
||
```
|
||
|
||
Model modes are **data** (`config.yaml` → `models.modes`): each preset declares
|
||
only `engines` (path key + contributed classes) and `class_filters`.
|
||
Per-class `conf`/`iou`/`min_bbox_area` live in `models.detection_params` and
|
||
apply to ALL modes. `detection_params.*.conf` is the **authoritative detection
|
||
floor** — `predict.py` no longer hardcodes a second gate (old 0.50 sack / 0.45
|
||
truck overrides are gone). `counting.cross_class_iou` (default 0.4) drops sack
|
||
detections that overlap a box detection (v4 has no box class); `<= 0` disables.
|
||
Adding mode E/F/... is a YAML-only change — `predict.py`
|
||
derives tracker roles structurally, and the dashboard `/api/model-modes`
|
||
endpoint lists them automatically.
|
||
|
||
Mode switch: dashboard `POST /api/batch/mode {"model_mode": "X"}` validates
|
||
against `config.yaml` and persists atomically (tmp+replace, comments preserved)
|
||
to `models.active_mode`. **Manual `karung-counter` restart still required**
|
||
(models load once at startup). `batch_mode.json` keeps only the batch flow
|
||
`mode` (`auto` | `do_manual` | `manual`); its legacy `model_mode` key is
|
||
ignored (warned). `MODEL_MODE` env var still overrides for one run but is
|
||
deprecated (warned).
|
||
|
||
**Batch flow modes** (`batch.default_mode` in YAML; runtime `batch_mode.json`):
|
||
|
||
| Mode | Who opens/closes | DO gate |
|
||
|---|---|---|
|
||
| `auto` (default) | AI truck FSM | n/a |
|
||
| `do_manual` | Operator start/stop + staged DO photos | yes |
|
||
| `manual` | Operator start/stop (legacy) — plate required at start | no |
|
||
|
||
`POST /api/batch/mode` with `mode` and/or `model_mode` is **office port only**
|
||
(403 on operator `:5000`); mode switch while a batch is active → **409**.
|
||
`GET /api/batch/mode` works on both ports (`mode_editable` / `model_mode_editable`).
|
||
|
||
**Auto-mode timers** (`batch:` in `config.yaml`, comments inline):
|
||
|
||
| Key | Default | Controls |
|
||
|---|---|---|
|
||
| `timeout_seconds` | `20` | sack-idle: N s with no crossing **and** no sack visible in the truck area → batch pauses (`WAITING_FOR_ACTIVITY`) |
|
||
| `truck_gone_tolerance_seconds` | `30` | truck-gone: in `WAITING_FOR_ACTIVITY`, N s with no crossing + no visible sack + no valid truck signal → batch finalized |
|
||
|
||
`--batch-timeout` (dev CLI) overrides both for one run. Truck presence
|
||
(`truck_in_area`) accepts a bbox with ≥50 % area overlap of
|
||
`detection_polygon` (100 % containment made the signal flicker for big
|
||
docked trucks); transitions are logged as `[TRUCK] truck_in_area ...`.
|
||
|
||
**DO block** (`do:` in `config.yaml`): `enabled`, `require_do`, `require_plate`
|
||
(default seed), `retention_days: 7`, `photo_dir: do_photos`,
|
||
`max_photos_per_batch`, `zone_warn_seconds`, `ocr.engine` (YAML seed only).
|
||
|
||
**Runtime DO settings** (`$OUTPUT_DIR/do_settings.json`):
|
||
`require_plate` / `require_do` / `ocr_engine`
|
||
(`rapid`|`tesseract`|`paddle`|`none`, default `rapid`) — **office-only write**
|
||
(403 on operator). Sync via `GET/POST /api/do/settings`. Engine flip applies
|
||
to the next upload without restart.
|
||
|
||
Template: `.env.example`. Production values live in `.env` (git-ignored).
|
||
Missing `config.yaml` falls back to `.env` + built-in defaults with a warning
|
||
(see `src/config_loader.py`); explicit legacy path env vars below still override
|
||
when set.
|
||
|
||
## 1. `.env` (secrets & deployment — `predict.py` / `counter_dashboard.py`)
|
||
|
||
| Key | Default | Meaning |
|
||
|---|---|---|
|
||
| `OUTPUT_DIR` | `/opt/jetson-counter` | Legacy override of `output.dir` when set |
|
||
| `DB_PATH` | `$OUTPUT_DIR/jetson_counter.db` | Legacy override of the SQLite path when set |
|
||
| `STATE_FILE` | `$OUTPUT_DIR/current_batch.json` | Legacy override of the live batch state path when set |
|
||
| `BATCH_MODE_FILE` | `$OUTPUT_DIR/batch_mode.json` | Legacy override (file keeps only batch flow mode: auto/do_manual/manual) |
|
||
| `DO_SETTINGS_PATH` | `$OUTPUT_DIR/do_settings.json` | Runtime DO settings (require_plate/do, ocr_engine) |
|
||
| `DO_PHOTO_ROOT` | `$OUTPUT_DIR/do_photos` | DO photo tree root |
|
||
| `LIVE_STREAM_FRAME_PATH` | `/dev/shm/jetson-counter/live_frame.jpg` | Legacy override of the annotated frame path when set |
|
||
| `CAMERA_NAME` | `CC1` | Camera tag stored per batch |
|
||
| `OBJECT_LABEL` | `karung-pakan` | Object tag stored per batch |
|
||
| `DAILY_CUTOFF_TIME` | `06:00` | Counting-day boundary (`get_counting_date`) |
|
||
| `SECRET_KEY` | — | Flask session key (**change in production**) |
|
||
| `DASHBOARD_HOST` / `DASHBOARD_PORT` | `0.0.0.0` / `5000` | Dashboard bind |
|
||
| `OFFICE_PORT` | `5721` | Second dashboard port |
|
||
| `FLASK_DEBUG` | `false` | Flask debug |
|
||
| `RTSP_URL` | — | Camera stream URL (env-only, never in YAML) |
|
||
| `MOTIONEYE_URL` | `""` | motionEye base URL for batch clip download (empty disables the endpoint) |
|
||
| `MOTIONEYE_CAMERA_ID` | `2` | motionEye camera id used for batch clip download |
|
||
| `MOTIONEYE_CLIP_PAD` | `3` | Seconds padded before/after the batch window when trimming the clip (float) |
|
||
| `MOTIONEYE_OSD_ALIGN` | `1` | `1` = OCR-correct burned-in OSD clock drift at cut points, `0` = filename-based offsets only |
|
||
| `MODEL_PATH` | — (deprecated) | Single-file v4 override, folded into `models.paths` |
|
||
| `MODEL_MODE` | — (deprecated) | One-run override of `models.active_mode` (warned) |
|
||
| `BATCH_MERGE_THRESHOLD_SECONDS` | `300` | Merge window for adjacent batches |
|
||
|
||
On Windows dev machines these resolve to `d:/Belajar/menghitung karung/...`.
|
||
|
||
## 2. `src/config.py` keys (deprecated v3 `src/main.py --env`)
|
||
|
||
⚠️ **Deprecated** — the v3 loop is retired; production uses `config.yaml` via
|
||
`src/config_loader.py`. Documented here only because the old keys still exist
|
||
in code. Do not add new keys here.
|
||
|
||
⚠️ **Different names** from the table above — the v3 loader uses its own keys:
|
||
|
||
| Key | Default |
|
||
|---|---|
|
||
| `LOCAL_RTSP` / `JETSON_RTSP` | `""` |
|
||
| `MODEL_SACK_PATH` / `MODEL_TRUCK_PATH` | `./models/best.engine`, `./models/truck-detector.engine` |
|
||
| `COUNTING_LINE_Y` / `_X_START` / `_X_END` | `0.60` / `0.38` / `0.72` (fractions; initial line before ROI sync) |
|
||
| `SACK_CONF_THRESHOLD` / `TRUCK_CONF_THRESHOLD` | `0.40` / `0.50` |
|
||
| `BATCH_TIMEOUT_SECONDS` | `30` |
|
||
| `CSV_OUTPUT_DIR` | `./output` |
|
||
| `DATA_SEED` | `42` |
|
||
|
||
CLI: `python -m src.main --source video.mp4 --env .env`.
|
||
|
||
## 3. `zones.json` (calibrated geometry, 1920×1080 reference)
|
||
|
||
- `palet` / `truck` / `counting` — zone polygons; scaled to actual resolution
|
||
at startup.
|
||
- `left_limit` / `right_limit` (`0.27578` / `0.72578`) — counting X band.
|
||
- `external_stream_url` — MediaMTX restream endpoint.
|
||
- Legacy knob keys (`duplicate_circle_radius`, `min_valid_area`,
|
||
`jarak_toleransi_duplikat`, `max_reid_transit_distance`,
|
||
`circle_stay_timeout_sec`, `inference_stride`, `confirm_delay_sec`,
|
||
`exit_confirm_delay_sec`) are **ignored with a warning** — they moved to
|
||
`config.yaml counting.*` / `stream.inference_stride`. Keep only geometry here.
|
||
|
||
Recalibrate with `archive/get_coordinates.py` / `archive/get_calib_frame.py`
|
||
(`calib_frame.jpg`).
|
||
|
||
## 4. `cfg/tracker.yaml` (FastTrack/ByteTrack tuning)
|
||
|
||
`track_buffer=60` (~2.4 s lost-track hold for worker occlusion), `new_track_thresh=0.30`
|
||
(anti-duplicate IDs), `track_high/low_thresh=0.20/0.05`, `match_thresh=0.85`,
|
||
`active_occ_to_lost_thresh=15`, `occ_reappear_window=60`, `enlarge_bbox_occ=1.15`,
|
||
`occ_cover_thresh=0.6`, Kalman offsets + `init_iou_suppress=0.65`.
|
||
Falls back to stock `bytetrack.yaml` if the file is missing (`src/tracking.py:39`).
|
||
|
||
## 5. `archive/rpo_iki/configs/` (retired alternate engine, not imported)
|
||
|
||
`area_truk*.json` (per-camera truck areas), `cameras.json` (cam1/cam2 RTSP),
|
||
`counting_params.json` (+ `counting_params_last_truck.json`, hot-reloaded by
|
||
`count.py`), `model_registry.json` (pinned model + metrics), `telegram.json`
|
||
(notification settings).
|