Files
zenai-ktc-python/DEPLOY.md
T
2026-07-24 11:42:18 +07:00

7.9 KiB

ZenAI KTC Counter — Edge Deployment Guide

Production deployment for RK3588 (or compatible RKNN NPU) edge devices running a zone-based sack feeder counter (left / right feeders):

Component Script systemd unit
RTSP counter (RKNN + ByteTrack + zones) counter_live_rknn.py zenai-ktc-counter.service
Web dashboard (Flask) counter_dashboard.py zenai-ktc-dashboard.service

Both processes share a single .env file and read/write the same SQLite database and state JSON.

Counting model: two rectangular zones (left + right). A sack is counted once when its centroid enters a zone. Left zone → left feeder; right zone → right feeder.


1. Prerequisites

Hardware & OS

  • RK3588 board (or Jetson/RK device with RKNN Lite runtime)
  • Linux with systemd
  • Network access to the RTSP camera stream

System packages

sudo apt update
sudo apt install -y python3 python3-venv python3-pip ffmpeg libgl1

ffmpeg is required for low-latency RTSP capture via OpenCV. libgl1 is often needed for opencv-python on headless systems.

RKNN model

Export or copy your .rknn model to the device, e.g.:

/opt/models/your_model.rknn

Set MODEL_PATH in .env to match. The model class count must match NUM_CLASSES, and OBJECT_CLASS_ID must point at the class you count.


2. Directory layout

Default paths used by the service files and env.example:

/opt/zenai-ktc-python/          # application code (this repo)
├── counter_live_rknn.py
├── counter_dashboard.py
├── counter_store.py
├── templates/
├── venv/                       # Python virtual environment (created during install)
├── .env                        # runtime config (not in git)
├── env.example                 # template — copy to .env
└── DEPLOY.md

/opt/zenai-ktc-counter/         # persistent runtime data (created automatically)
├── counter.db                  # SQLite daily records
├── current_counter.json        # live counting-day state
├── snapshots/                  # zone-entry/detect JPEGs (if enabled)
└── crossings.csv               # optional per-event CSV

/opt/models/                    # RKNN models (deploy separately)
/dev/shm/zenai-ktc-counter/     # live JPEG frame for dashboard video (tmpfs)

3. Install application

3.1 Copy code to the device

sudo mkdir -p /opt/zenai-ktc-python
sudo rsync -av --exclude venv --exclude .env --exclude __pycache__ \
  ./ /opt/zenai-ktc-python/
# Or: sudo git clone <repo-url> /opt/zenai-ktc-python

3.2 Create virtual environment and install dependencies

cd /opt/zenai-ktc-python
sudo python3 -m venv venv
sudo ./venv/bin/pip install --upgrade pip
sudo ./venv/bin/pip install -r requirements.txt

rknn-toolkit-lite2 is platform-specific. Install on the target ARM device, not on a Windows dev machine.

3.3 Create runtime config

cd /opt/zenai-ktc-python
sudo cp env.example .env
sudo nano .env

Minimum values to edit before starting:

Variable Description
SOURCE RTSP URL or local video file path
MODEL_PATH Path to your .rknn model on device
NUM_CLASSES Must match the exported model
OBJECT_CLASS_ID Class index of the object being counted
CLASS_OBJECT / OBJECT_LABEL Labels stored in DB (e.g. karung)
ZONE_LEFT_*_FRAC / ZONE_RIGHT_*_FRAC Feeder zone rectangles (tune per camera)
SECRET_KEY Random string for Flask sessions

Ensure STATE_FILE and DB_PATH both live under /opt/zenai-ktc-counter/ so data survives reboots (avoid /tmp in production).

3.4 Create data directories (optional — app creates most paths automatically)

sudo mkdir -p /opt/zenai-ktc-counter /opt/models /dev/shm/zenai-ktc-counter

4. Install systemd services

cd /opt/zenai-ktc-python
sudo cp zenai-ktc-counter.service zenai-ktc-dashboard.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable zenai-ktc-counter zenai-ktc-dashboard
sudo systemctl start zenai-ktc-counter
sudo systemctl start zenai-ktc-dashboard

