miketsai 953b7a348a feat(test): BLE test mode for validating alerts, CAN speed, and buzzer
Add TEST_ENTER/TEST_EXIT commands via BLE to enter/exit test mode.
In test mode, inference results are suppressed; testers can directly
trigger BLE JSON (TEST_BLE *), CAN+Buzzer actions (TEST_CAN *),
or run sequenced full-coverage tests (TEST_BLE_ALL, TEST_CAN_ALL,
TEST_ALL). Auto-exits after 60s idle. Routes unrecognised BLE
commands through new bt_uart_set_extra_cmd_cb() hook.
2026-06-13 18:12:05 +08:00
2026-06-08 14:49:20 +08:00
2026-06-08 14:49:20 +08:00
2026-04-12 17:47:54 +08:00
2026-04-13 10:51:34 +08:00
2026-06-08 14:49:20 +08:00
2026-06-08 16:11:49 +08:00
2026-06-08 14:49:20 +08:00
2026-04-12 09:40:04 +00:00
2026-06-08 14:49:20 +08:00
2026-06-08 14:49:20 +08:00

KL630 Host Stream Firmware

即時影像語義分割系統,運行於 Kneron KL630 (Cortex-A7, uClibc)。 透過 IMX662 DOL-HDR 雙曝光攝影機進行 STDC 語義分割,並將結果以 RTSP 串流或 HDMI 輸出。

技術細節 → docs/technical_report.md


目錄結構

kl630_build/
├── web_serve.py             # Web 控制台(主要使用)
├── build_and_serve.py       # CLI 版本(不需要瀏覽器)
├── compile.sh               # Docker 內 ARM 交叉編譯腳本
├── Dockerfile               # kl630-dev image 定義
├── requirements.txt         # Python 套件清單
│
├── src/
│   ├── host_stream/         # 主程式(初始化、推論迴圈、結果處理)
│   ├── app_flow/            # VMF pipeline 控制
│   ├── pre_post/            # YOLOv5 前後處理
│   └── stdc/                # STDC 語義分割後處理
│
├── include/
│   ├── stdc/                # stdc_post_process.h分析結果結構
│   └── fake/                # SDK 缺少時的 stub headers
│
├── ini/
│   └── host_stream.ini      # 執行期設定model、stream、ISP、FEC 參數)
│
│
├── lib/                     # 裝置端 .so 函式庫VMF SDK
├── docs/
│   └── technical_report.md  # 完整技術文件
└── build/                   # 編譯輸出(由 compile.sh 產生)

快速開始

前置條件

安裝

