韌體變更紀錄機制
從 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>.jsonmanifest 的changelog欄位 - 唯一顯示 = admin UI 韌體列表展開
- 不維護獨立 markdown / wiki / git 抓取(會跟 manifest 不同步)
#三種使用方式
#A) 直接字串(單行 / 短描述)
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:
# 寫一個 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)
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 時)
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 時的可讀性很重要:
## 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 失敗回應:
{
"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 已執行:
// 對 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?
腳本順序:
git log v<prev>..HEAD— 嘗試找 prev tag(沒有 tag 表示沒打 release tag)- 若失敗,fallback
git log HEAD~5..HEAD - 若仍失敗(lab 機器沒 git),互動式 prompt 強制輸入
如果連互動式 prompt 也沒人輸入,最終 sys.exit(1) — 不會白編譯 + 丟個沒記錄的 binary 上去。
#Q2: 我已經 build 好 .bin 了,可以直接 curl upload 嗎?
可以,但要自己處理 base64:
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/changelogendpoint(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/license 的 hasWifi/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 endpointconfig-server/public/index.html— Admin UI 韌體列表