MCU 已經會回報真正狀態,今天要把 Python 收到的布林值整理成 ON/OFF。
Python 的條件運算式可以根據真假值選擇結果,寫法是 "ON" if state else "OFF",當 state 為 True 時得到 "ON",否則得到 "OFF"。
這項轉換只處理顯示文字,不會反過來修改 MCU 的 ledState,Python 仍然以收到的硬體結果為準,避免上層服務形成第二份可自行變動的 LED 狀態。
只有一段 "ON" 文字雖然能閱讀,後續傳給 Web 時仍需要知道它代表什麼,因此再將結果放入 {"status": label},以 status 作為固定欄位名稱。
Python 字典使用大括號保存鍵值配對,冒號左邊是欄位名稱,右邊是對應資料,未來即使增加其他訊息,Web 仍可從 status 取得目前燈號狀態。
欄位名稱一旦確定就應保持一致,若今天使用 status,後續 JavaScript 也會依這個名稱讀取內容,隨意改成 state 或 led 會讓資料雖然成功送出,接收端卻找不到預期欄位,因此資料格式本身也是介面的一部分。
將 Day 15 的 Python 接收函式改成以下內容,Bridge 登記方式與下行測試呼叫保持不變。
from arduino.app_utils import App, Bridge
service_name = "Intersection Edge Service"
service_ready = True
def on_led_status(state: bool):
label = "ON" if state else "OFF" # 本日新增
message = {"status": label} # 本日新增
print("LED 狀態:", message["status"]) # 本日新增
def on_toggle_led(client_id, data):
Bridge.call("toggle_led")
print("已要求 MCU 切換 LED")
Bridge.provide("led_status", on_led_status)
print("Service ready:", service_name)
on_toggle_led(None, None)
App.run()
label 保存轉換後的文字,message 保存具有固定欄位的字典,message["status"] 則取出該欄位內容供 print() 顯示。
這三個步驟刻意分開,不直接在 print() 中塞入所有運算,讀者可以先檢查原始 state,再確認 label 是否正確,最後查看字典欄位,當資料顯示不符預期時,除錯位置會比一行完成所有工作更清楚。
變數名稱刻意反映資料處理過程,state 是 MCU 傳來的原始布林值,label 是可讀文字,message 是準備交給上層使用的資料,除錯時能清楚看出問題出在哪一層。
按下 Run 後,啟動測試命令會切換 D2,Python Console 應顯示 LED 狀態: ON 或 LED 狀態: OFF,顯示結果必須與實體 LED 一致。
接著連續按下 D9,每次切換都應出現新的 ON/OFF,若 Console 顯示內容沒有變化,先確認 MCU 是否確實回報新的 ledState,不要直接在 Python 端自行反轉 label。
測試時可依序記錄 LED 亮滅、MCU 布林值與 Python 文字,三者應形成亮燈、True、ON,以及熄燈、False、OFF 的固定對應,只有這兩組結果都正確,才表示資料轉換沒有顛倒。
保留原始狀態與顯示資料的界線
state 是 Bridge 傳入的事實,label 與 message 則是 Python 依這個事實產生的顯示資料,若日後文字需要改成中文,只要調整轉換結果,不必改動 MCU 回報的布林格式,硬體通訊與畫面呈現便能各自演進,也不會因顯示用詞改變而破壞兩顆大腦之間的資料契約。
本日建立 message 字典只是固定資料格式,尚未匯入 WebUI,也沒有呼叫 ui.send_message(),因此瀏覽器不會收到任何狀態更新。
這個界線很重要,Day 16 只負責將硬體資料整理成可讀資訊,下一階段建立 Web 後,才能把同一份 message 傳給畫面,不必重新定義 ON/OFF 的意義。
status 欄位。print() 檢查資料轉換結果。現在 Python 已能把硬體狀態轉成 ON/OFF,也有固定資料格式,下一篇先不做網頁,而是把 MCU 與 MPU 的雙向流程完整驗收一次。
下一篇|階段驗收 Edge Box 2.0