Files
karung-counting-feedmill-se…/docs/configuration.md
T
andrew 6c5b1c8b30
ci / smoke (push) Canceled after 0s
feat(manual-batch): canonical plate + manual mode as default
- canonical_plate (uppercase alnum, strips space/dot/hyphen) at all plate
  write sites; pretty_plate for render (history, XLSX, operator tile) so
  B 1234 XYZ and B1234XYZ are one plate everywhere
- group_dos_by_plate compares canonical plates -> no false mixed_plates
- warn-only (never blocking) plate format hint in operator + monitoring modals
- batch.default_mode: manual (auto merged truck loads when a sack sat in the
  counting ROI); operator banner explains plate -> start -> stop
- docs + AGENTS known-limitation note; 85 tests pass
2026-10-05 09:36:32 +07:00

152 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` | AI truck FSM — merges batches when a sack sits in the counting ROI (known) | n/a |
| `do_manual` | Operator start/stop + staged DO photos | yes |
| `manual` (**default**) | Operator start/stop, 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).