
重新啟動 App,確認 D2 依 ledState = false 初始化為熄滅,管理頁面初始顯示 OFF,Python Edge Service 進入等待狀態。
驗收過程應先固定同一份 Day 26 程式,不在觀察途中修改事件名稱或加入額外輸出,若發現異常,先記錄命令停在哪一層,再針對該層檢查,避免改動後失去可重現條件。
開啟瀏覽器 Console 與 Python Console,前者用來檢查 JavaScript 錯誤,後者用來觀察 Web 命令與 MCU 回報,測試期間先不要按下 D9,以免混入另一條操作路徑。
點擊「切換 LED」後,按鈕外觀應產生 active 回饋,JavaScript 執行 click callback 並呼叫以下程式。
socket.emit("toggle_led", {});
此時前端不應先將 OFF 改成 ON,若畫面在 LED 動作前就自行變化,代表程式違反等待 MCU 回報的規則。
若 Python 完全沒有訊息,問題多半仍在 Socket.IO 連線、事件名稱或 ui.on_message(),不必先檢查 D2 腳位。
Python 收到 "toggle_led" 後,on_toggle_led(client_id, data) 應執行,Console 顯示收到 Web 命令,再呼叫以下程式。
Bridge.call("toggle_led")
如果 Python 能收到事件但 LED 沒有變化,應比對 Python 與 MCU 是否都使用同一個 "toggle_led",並確認 MCU 已執行 Bridge.begin() 與 Bridge.provide()。
這一層只轉送命令,不保存 ON/OFF,也不修改網頁資料。
MCU 收到呼叫後進入 on_toggle_led(),再呼叫既有的 toggle_led(),由它反轉 ledState、更新 D2,並送出 led_status。
遠端命令與 D9 按鈕共用相同函式,因此去除操作來源後,真正的硬體規則只有一套。
第一次測試應由 OFF 變成 ON,第二次再由 ON 變成 OFF,每次點擊只切換一次,若一次操作出現多次變化,應檢查前端是否重複登記事件監聽器。
MCU 回報後,Python on_led_status() 將布林值轉成 ON/OFF,並以 "led_update" 推送到 Web,JavaScript 收到後才更新 textContent 與 className。
驗收時應觀察 LED 先完成切換,畫面再顯示相同結果,不能只看按鈕是否有反應,也不能以瀏覽器文字取代實體輸出檢查。
若 Python 已印出 ON/OFF,頁面卻沒更新,問題應集中在 ui.send_message()、socket.on() 或 data.status。
每一層都能提供不同證據,瀏覽器 Console 證明 click 與 Socket.IO,Python Console 證明 WebUI 與 Bridge,實體 LED 證明 MCU 執行,最後的狀態文字則證明回程完整,四種證據缺少一項都不算驗收通過。
連續操作與分層除錯
連續點擊五次,每次等待畫面完成更新後再進行下一次,LED、Python 與 Web 應依序交替 ON、OFF,而且三層始終一致。
接著可稍微加快速度,確認事件仍逐次抵達,但本日不以極端快速操作當成主要測試,Day 29 才會正式進行現場與網頁交替壓力驗證。
分層追蹤的價值在於每一步都有可觀察結果,錯誤發生時能判斷停在哪一層,不必同時修改所有檔案。
驗收完成後應恢復乾淨的 Console,移除只為定位問題而暫時加入的重複輸出,保留必要訊息即可。
toggle_led。toggle_led() 切換 D2。led_status 回報後才更新。現在遠端控制路徑已通過驗證,但控制箱旁的人按下 D9 時,瀏覽器也必須同步更新,下一篇要專門驗收現場操作回到管理畫面的反向路徑。
下一篇|從現場串起遠端控制完整路徑