visionA/local-tool/docs/LOCAL-TOOL-SPEC.md
jim800121chen 14d5a0ed2f docs(local-tool): Build 指引 → Installer Build 指引
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:04:38 +08:00

314 lines
14 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.

# visionA Local Tool — 功能規格文件
> 版本v0.1.0-dev | 最後更新2026-04-16 | 對應 commit`9793a2e`
## 概述
visionA Local Tool 是 Kneron KL520 / KL720 邊緣 AI 推論硬體的**本機桌面應用**,讓使用者在完全離線的環境下,透過 USB 連接 Kneron 裝置,進行影像 / 影片 / 攝影機即時推論。
架構為 **Wails 桌面 AppGo + Vanilla JS 控制台)+ Go HTTP Server + Next.js Web UI瀏覽器**。Wails 控制台負責 server lifecycle 管理,瀏覽器 Web UI 負責裝置操作、模型管理、推論工作區。
### 三平台支援
| 平台 | 安裝格式 | Build target |
|------|---------|-------------|
| macOS (x86_64) | `.dmg` | `make dmg` |
| Windows (x64) | `.exe` (Inno Setup) | `make exe` |
| Linux (x86_64) | `.AppImage` | `make appimage` |
### 完全離線安裝
所有依賴Python runtime、wheels、ffmpeg、ffprobe、.nef 模型)全部 vendor 進 installer安裝和執行過程**不需要網路連線**。
---
## 1. Wails 控制台(桌面應用程式視窗)
### 1.1 啟動流程 — 5 階段進度面板
| 階段 | 名稱 | 做什麼 |
|------|------|--------|
| 1 | 初始化控制台 | 建立 dataDir、舊資料遷移、single-instance lock、IPC server、首次啟動 seed複製內建模型到 user dataDir |
| 2 | 檢查 Python 執行環境 | 偵測系統 Python → 或解壓內建 Python runtime首次啟動 ~1-3 分鐘)→ 建 venv → pip install wheelsnumpy/opencv/KneronPLUS 等 9 個套件) |
| 3 | 啟動本機伺服器 | spawn `visiona-local-server` subprocess → 等 health check 通過(首次啟動 Windows Defender 掃描可能需 1-2 分鐘) |
| 4 | 偵測 Kneron 裝置 | 對 `/api/devices` 發一次 GET 確認 server 可 serve 業務 endpoint |
| 5 | 開啟瀏覽器 | 自動開啟系統預設瀏覽器到 `http://127.0.0.1:3721`(可在設定中關閉) |
- **全屏 splash**app 啟動最一開始顯示 logo + spinner 全屏 overlay收到第一個 stage event 後切換到 5 階段面板
- **每階段細步文案**Go 端在每個 sub-step emit `startup:stage-detail` event前端即時顯示當前正在做什麼例如「正在解壓 Python runtime」「等待伺服器健康檢查通過」
- **啟動完成自動收合**5 階段全部完成後面板收合成一行 summary「✓ 啟動完成 · 點此展開檢視」,使用者點擊可展開歷史紀錄
- **重啟 / 重試時重新展開**:按「重新啟動伺服器」或「重試」會重置面板並完整重跑 5 階段
- **前端 snapshot 補漏**:前端 init 完成後呼叫 `GetStartupSnapshot()` 補上 race window 中漏掉的 stage events避免順序亂跳
- **Web UI 連線指示燈**Stage 6「等待 Web UI 連線」從面板隱藏,改為 header 的 Web UI 連線指示燈(綠燈 = 已連線、黃燈 pulse = 等待中)
### 1.2 Timeout 機制
| 類型 | 時長 | 行為 |
|------|------|------|
| 每階段 soft timeout | 20 秒 | emit「正在重試...」提示,**不中斷流程** |
| 整體 hard timeout | 5 分鐘300 秒) | 超過則 fail 進 Error state |
| 首次 bootstrap pause | 無上限 | Stage 1 seed / Stage 2 Python bootstrap / Stage 3 waitHealthy 期間暫停 hard timeout 計時,不算進 5 分鐘 budget |
### 1.3 控制台功能
- **狀態列**:顯示 server 狀態(閒置 / 啟動中 / 執行中 / 停止中 / 已停止 / 錯誤、port、PID、uptime、Web UI 連線狀態
- **主要控制**:在瀏覽器開啟 / 啟動 / 管理(停止 / 重新啟動 / 開啟 log 資料夾)
- **Log 面板**server 即時 log 顯示、自動跟隨最新、關鍵字過濾、層級過濾All / INFO / WARN / ERROR、清空 / 複製 / 匯出 / 開啟 log 資料夾
- **Settings**啟動時自動開啟瀏覽器macOS/Windows 預設 ON、Linux 預設 OFF、語言切換繁體中文 / English / Auto、關於資訊
- **Shutdown modal**server 停止時顯示「正在停止伺服器…」overlay15 秒 watchdog 自動 hide可用 Esc / 點 backdrop 手動關閉
- **Error 處理**server 啟動失敗 → 紅 banner「伺服器無法啟動」+ 重試按鈕runtime crash → OS 原生通知 + Error state
- **i18n 雙語**:繁體中文 + English全 UI 元素(含 stage 細步文案、設定、錯誤訊息)
### 1.4 Single-instance 保護
-`visiona-local.lock` 檔案鎖 + PID 存活檢查
- 第二次啟動偵測到已有 instance → 嘗試 IPC raise 把現有視窗提到前景 → 自己 quietly exit
- Stale lockPID 已死)自動清理並取得新 lock
---
## 2. Web UI瀏覽器介面
### 2.1 頁面路由
| 路由 | 功能 |
|------|------|
| `/` | 儀表板 — 已連接裝置列表、活動時間軸、統計卡片 |
| `/devices` | 裝置列表 — 掃描 / 連接 / 斷開 Kneron USB 裝置 |
| `/devices/[id]` | 裝置詳細 — 狀態、健康度、韌體版本、連線日誌、設定 |
| `/models` | 模型庫 — 7 個預設 .nef 模型KL520 × 4 + KL720 × 3+ 上傳自訂模型 |
| `/models/[id]` | 模型詳細 — metadata、支援硬體、效能數據 |
| `/workspace` | 工作區 — 選裝置 → 選模型 → 選來源 → 推論 |
| `/workspace/[deviceId]` | 單一裝置工作區 — 推論操作主介面 |
| `/settings` | 設定 — 語言、主題、其他偏好 |
### 2.2 推論來源
| 來源 | 說明 |
|------|------|
| 攝影機 (Camera) | USB / IP Camera 即時串流推論 |
| 圖片 (Image) | 上傳單張 JPG/PNG 做單次推論 |
| 影片 (Video) | 上傳 MP4/AVI/MOV/MPEG/MPG 做逐幀推論ffmpeg 解碼) |
| 批次圖片 (Batch Images) | 上傳多張圖片逐張推論 |
### 2.3 推論結果顯示
- **MJPEG 即時串流**`/api/camera/stream` 提供多客戶端 multipart MJPEG 串流
- **Canvas overlay**bounding box + label + confidence 即時疊加
- **推論面板**FPS、平均延遲、信心度門檻調整、分類結果展示
- **影片進度**:目前幀 / 總幀、seek 跳轉
- **批次進度**:已處理 / 總張數、縮圖預覽
### 2.4 模型管理
- **7 個預設模型**NEF 格式、INT8 量化)
- **上傳自訂 .nef 模型**`POST /api/models/upload`
- **刪除已上傳模型**`DELETE /api/models/:id`
- **模型篩選**按任務類型object_detection / classification、硬體KL520 / KL720、關鍵字
- **模型對比工具**:並排比較兩個模型的規格
### 2.5 裝置管理
- **掃描 USB 裝置**:偵測已連接的 Kneron KL520 / KL720
- **連接 / 斷開**:連接時自動載入 firmwareKL520 USB Boot 流程)
- **韌體更新**flash .nef 到裝置 + 進度 WebSocket 即時回報
- **WinUSB 驅動安裝**Windows only首次啟動自動透過 KneronPLUS SDK libwdi 安裝,需 UAC 提權
### 2.6 離線覆蓋層
- Server 關閉 / 崩潰時,瀏覽器 tab 顯示 Offline Overlay
- `role=alertdialog` + focus trap + WebSocket 重連機制
- `boot-id` 偵測 server restart → 自動 reload含 reload loop guard
---
## 3. 預設模型
### KL5204 個)
| 模型 ID | 名稱 | 任務 | 輸入 |
|---------|------|------|------|
| kl520-yolov5-detection | YOLOv5 Detection | 物件偵測 | 640×640 |
| kl520-fcos-detection | FCOS Detection | 物件偵測 | 512×512 |
| kl520-ssd-face-detection | SSD Face Detection | 人臉偵測 | 320×240 |
| kl520-tiny-yolov3 | Tiny YOLOv3 | 物件偵測 | 416×416 |
### KL7203 個)
| 模型 ID | 名稱 | 任務 | 輸入 |
|---------|------|------|------|
| kl720-yolov5-detection | YOLOv5 Detection | 物件偵測 | 640×640 |
| kl720-resnet18-classification | ResNet18 Classification | 分類1000 類)| 224×224 |
| kl720-fcos-detection | FCOS Detection | 物件偵測 | 512×512 |
---
## 4. 內嵌依賴
| 依賴 | 版本 | 用途 | 授權 |
|------|------|------|------|
| Python | 3.12.9 (python-build-standalone) | Kneron Python bridge | PSF |
| numpy | 2.4.4 | 影像處理 | BSD |
| opencv-python-headless | 4.10.0 | 影像處理 | Apache-2.0 |
| KneronPLUS | 2.0.0 | Kneron SDK Python binding | Kneron |
| pyusb | 1.3.1 | USB 裝置存取 | BSD |
| requests | 2.33.1 | HTTP 工具 | Apache-2.0 |
| ffmpeg | 自建 LGPL v3 decoder-only | 影片解碼mp4/avi/mov/mpeg/mpg| LGPL v3 |
| ffprobe | 同上 | 影片 metadata 提取 | LGPL v3 |
### ffmpeg LGPL 合規
macOS 版為自行編譯的最小 decoder-only build~5.7MB),只啟用必要的 demuxer/decoder/parser/filter**無 --enable-gpl / libx264 / libx265**,符合 LGPL v3。Windows/Linux 使用 BtbN 官方 LGPL 預編譯 binary。
---
## 5. Server API 摘要
### 系統
| Method | Path | 說明 |
|--------|------|------|
| GET | `/api/system/health` | 健康檢查(高頻輪詢用,無 log |
| GET | `/api/system/info` | 版本、平台、uptime |
| GET | `/api/system/metrics` | Go runtime 記憶體統計 |
| GET | `/api/system/deps` | 外部依賴檢查python/ffmpeg/ffprobe |
| GET | `/api/system/boot-id` | server 啟動 ID偵測 restart 用) |
| POST | `/api/system/restart` | 重啟 server |
| POST | `/api/system/install-driver` | 安裝 Kneron USB 驅動Windows only |
| POST | `/api/system/shutdown-notify` | 廣播關機通知到 WebSocket clients |
### 模型
| Method | Path | 說明 |
|--------|------|------|
| GET | `/api/models` | 列出所有模型(支援 filter |
| GET | `/api/models/:id` | 取得單一模型詳細 |
| POST | `/api/models/upload` | 上傳自訂 .nef 模型 |
| DELETE | `/api/models/:id` | 刪除已上傳模型 |
### 裝置
| Method | Path | 說明 |
|--------|------|------|
| GET | `/api/devices` | 列出已偵測裝置 |
| POST | `/api/devices/scan` | 掃描 USB 裝置 |
| GET | `/api/devices/:id` | 取得裝置詳細 |
| POST | `/api/devices/:id/connect` | 連接裝置 |
| POST | `/api/devices/:id/disconnect` | 斷開裝置 |
| POST | `/api/devices/:id/flash` | 燒錄韌體 |
| POST | `/api/devices/:id/inference/start` | 啟動推論 |
| POST | `/api/devices/:id/inference/stop` | 停止推論 |
### 媒體
| Method | Path | 說明 |
|--------|------|------|
| GET | `/api/camera/list` | 列出可用攝影機 |
| POST | `/api/camera/start` | 啟動攝影機推論 pipeline |
| POST | `/api/camera/stop` | 停止 pipeline |
| GET | `/api/camera/stream` | MJPEG 即時串流 |
| POST | `/api/media/upload/image` | 上傳單張圖片推論 |
| POST | `/api/media/upload/video` | 上傳影片逐幀推論 |
| POST | `/api/media/upload/batch-images` | 批次上傳圖片推論 |
| GET | `/api/media/batch-images/:index` | 取得批次中特定幀 |
| POST | `/api/media/seek` | 影片 seek 跳轉 |
### WebSocket
| Path | 說明 |
|------|------|
| `/ws/devices/events` | 裝置連接 / 斷開事件 |
| `/ws/devices/:id/flash-progress` | 韌體更新進度 |
| `/ws/devices/:id/inference` | 推論結果即時串流 |
| `/ws/server-logs` | server log 即時廣播 |
| `/ws/system` | 系統事件(含 shutdown-imminent |
---
## 6. 資料目錄
| 平台 | 位置 |
|------|------|
| macOS | `~/Library/Application Support/visiona-local/` |
| Windows | `%APPDATA%\visiona-local\` |
| Linux | `~/.config/visiona-local/``$XDG_DATA_HOME/visiona-local/` |
### 目錄結構
```
visiona-local/
├── visiona-local.lock # single-instance 鎖
├── visiona-local.ipc-port # server port供 raise 用)
├── visiona-local.wails-ipc-port # Wails IPC port
├── preferences.json # 使用者偏好autoOpenBrowser / locale
├── models.json # 預設模型 catalog首次啟動從 bundle seed
├── nef/ # 預設 .nef 模型檔(首次啟動從 bundle seed
│ ├── kl520/
│ └── kl720/
├── custom-models/ # 使用者上傳的自訂模型
├── runtime/ # Python runtime首次啟動解壓
│ ├── python/
│ └── venv/
├── logs/
│ ├── server.stdout.log # server subprocess stdout
│ ├── server.stderr.log # server subprocess stderr
│ └── wails.log # Wails app (appLog) 啟動流程日誌
└── .first-ws-connected # WebSocket sentinel file啟動階段用
```
---
## 7. Installer Build 指引
### macOS
```bash
cd local-tool
make vendor-sync # 下載 Python + wheels + 驗證 ffmpeg LGPL
make payload-macos # 準備 payload/darwin/
make dmg # → dist/visiona-local.dmg (~163MB)
```
### Windows需在 Windows 機器上)
```powershell
cd local-tool
.\scripts\bootstrap-windows.ps1 # 安裝 Go / Node / pnpm / Wails / Python / MSYS2
make exe # → dist/visiona-local-*-windows-x64.exe
```
### LinuxUbuntu 22.04+
```bash
cd local-tool
bash scripts/bootstrap-linux.sh # 安裝所有依賴 + 自動 build
# 或手動:
make vendor-python-linux vendor-wheels-linux vendor-ffmpeg-linux
make payload-linux
make appimage # → dist/visiona-local-*-linux-x64.AppImage
```
---
## 8. 除錯指引
### Windows 啟動問題
1. 檢查 `%APPDATA%\visiona-local\logs\wails.log`
- 第一行應有 `fix marker: d946561+`(確認 build 版本)
- Stage 1-5 的細步文案會記錄每個 sub-step
2. 檢查 `server.stdout.log` / `server.stderr.log`
3. 如需更詳細的 Wails 端 log從命令列啟動
```
"C:\Program Files\visiona-local\visiona-local.exe" > %TEMP%\wails-debug.txt 2>&1
```
### 常見問題
| 症狀 | 可能原因 | 解法 |
|------|---------|------|
| 啟動 Stage 3 timeout | Windows Defender 首次掃 .exe | 等待,有 pause 機制不會 fail或加白名單 |
| 第二次啟動閃黑窗消失 | 前一次 crash 的 lock 殘留 | 刪 `visiona-local.lock` |
| 瀏覽器看不到裝置 | USB 權限Linux/ WinUSB driver 沒裝 | Linux: `sudo bash install-udev.sh`Windows: 從 UI 點「安裝 Kneron USB 驅動程式」 |
| 模型庫是空的 | 首次啟動 seed 失敗 | 檢查 `wails.log` 的 seed 訊息;或手動複製 `models.json + nef/` 從 installer 到 user dataDir |