pip install -r requirements.txt
套件 用途
flask Web 控制台 + HTTP file server
opencv-python RTSP 串流預覽(內建 FFmpeg無需另外安裝

啟動

python web_serve.py

瀏覽器開啟 http://localhost:8080/


新機器首次設定 SOP

全新 KL630 裝置依序執行以下步驟:

Step 1 — Compile

在 Web 控制台按 Compile

  • 自動建立 Docker image若不存在
  • 交叉編譯 ARM binary
  • 複製 binary / INI / 腳本到 build/

若 binary 已是最新版本,可跳過此步驟直接從 Step 2 開始。

Step 2 — 設定 Output Mode

INI Settings 面板選擇輸出模式(預設 RTSP

組合 RTSP HDMI 啟動腳本
RTSP 串流 ON OFF demo_rtsp.sh
HDMI 顯示 OFF ON demo_hdmi.sh
RTSP + HDMI 同時 ON ON demo_rtsp_hdmi.shINI voc_enable=1
純推論(無輸出) OFF OFF 直接啟動 binary

Step 3 — Deploy to KL630

Deploy to KL630,自動透過 Telnet 完成:

  1. 停止舊 firmware
  2. 下載 binary、INI、NEF 模型
  3. 下載 demo_rtsp.shdemo_hdmi.shdemo_rtsp_hdmi.sh
  4. 設定 VOC 輸出模式
  5. 啟動 firmware

Step 4 — First-time ISP Setup

First-time ISP Setup。 寫入 DOL-HDR 所需的 flash 參數(dwStatisticsSrcType=2bGTREnable=1 只需執行一次,設定永久保留在 flash重新 Deploy 不會被覆蓋。

跳過此步驟影像會過暗或曝光不正確。

Step 5 — 魚眼鏡頭校正FEC

INI Settings 面板設定 Fish-Eye Correction

參數 推薦設定 說明
FEC ON 開啟魚眼校正
Mode 4 — 180° Two Direction 天花板魚眼鏡頭推薦模式,同時展開水平與垂直方向
Install Type 0 — Ceiling 天花板安裝
EIS 視需求 電子防手震

Apply to Device + Restart 套用並重啟 firmware。


Web 控制台功能說明

Network Config

設定 Host IP(這台 PCKL630 IPHTTP PortDocker Image。 按 Save 後自動更新 deploy.shHOST_URL

HTTP Server Files

列出 build/ 目錄下所有可下載的檔案,以及裝置端手動部署指令:

wget http://<host_ip>:8080/deploy.sh -O /tmp/deploy.sh && sh /tmp/deploy.sh

RTSP Stream Preview

直接在網頁預覽 KL630 串流,不需要開 VLC。 按 ▶ Start Stream 即可,連線失敗時 6 秒內回報錯誤。


Actions

按鈕 說明
Compile Docker 交叉編譯 ARM binary複製到 build/
Deploy to KL630 Telnet 部署 binary / INI / NEF / 腳本,依 Output Mode 啟動 firmware
First-time ISP Setup 新機器一次性 ISP flash 設定DOL-HDR 參數)
Write Autostart 寫入開機自動啟動腳本 /etc/init.d/S99firmware

INI Settings

Fish-Eye Correction (FEC)

參數 說明
FEC ON/OFF 開啟或關閉魚眼校正(fec_mode = 0 為關閉)
Mode 1 Single Region
Mode 2 180° All Direction
Mode 3 180° One Direction
Mode 4 180° Two Direction推薦
Mode 5 PT Mode
Install Type Ceiling / Table / Wallinitial_fec_app_type
EIS 電子防手震(eis_enable
DrawBox H.264 burn-in 偵測框(DrawBoxEnable

Output Mode

選項 說明
RTSP H.264 RTSP 串流輸出,由 demo_rtsp.sh 管理
HDMI VOC HDMI 顯示輸出,由 demo_hdmi.sh 管理
  • Save INIdisk only — 更新本地 ini/host_stream.ini,下次 Deploy 時推送至裝置
  • Apply to Device + Restart — 立即 Telnet 更新裝置 INI 並重啟 firmware

Model Settings

切換推論模型NEF 檔、ModelId、JobId支援上傳新 NEF。 Apply to Device + Restart 會下載 NEF 到裝置並依目前 Output Mode 重啟。


Terminal

Output Log 下方有命令輸入列,可直接在網頁對 KL630 下指令:

cat /tmp/fw.log           # 查看 firmware 啟動 log
cat /tmp/rtsp_demo.log    # 查看 RTSP demo log
ps | grep firmware        # 確認 firmware 是否在執行
killall kp_firmware_host_stream


Web Server 命令行操作指南

若不喜歡 GUI可透過指令和 API 完全控制 web_serve.py,不需要開瀏覽器。

啟動 Web Server

# 預設 port 8080
python web_serve.py

# 指定端口
python web_serve.py --port 8080
python web_serve.py --port 9090

Server 啟動後可用 curl 調用各項功能。

Web Server API 參考

1. 查詢/保存設定

# 查看現在設定Host IP、KL630 IP、HTTP Port、Docker Image
curl http://localhost:8080/api/config

# 修改設定
curl -X POST http://localhost:8080/api/config \
  -H "Content-Type: application/json" \
  -d '{
    "host_ip": "192.168.3.1",
    "kl630_ip": "192.168.3.10",
    "port": 8080,
    "docker_image": "kl630-dev"
  }'

2. 查看 build/ 目錄下載文件列表

curl http://localhost:8080/api/files

輸出示例:

[
  {"name": "kp_firmware_host_stream", "size": 5242880},
  {"name": "host_stream.ini", "size": 2048},
  {"name": "demo_rtsp.sh", "size": 512},
  {"name": "deploy.sh", "size": 1024}
]

3. 編譯Server-Sent Events 串流輸出)

# 啟動編譯,即時輸出編譯 log
curl http://localhost:8080/api/compile/run

# 搭配 jq 只看 error
curl http://localhost:8080/api/compile/run | grep -o '"kind":"error"' | wc -l

編譯 log 格式SSE

{"kind": "log", "text": "Starting cross-compile..."}
{"kind": "ok", "text": "Compile SUCCESS"}
{"kind": "error", "text": "Compile FAILED (exit 1)"}

4. 部署到 KL630Telnet

# 執行完整部署流程(停止舊 firmware、下載 binary、啟動新 firmware
curl http://localhost:8080/api/deploy/run

# 查看部署 log最後 100 行)可透過網頁 Terminal 或直接用 tail

部署流程等同於 Web UI 按下 Deploy to KL630

5. ISP / Flash 一次性設定

# 一次性 ISP setupDOL-HDR 參數)
curl http://localhost:8080/api/spi_setup/run

# 或藍牙相關設定
curl http://localhost:8080/api/bt_setup/run

6. INI 設定讀取/寫入

# 讀取目前 INI 設定
curl http://localhost:8080/api/ini

# 修改 INI 並立即套用到裝置(等同 Web UI "Apply to Device + Restart"
curl -X POST http://localhost:8080/api/ini/apply \
  -H "Content-Type: application/json" \
  -d '{
    "fec_mode": 4,
    "DrawBoxEnable": 1,
    "voc_enable": 0
  }'

常見 INI 參數:

  • fec_mode: 0=關閉, 1-5=魚眼校正模式
  • DrawBoxEnable: 0/1 — H.264 burn-in 偵測框
  • voc_enable: 0/1 — HDMI VOC 輸出
  • ModelPath, ModelId, JobId: 推論模型設定

7. RTSP 串流預覽 / 停止

# 啟動 RTSP 預覽(返回 MJPEG 影像串流)
curl http://localhost:8080/api/stream/video > stream.mjpeg

# 停止 RTSP 預覽
curl -X POST http://localhost:8080/api/stream/stop

8. STDC 推論統計

# 查看即時推論統計(幀率、語義分割百分比)
curl http://localhost:8080/api/stdc/stats

# 啟動推論
curl -X POST http://localhost:8080/api/stdc/start

# 停止推論
curl -X POST http://localhost:8080/api/stdc/stop

輸出示例:

{
  "frame": 42,
  "mov": 1,
  "diff": 4.2,
  "classes": {
    "bunker": 0.0,
    "car": 8.3,
    "grass": 0.0,
    "greenery": 12.1,
    "person": 0.0,
    "pond": 0.0,
    "road": 71.4,
    "tree": 8.2
  }
}

9. 遠端執行指令Telnet 到裝置)

# 在裝置上執行指令並取得輸出
curl -X POST http://localhost:8080/api/terminal/exec \
  -H "Content-Type: application/json" \
  -d '{"cmd": "ps | grep firmware"}'

# 查看 firmware log
curl -X POST http://localhost:8080/api/terminal/exec \
  -H "Content-Type: application/json" \
  -d '{"cmd": "cat /tmp/fw.log"}'

# 查看可用模型
curl -X POST http://localhost:8080/api/terminal/exec \
  -H "Content-Type: application/json" \
  -d '{"cmd": "ls -lh /mnt/flash/vienna/nef/"}'

10. 開機自動啟動設定

# 查看自動啟動腳本設定
curl http://localhost:8080/api/autostart/read

# 寫入自動啟動腳本(`/etc/init.d/S99firmware`
curl -X POST http://localhost:8080/api/autostart/write \
  -H "Content-Type: application/json" \
  -d '{"autostart_mode": "rtsp"}'  # or "hdmi", "rtsp_hdmi"

11. 模型管理

# 查看可用模型列表
curl http://localhost:8080/api/model/list

# 切換模型(需要指定 ModelId / JobId
curl -X POST http://localhost:8080/api/model \
  -H "Content-Type: application/json" \
  -d '{
    "model_id": "100001",
    "job_id": 1
  }'

