MES I/O Gateway / 開發者 / 整合
04開發者 / 整合

韌體變更紀錄機制

從 cloud server 5.9.50 起,每次上傳韌體都必須夾帶 changelog。 沒帶或太短(< 10 chars)會被 cloud 直接 400 拒絕。 設計目的:避免 manifest / git log / wiki 等多處紀錄碎片化。


#為什麼這樣設計?

單一來源原則

release_firmware.py        →    Upload API (header)    →    Cloud Manifest    →    Admin UI
  --changelog ...               X-Firmware-Changelog-B64    firmware.json          顯示
  (or auto-git-log)             (base64-encoded UTF-8)      changelog field         /api/firmware
  • 唯一寫入點 = release_firmware.py
  • 唯一儲存 = cloud /app/firmware/<version>.json manifest 的 changelog 欄位
  • 唯一顯示 = admin UI 韌體列表展開
  • 不維護獨立 markdown / wiki / git 抓取(會跟 manifest 不同步)

#三種使用方式

#A) 直接字串(單行 / 短描述)

bash
python3 scripts/release_firmware.py --bump patch --upload https://opta.smms.com.tw \
  --changelog "WI-114: 強制 changelog upload + admin UI 展開"

#B) 從檔案讀(多行 markdown)

最推薦的方式 — CHANGELOG.md 跟 commit 一起入 git:

bash
# 寫一個 CHANGELOG.md(隨手寫,Markdown 格式)
cat > CHANGELOG.md <<EOF
## v5.9.50 — 2026-05-05

### Features
- WI-114: Cloud changelog 強制夾帶(單一來源防碎片化)
- Cloud admin UI 韌體列表加展開區塊

### Bug Fixes
- 修正 X-Firmware-Changelog header 多行字元編碼

### 升級注意
- 新版 cloud 拒絕沒 changelog 的 upload
EOF

# 用 @ 字首把檔讀進去
python3 scripts/release_firmware.py --bump patch --upload https://opta.smms.com.tw \
  --changelog @CHANGELOG.md

#C) 從 stdin 讀(CI / pipe)

bash
git log v5.9.49..HEAD --pretty='- %s' --no-merges \
  | python3 scripts/release_firmware.py --bump patch --upload https://opta.smms.com.tw \
      --changelog @-

#D) 自動從 git log 產生(沒帶 --changelog 時)

bash
python3 scripts/release_firmware.py --bump patch --upload https://opta.smms.com.tw
# 不帶 --changelog 時:
#   1. 嘗試 `git log v<prev>..HEAD --pretty='- %s' --no-merges`
#   2. 若 v<prev> tag 不存在,fallback 到最近 5 個 commits
#   3. 全部失敗 → 互動式 prompt 強制要求輸入

#編寫慣例(建議)

不強制,但 admin 看 changelog 時的可讀性很重要:

markdown
## v<version> — <YYYY-MM-DD>

### Features
- WI-XXX: short description
- 關鍵新功能或 endpoint

### Bug Fixes
- 修了什麼

### 升級注意 / Breaking Changes
- 客戶端需要做什麼動作(重 login?重新校時?)

### 內部變更
- refactor / 文件 / 工具

### Deploy notes
- ⚠️ Cloud 需要重啟 docker container?
- ⚠️ 此版本之後不允許降級?

對應「升級注意」段落,下次可考慮在 manifest 加 breakingChanges: bool 讓 admin UI 標紅醒目(sprint-28 候選)


#Cloud API 變動(v5.9.50+)

#POST /api/firmware/upload

新 header(推薦)

X-Firmware-Changelog-B64: <base64-encoded UTF-8 string>
  • 支援多行(\n)+ 中文 / 日文 / 任何 UTF-8
  • 解碼後 trim 至少 10 字元

舊 header(向後相容)

X-Firmware-Changelog: <plain string, URL-encoded>
  • 適合單行短描述
  • 不建議帶 newline / CJK

400 失敗回應

json
{
  "error": "Changelog required",
  "message": "Send X-Firmware-Changelog-B64 (base64 UTF-8, recommended for multi-line/CJK) or X-Firmware-Changelog header. Min 10 chars after decode.",
  "examples": {
    "base64": "echo -n \"WI-114: bug fixes\" | base64",
    "cli": "release_firmware.py --changelog \"...\" or --changelog @CHANGELOG.md"
  }
}

#GET /api/firmware

回傳列表,每筆含完整 changelog 欄位(可能多行 UTF-8)。


#既有韌體(5.9.49 以前)

