- 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
8.2 KiB
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 toconfig.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).