完整工作流示例(指令行完全不用 GUI

# 1. 設定網路Host IP 和 KL630 IP
curl -X POST http://localhost:8080/api/config \
  -H "Content-Type: application/json" \
  -d '{"host_ip": "192.168.3.1", "kl630_ip": "192.168.3.10"}'

# 2. 編譯
echo "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Compiling..."
curl http://localhost:8080/api/compile/run | grep '"kind"' | tail -1

# 3. 檢查生成的文件
echo "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Build files:"
curl http://localhost:8080/api/files | grep name

# 4. 部署到裝置
echo "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Deploying to KL630..."
curl http://localhost:8080/api/deploy/run

# 5. 查看推論統計
echo "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> STDC Stats:"
curl http://localhost:8080/api/stdc/stats | python -m json.tool

# 6. 設定魚眼校正FEC Mode 4
curl -X POST http://localhost:8080/api/ini/apply \
  -H "Content-Type: application/json" \
  -d '{"fec_mode": 4}'

CLI 指令完整參考

完全不用瀏覽器,所有操作均可透過指令完成。


1. 編譯(交叉編譯 ARM binary

方法 A — build_and_serve.py(推薦)

# 完整流程:編譯 + 檢查 binary + 啟動 HTTP server
python build_and_serve.py

# 常用旗標
python build_and_serve.py --no-build          # 跳過編譯,直接 servebinary 已存在時)
python build_and_serve.py --no-serve          # 只編譯 + 檢查,不啟動 server
python build_and_serve.py --port 9090         # 指定 HTTP server port預設 8080
python build_and_serve.py --image my-kl630    # 指定 Docker image 名稱
python build_and_serve.py --no-copy           # 不複製到網路資料夾
python build_and_serve.py --copy-dst /tmp/out # 指定複製目的地

方法 B — 直接 Docker

# 建立 Docker image只需一次
docker build -t kl630-dev .

# 交叉編譯
docker run --rm \
  -v "$(pwd):/workspace/kl630_build" \
  kl630-dev \
  bash /workspace/kl630_build/compile.sh

# 確認輸出
ls -lh build/kp_firmware_host_stream

2. 啟動 HTTP File Server裝置 wget 用)

# 用 build_and_serve.py推薦自動 copy INI + deploy.sh
python build_and_serve.py --no-build --no-check --port 8080

# 或直接 Python 內建 server
cd build && python -m http.server 8080

3. 部署到裝置Telnet / 裝置端指令)