Backfill 一次性處理:在 cloud 升 5.9.50 之前,sprint-27 已執行:

js
// 對 changelog 缺失或太短的 manifest 補上
m.changelog = "(legacy, no changelog record — see git log v5.9.X)";

4 筆被補(5.9.8 / 5.9.40 / 5.9.41 / 5.9.42),其餘 9 筆原本就有有意義的 changelog。

Admin UI 對 (legacy 開頭的 changelog 顯示為灰色斜體,方便辨識


#Troubleshooting

#Q1: release_firmware.py 沒帶 --changelog,又沒 git tag?

腳本順序:

  1. git log v<prev>..HEAD — 嘗試找 prev tag(沒有 tag 表示沒打 release tag)
  2. 若失敗,fallback git log HEAD~5..HEAD
  3. 若仍失敗(lab 機器沒 git),互動式 prompt 強制輸入

如果連互動式 prompt 也沒人輸入,最終 sys.exit(1) — 不會白編譯 + 丟個沒記錄的 binary 上去。

#Q2: 我已經 build 好 .bin 了,可以直接 curl upload 嗎?

可以,但要自己處理 base64:

bash
CHANGELOG=$(cat CHANGELOG.md | base64)
curl -X POST https://opta.smms.com.tw/api/firmware/upload \
  -H "Authorization: Bearer admin-token" \
  -H "Content-Type: application/octet-stream" \
  -H "X-Firmware-Version: 5.9.50" \
  -H "X-Firmware-Changelog-B64: $CHANGELOG" \
  --data-binary @release/mes-gateway-v5.9.50-20260505.bin

#Q3: Changelog 改完了想覆寫 manifest?

目前沒 PUT/PATCH endpoint。兩種選擇:

  • 直接 SSH 到 cloud 改 /app/firmware/<version>.json(admin 可做)
  • 重新跑 release_firmware.py(會以新時間戳產出新 .bin,舊的還在)

未來如果有需求,可以加 PATCH /api/admin/firmware/:filename/changelog endpoint(sprint-28 候選)

#Q4: changelog 欄位 size 上限?

Cloud server 沒設限(manifest JSON 寫多大都可以)。實務上保持在 5KB 內,admin UI 才好看。


#近期版本重點(v5.9.241 ~ v5.9.244 — 8310 機型支援)

ℹ️ 權威 changelog 仍在 cloud manifest(單一來源,見上)。本段為文件側快速索引,方便對照本批 8310 相關改動, 對應 sprint cards WI-149 ~ WI-152。

版本 重點 卡片 / 記憶
v5.9.241 8310 安裝根治:QSPI 空白 MBR 回 -3101,舊韌體只救 -3102 → FS 不掛載 → 設定/網路存不了。src/LocalConfig.h 救援涵蓋 -3101 + -3102,任何空白 QSPI 設備第一次燒就自我建分割區 + 格式化(相容 8320,init 成功就跳過)。 WI-149 前置、[[opta_8310_qspi_blank_mbr_3101]]
v5.9.242 ~ .244 拓荒包(Pioneer)韌體變體 + 開荒設定頁env:opta_pioneer,WI-149):自包單一網頁(UID + 網路 + 大「上傳 .mesb」鈕),USB 首燒即可用。 WI-149
型號感知 UI 過濾(WI-151):OTP 讀板型 → g_hasWifi,曝光 /api/system/api/licensehasWifi/boardModel;8310 拓荒頁與完整版網路設定過濾掉 WiFi(隱藏 SSID/密碼 + 介面模式選單,強制乙太網路)。 WI-151、[[opta_otp_board_functionalities]]
8310 心跳燈(WI-152):藍燈是 BLE 模組燈(僅 WiFi 版能亮),8310 改用**琥珀色(紅+綠同亮)**心跳,8320 維持藍燈。 WI-152
.mesb 一鍵完整安裝 + favicon + ETag 修正.mesb 打包韌體 + 6 資產 + favicon.ico;拓荒頁內嵌真 favicon;根網頁 ETag 併入頁面大小,避免 pioneer→完整版(同版號)OTA 後顯示舊快取頁。 WI-149

注意:AP 模式需要 WiFi,只有 8320 能進;8310 無 WiFi 進不了 AP(會 fallback)。User button 開機長按:0-5s 正常 / 5-10s AP / 10s+ 原廠重置。


#相關程式(原始碼,非本站文件)

  • scripts/release_firmware.py — 打包腳本(含 resolve_changelog
  • config-server/modules/firmware.js — Cloud upload endpoint
  • config-server/public/index.html — Admin UI 韌體列表