YiBi Dev Docs
架構決策 (ADR)

IoT Simulator 每個模擬裝置使用獨立 WebSocket + 狀態 in-memory

Context

IoT Simulator Admin Console 需要支援同時模擬多個裝置,Admin UI 要即時看到每個裝置的狀態與 MQTT 訊息。 需要決定通訊架構(單一 WebSocket vs 多路 vs polling)以及 session 狀態的持久化方式(DB vs in-memory)。

Decision

結論(通訊):每個模擬裝置使用獨立的 WebSocket 連線,同時承載控制命令(client → server)和 MQTT 事件(server → client)。

結論(持久化):Simulator session 存在 SimulatorManager._sessions dict in-memory,不寫入 DB。

Alternatives Considered

通訊方案

  • 單一 WebSocket + message type multiplexing — 考慮過。多裝置共用單一 WS 需在協議層加裝置 ID routing,邏輯複雜,前端訂閱過濾也難做。
  • HTTP polling — 考慮過。MQTT 事件實時性要求高(heartbeat 每秒),polling 延遲不可接受。

持久化方案

  • DB 持久化 simulator session — 考慮過。simulator 是 dev-only 工具,DB 寫入增加不必要的 schema 複雜度;backend 重啟後 session 自然失效是可接受行為(開發環境)。
  • Redis 短期持久化 — 考慮過。增加依賴,收益僅為「backend 重啟後 session 存活」,對 dev tool 不值得。

Consequences

  • 每個裝置的 WebSocket 連線天然隔離,前端可針對單一裝置訂閱事件
  • In-memory session 零 DB 依賴,適合 dev/testing 環境使用
  • 前端 WebSocket 重連時自動建立新 session,行為直觀

壞 / 代償

  • Backend 重啟後所有 simulator session 消失(設計上接受此限制)
  • 前端需處理 WebSocket 斷線 reconnect 邏輯
  • asyncio.Lock 必須保護每個 session 防止 WS 命令與 MQTT event handler 並發競爭

中性

  • Hybrid command routing:lifecycle 命令(pair/remove/reset)在 SimulatorEngine 直接處理;device control 命令(pause/resume/volume)可透過 MQTT round-trip 測試完整流程
  • Sleep timer、volume 等命令在 WebSocket handler 做 input validation(非負數、0-100 範圍)

On this page