The dashboard unit starts after the counter unit (After=zenai-ktc-counter.service).

Verify

systemctl status zenai-ktc-counter
systemctl status zenai-ktc-dashboard
journalctl -u zenai-ktc-counter -f

Open the dashboard in a browser:

http://<device-ip>:5000

(Port is set by DASHBOARD_PORT in .env, default 5000.)


5. Tuning feeder zones

Zones are axis-aligned rectangles. Defaults cover the left and right sides of the frame:

ZONE_LEFT_X1_FRAC=0.00
ZONE_LEFT_Y1_FRAC=0.20
ZONE_LEFT_X2_FRAC=0.35
ZONE_LEFT_Y2_FRAC=0.85

ZONE_RIGHT_X1_FRAC=0.65
ZONE_RIGHT_Y1_FRAC=0.20
ZONE_RIGHT_X2_FRAC=1.00
ZONE_RIGHT_Y2_FRAC=0.85

For pixel-perfect placement, set absolute coordinates instead (they override fractions):

ZONE_LEFT_X1=40
ZONE_LEFT_Y1=120
ZONE_LEFT_X2=420
ZONE_LEFT_Y2=900

Enable DEBUG_TRACKING=true temporarily for verbose inherit / dup / cooldown logs.

Each successful count always prints a Frigate-style line to the journal:

Total karung di kandang_bawah_feeder_kanan: 5

Set FEEDER_LEFT_NAME / FEEDER_RIGHT_NAME (and OBJECT_LABEL) in .env to match your site.


6. Operations

Restart after config change

sudo systemctl restart zenai-ktc-counter
sudo systemctl restart zenai-ktc-dashboard

View logs

journalctl -u zenai-ktc-counter -n 100 --no-pager
journalctl -u zenai-ktc-dashboard -n 100 --no-pager

Stop services

sudo systemctl stop zenai-ktc-dashboard zenai-ktc-counter

The counter handles SIGTERM gracefully — it finishes the current frame, persists state to SQLite, then exits.

Update application code

cd /opt/zenai-ktc-python
sudo systemctl stop zenai-ktc-dashboard zenai-ktc-counter
# rsync or git pull new code
sudo ./venv/bin/pip install -r requirements.txt   # if dependencies changed
sudo systemctl start zenai-ktc-counter zenai-ktc-dashboard

7. Troubleshooting

Symptom Things to check
Counter won't start journalctl -u zenai-ktc-counter; verify MODEL_PATH exists; RKNN drivers installed
No RTSP frames Ping camera; test with ffplay <SOURCE>; check OPENCV_FFMPEG_CAPTURE_OPTIONS
Dashboard shows 0 count STATE_FILE in .env must match between counter and dashboard; check file exists
Live video blank LIVE_STREAM_ENABLED=true; path matches LIVE_STREAM_FRAME_PATH in both processes
Wrong feeder / missed counts Tune ZONE_*_FRAC, CONF, ByteTrack thresholds; enable DEBUG_TRACKING=true
Service keeps restarting journalctl -u zenai-ktc-counter -e; often missing model, bad RTSP URL, or venv not created

Manual test (without systemd)

cd /opt/zenai-ktc-python
source venv/bin/activate
python counter_live_rknn.py    # terminal 1
python counter_dashboard.py    # terminal 2

8. Optional: reverse proxy

For HTTPS or port 80 access, put nginx in front of the dashboard:

server {
    listen 80;
    server_name counter.example.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffering off;        # required for /api/live-video MJPEG stream
        proxy_read_timeout 3600s;   # keep long-lived MJPEG connections open
        proxy_send_timeout 3600s;
    }
}

9. Security notes

  • Change SECRET_KEY from the default before exposing the dashboard on a network.
  • Services currently run as root for simplicity on edge devices. For hardened deployments, create a dedicated user, chown /opt/zenai-ktc-counter, and update the User= / Group= lines in the service files.
  • Do not commit .env — it may contain RTSP credentials.
  • Set FLASK_DEBUG=false in production.