先確認 HTTP server 在 PC 端已啟動,再 Telnet 進裝置:

telnet 192.168.3.10

在裝置端執行:

# 一鍵下載並部署(最常用)
wget http://192.168.3.1:8080/deploy.sh -O /tmp/deploy.sh && sh /tmp/deploy.sh

# 或分步驟手動執行:

# 停止舊 firmware
killall -9 kp_firmware_host_stream 2>/dev/null; killall -9 rtsps 2>/dev/null
sleep 1; rm -f /dev/shm/*

# 下載 binary 和 INI
wget http://192.168.3.1:8080/kp_firmware_host_stream -O /mnt/flash/vienna/kp_firmware_host_stream
chmod +x /mnt/flash/vienna/kp_firmware_host_stream
wget http://192.168.3.1:8080/host_stream.ini -O /mnt/flash/plus/kp_firmware/kp_firmware_0/kp_firmware/bin/ini/host_stream.ini

# 下載並啟動 RTSP demo
wget http://192.168.3.1:8080/demo_rtsp.sh -O /mnt/flash/plus/kp_firmware/kp_firmware_0/kp_firmware/bin/ini/demo_rtsp.sh
chmod +x /mnt/flash/plus/kp_firmware/kp_firmware_0/kp_firmware/bin/ini/demo_rtsp.sh
cd /mnt/flash/plus/kp_firmware/kp_firmware_0/kp_firmware/bin
sh ./ini/demo_rtsp.sh

新機器一次性 ISP 設定(只需跑一次):

wget http://192.168.3.1:8080/deploy.sh -O /tmp/deploy.sh && sh /tmp/deploy.sh --setup

4. 裝置端常用指令

# 確認 firmware 是否在跑
ps | grep firmware

# 查看 firmware log
cat /tmp/fw.log
tail -f /tmp/fw.log        # 持續監看BusyBox 無 -f用 watch 替代)

# 查看 RTSP demo log
cat /tmp/rtsp_demo.log

# 手動停止 firmware
killall -9 kp_firmware_host_stream
killall -9 rtsps

# 直接啟動(指定模型)
BIN_DIR=/mnt/flash/plus/kp_firmware/kp_firmware_0/kp_firmware/bin
FW=/mnt/flash/vienna/kp_firmware_host_stream
LD_LIBRARY_PATH=/mnt/flash/vienna/lib $FW \
  -m nef/stdc_scnn_fp.nef \
  -i 100001 -j 1 &

# 切換輸出模式(不用重新 deploy
sh $BIN_DIR/ini/demo_rtsp.sh       # RTSP 串流
sh $BIN_DIR/ini/demo_hdmi.sh       # HDMI 顯示
sh $BIN_DIR/ini/demo_rtsp_hdmi.sh  # RTSP + HDMI 同時

5. INI 設定(指令修改)

直接用 sed 修改裝置上的 INI不需要重新 deploy

INI=/mnt/flash/plus/kp_firmware/kp_firmware_0/kp_firmware/bin/ini/host_stream.ini

# 開啟 / 關閉魚眼校正 FEC
sed -i 's/^fec_mode.*/fec_mode = 4/' $INI   # Mode 4180° Two Direction
sed -i 's/^fec_mode.*/fec_mode = 0/' $INI   # 關閉

