設備心跳+線上狀態+雲端健康監控版:讓故事機自己回報「我還正常運作」
V1.0-11已完成設備身分、Django事件同步與Flash離線佇列;V1.0-12再向前一步,加入低優先權設備心跳,讓管理者從雲端儀表板確認每台故事機是ONLINE或OFFLINE,以及目前狀態與韌體版本。
一、為什麼故事機需要「心跳」?
故事播放正常,不代表管理者隨時知道設備是否健康。故事機部署在社區、展場或兒童館後,可能遇到斷電、分享器失效、Wi-Fi中斷、程式重啟或設備長時間沒有回報等狀況。
若沒有心跳,雲端只能看到「最後一筆故事事件」,卻無法判斷設備是安靜待機,還是已經離線。V1.0-12因此讓HUB 8735 Ultra每隔60秒主動向Django報到。
二、V1.0-12心跳包含哪些資訊?
心跳不是故事事件,不需要永久保存在Flash。它是一份設備當下的健康摘要:
{
"device_id": "SHUIJING-002",
"state": "IDLE",
"firmware": "V1.0-12",
"rssi": -24,
"uptime": 3600,
"volume": 16,
"queue_count": 0,
"current_track": 0,
"jq_recoveries": 0,
"last_cloud_http": 201,
"last_error": ""
}
| 欄位 | 用途 | 管理意義 |
|---|---|---|
device_id | 設備唯一編號 | 區分不同展場與故事機 |
state | IDLE、PLAYING或ERROR | 知道設備正在待機、播放或異常 |
firmware | 韌體版本 | 確認設備是否完成升級 |
rssi | Wi-Fi訊號強度 | 找出連線不穩的場域 |
queue_count | 尚未同步事件數 | 判斷Django或網路是否阻塞 |
jq_recoveries | 播放器復原次數 | 觀察JQ6500長期穩定性 |
三、心跳不能影響故事播放
展場系統最重要的仍是使用者操作。因此V1.0-12把心跳放在最低優先層級:
- 實體按鈕與停止操作。
- JQ6500播放與BUSY狀態機。
- 手機Web控制。
- Flash離線事件補送。
- 設備心跳。
四、開機測試:先送重要事件,再送心跳
V1.0-12沿用V1.0-11的Flash資料結構,開機後成功恢復音量、STA設定、事件序號與佇列:
[FLASH] V1.0-11 data restored
[FLASH] Volume = 16
[FLASH] Boot count = 54
[CLOUD] Device ID: SHUIJING-002
[CLOUD] Offline queue: 0
接著建立本次開機事件:
[CLOUD QUEUE] + SHUIJING-002-0000000016 | DEVICE_BOOT | pending=1
STA與NTP完成後,系統先把重要的DEVICE_BOOT送到Django:
[TIME] Synced by NTP | 2026-08-25 10:44:06
[MODE] STA online service ready
[CLOUD] POST SHUIJING-002-0000000016 | pending=1
[CLOUD] Accepted HTTP 201 | remaining=0
只有在事件佇列回到0以後,才開始傳送心跳:
[HEARTBEAT] POST | state=IDLE | queue=0
[HEARTBEAT] Accepted HTTP 200
五、連續心跳實測
序列監控顯示,故事機約每分鐘傳送一次心跳,而且每次均獲得Django的HTTP 200:
10:46:07 [HEARTBEAT] POST | state=IDLE | queue=0
10:46:09 [HEARTBEAT] Accepted HTTP 200
10:47:07 [HEARTBEAT] POST | state=IDLE | queue=0
10:47:09 [HEARTBEAT] Accepted HTTP 200
10:48:07 [HEARTBEAT] POST | state=IDLE | queue=0
10:48:09 [HEARTBEAT] Accepted HTTP 200
10:49:07 [HEARTBEAT] POST | state=IDLE | queue=0
10:49:09 [HEARTBEAT] Accepted HTTP 200
從紀錄可觀察到每次HTTPS請求約在兩秒內完成;下一次心跳不會緊接著大量重複送出,而是依照週期執行。
六、Django儀表板成功判斷ONLINE
Django以設備最後收到心跳的時間判斷線上狀態。實測畫面中,舊設備SHUIJING-001因長時間沒有心跳而顯示OFFLINE;目前測試設備SHUIJING-002則顯示ONLINE,並正確呈現IDLE / V1.0-12。
儀表板實測結果
- SHUIJING-001:OFFLINE,顯示舊韌體資訊。
- SHUIJING-002:ONLINE,狀態IDLE,韌體V1.0-12。
- 故事啟動:6次。
- 完整播放:6次。
- 播放完成率:100%。
- 互動來源:實體按鈕5次、Edge Web 1次。
七、Django如何判斷設備是否在線?
API收到心跳後更新last_seen、last_state、firmware_version與last_rssi。儀表板再依最後回報時間判定設備狀態:
online_cutoff = timezone.now() - timedelta(minutes=10)
online = bool(
device.last_seen and
device.last_seen >= online_cutoff
)
正式展場可依網路品質調整門檻。若心跳每60秒一次,常見做法是:
| 最後心跳距今 | 建議狀態 | 管理判讀 |
|---|---|---|
| 2分鐘內 | ONLINE | 設備正常 |
| 2至5分鐘 | WARNING | 可能網路不穩 |
| 超過5分鐘 | OFFLINE | 需要遠端或現場檢查 |
八、HTTP狀態碼如何判讀?
| 紀錄 | 意義 | 處理方式 |
|---|---|---|
HTTP 200 | 心跳更新成功 | 設備維持ONLINE |
HTTP 201 | 事件建立成功 | 從Flash佇列移除該事件 |
HTTP 400 | JSON或欄位不合API規則 | 查看Django回應本文 |
HTTP 401 | 設備驗證失敗 | 檢查Device ID、API Key與啟用狀態 |
-1/-2 | 連線或等待逾時 | 檢查STA、DNS、TLS與伺服器 |
-3 | 心跳被現場操作取消 | 正常設計,稍後自動再試 |
九、V1.0-12驗收結果
- V1.0-11的Flash設定與統計成功延續。
- STA連線與NTP自動校時正常。
DEVICE_BOOT取得HTTP 201並從佇列移除。- 事件佇列為0後才開始傳送心跳。
- 連續多次心跳均取得HTTP 200。
- Django正確顯示SHUIJING-002為ONLINE。
- Django正確顯示IDLE與V1.0-12。
- 不同設備可以同時顯示ONLINE與OFFLINE。
- 心跳不寫入Flash,不增加Flash耗損。
- 按鈕、播放、停止、Web與事件補送仍具有較高優先權。
十、從「會播放」走向「可維護」
早期的故事機只要按下按鈕會播放,就可以稱為功能完成。但真正進入社區與展場後,管理者需要知道:設備是否在線、使用哪一版韌體、Wi-Fi訊號是否穩定、離線事件是否堆積,以及播放器是否經常復原。
V1.0-12加入的不是一個華麗功能,而是一項非常重要的營運能力:讓設備主動說明自己的健康狀況。這也是IoT系統從作品原型走向可管理、可維護及可擴充服務的重要分界。
沒有留言:
張貼留言