# 開啟 / 關閉 DrawBoxH.264 burn-in 框)
sed -i 's/^DrawBoxEnable.*/DrawBoxEnable = 1/' $INI
sed -i 's/^DrawBoxEnable.*/DrawBoxEnable = 0/' $INI

# 開啟 HDMI / VOC 輸出
sed -i 's/^voc_enable.*/voc_enable = 1/' $INI

# 查看目前設定
grep -E "fec_mode|DrawBoxEnable|voc_enable|ModelPath|ModelId" $INI

修改 INI 後需重啟 firmware 才生效:

killall -9 kp_firmware_host_stream 2>/dev/null
sh /mnt/flash/plus/kp_firmware/kp_firmware_0/kp_firmware/bin/ini/demo_rtsp.sh

6. Mock Server事件測試

# 啟動 mock serverport 8081
python tools/mock_server/server.py

# 開啟監控網頁
# http://localhost:8081/

curl 送測試事件(不用開網頁):

# Channel A — 送即時事件HTTP
curl -X POST http://localhost:8081/api/event \
  -H "Content-Type: application/json" \
  -d '{"response_type":"violation","content":{"id":"1","date":"2025-01-01T00:00:00+08:00","type":"road","level":2}}'

# 常用事件類型road / grass / hazard / person / bunker / pond / tree / car
# level0=解除, 1=警告, 2=嚴重, 3=緊急

# 查詢事件列表
curl http://localhost:8081/api/events

# Channel C — 送 CAN 事件(測試 CAN bus TX
curl -X POST http://localhost:8081/api/can/send \
  -H "Content-Type: application/json" \
  -d '{"type":"hazard","level":1,"can_id":256}'

# 送油門控制指令CAN ID 0x75
curl -X POST http://localhost:8081/api/can/send_cmd \
  -H "Content-Type: application/json" \
  -d '{"cmd":128,"can_id":117}'   # cmd: 0=關閉, 32/64/128/255=油門檔位

# 查詢 CAN bus 狀態
curl http://localhost:8081/api/can/status

# 啟動 CAN interface等同 UI Bring Up 按鈕)
curl -X POST http://localhost:8081/api/can/bringup \
  -H "Content-Type: application/json" \
  -d '{"channel":"can0","bitrate":250000}'

BLE 指令協議(藍牙通訊)

KL630 透過 DX-BT24 模組UART /dev/ttyS1 @ 115200與 iPad / 手機 app 溝通。 所有訊息均為 UTF-8 JSON無需 CRLF。


CommandApp → KL630

狀態確認

{"command":"status_check"}

回傳 Notifyresponse_type=status_check

查詢租借狀態

{"command":"get_rent_status"}

回傳 Notifyresponse_type=rent_status

租借

{"command":"rent"}

若目前 status=0 則轉為 1其他狀態忽略。回傳 Notifyresponse_type=rent_status

歸還

{"command":"return"}

若目前 status=1 則轉為 0其他狀態忽略。回傳 Notifyresponse_type=rent_status


NotifyKL630 → App

系統狀態(回應 status_check

{"response_type":"status_check","content":{"ares_x_version":"1.0.0","bluetooth_peripheral_name":"BT-24","is_intervention_cart_control":false}}
欄位 說明
ares_x_version 韌體版本,由 INI event:ares_version 設定
bluetooth_peripheral_name BLE 掃描名稱,由 INI event:bt_name 設定
is_intervention_cart_control 是否正在介入車輛控制CAN bus 活動中)

租借狀態(回應 rent / return / get_rent_status

{"response_type":"rent_status","content":{"status":0}}
status 說明
0 未租借
1 租借中
2 管理模式

違規事件(由推論結果觸發)

{"response_type":"violation","content":{"id":"abcd-1234-0000-0000","date":"2025-12-08T06:08:49Z","type":"lane","level":2}}
level 說明
0 解除
1 違規發生
2 違規持續 6 秒
3 違規持續 10 秒

危險區域警告

{"response_type":"alert","content":{"left_level":0,"right_level":1}}

左右各獨立,0=無危險,1=有危險。


INI 設定(ini/host_stream.ini [event] 區段)

bt_uart_dev  = /dev/ttyS1   # UART 裝置路徑
bt_at_probe  = 0             # 0: 正常啟動1: 首次設定9600→115200 升速)
ares_version = 1.0.0         # 韌體版本字串
bt_name      = BT-24         # BLE 掃描名稱

測試指令

用 BLE appnRF Connect 等)直接測試

複製以下 JSON 貼入 Write Characteristic 欄位送出:

{"command":"status_check"}
{"command":"get_rent_status"}
{"command":"rent"}
{"command":"return"}

用 Mock Server 模擬裝置回傳curl

# 模擬違規事件通知
curl -X POST http://localhost:8081/api/event \
  -H "Content-Type: application/json" \
  -d '{"response_type":"violation","content":{"id":"test-001","date":"2026-04-22T00:00:00Z","type":"lane","level":1}}'

# 模擬違規持續 6 秒
curl -X POST http://localhost:8081/api/event \
  -H "Content-Type: application/json" \
  -d '{"response_type":"violation","content":{"id":"test-001","date":"2026-04-22T00:00:00Z","type":"lane","level":2}}'

# 模擬違規解除
curl -X POST http://localhost:8081/api/event \
  -H "Content-Type: application/json" \
  -d '{"response_type":"violation","content":{"id":"test-001","date":"2026-04-22T00:00:00Z","type":"lane","level":0}}'

# 模擬危險區域警告(右側有危險)
curl -X POST http://localhost:8081/api/event \
  -H "Content-Type: application/json" \
  -d '{"response_type":"alert","content":{"left_level":0,"right_level":1}}'

# 模擬租借狀態更新
curl -X POST http://localhost:8081/api/event \
  -H "Content-Type: application/json" \
  -d '{"response_type":"rent_status","content":{"status":1}}'

# 查看目前所有事件記錄
curl http://localhost:8081/api/events

Firmware 執行結果console log

[STDC] frame=42 mov=1 diff=4.2 bunker=0.0% car=8.3% grass=0.0% greenery=12.1% person=0.0% pond=0.0% road=71.4% tree=8.2%
[STDC] ON ROAD
[STDC WARN] CAR 8.3%

詳細說明

IMX662 DOL-HDR 雙曝光設定、STDC 語義分割架構、新裝置部署 SOP、故障排查

docs/technical_report.md

Description
No description provided
Readme 62 MiB
Languages
C 94.5%
C++ 4.4%
Python 0.7%
CMake 0.1%
HTML 0.1%