iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
自我挑戰組

一塊板子,兩個腦袋:Arduino UNO Q 30 天實戰系列 第 26

Day 26|用 Python 主動更新網頁狀態

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20260828/20058745KIUJTICsHY.png

Web 按鈕已能控制實體 LED,今天要讓網頁等 MCU 回報後再更新狀態。

Python 推送固定資料格式

Day 16 已建立 {"status": label},今天直接沿用這個格式,不重新定義欄位,也不在 JavaScript 自行推算 ON/OFF。

on_led_status() 修改如下。

def on_led_status(state: bool):
    label = "ON" if state else "OFF"
    message = {"status": label}

    print("LED 狀態:", message["status"])
    ui.send_message("led_update", message)  # 本日新增

ui.send_message() 的第一個參數是事件名稱 "led_update",第二個參數是要送給瀏覽器的字典,Web 端收到後會以 data.status 取得內容。

事件名稱負責選擇哪一個 JavaScript listener,資料欄位則負責提供 listener 需要的內容,兩者功能不同,led_update 必須與 socket.on() 一致,status 則必須與 data.status 一致。

這個函式只在 MCU 回報後執行,因此送出的 ON/OFF 代表硬體已完成的真正結果,而不是瀏覽器剛才提出的要求。

JavaScript 監聽 led_update

assets/app.js 中加入以下接收程式。

// 本日新增
socket.on("led_update", (data) => {
  statusEl.textContent = data.status;
  statusEl.className = data.status === "ON" ? "on" : "off";
});

socket.on() 會持續等待 "led_update",事件到達後執行箭頭函式,data 就是 Python 傳來的資料物件。

textContent 修改狀態區的文字,className 則依 ON/OFF 選擇 onoff,CSS 會自動套用對應顏色。

更新文字與 class 要在同一個 callback 中完成,避免畫面出現文字已是 ON、顏色卻仍使用 off 的短暫不一致,收到一筆 MCU 結果後,前端應一次完成整組顯示更新。

JavaScript 條件運算式

data.status === "ON" ? "on" : "off" 是 JavaScript 條件運算式,若狀態文字完全等於 "ON",就將 class 設成 "on",否則設成 "off"

三個等號 === 代表嚴格比較,這裡比較的是字串內容,不使用單一等號,因為單一等號是指定值,不是判斷是否相等。

這項判斷只決定顯示樣式,不會產生新的硬體狀態,真正資料仍來自 data.status

遠端操作完整往返

重新執行 App,開啟頁面後點擊切換按鈕,D2 LED 應切換,Python Console 顯示 ON 或 OFF,瀏覽器文字與顏色接著同步更新。

完整路徑是 Web 發出 toggle_led、Python 呼叫 MCU、MCU 更新 ledState、回報 led_status、Python 推送 led_update,最後 JavaScript 更新畫面。

若 LED 有變化但頁面沒有更新,先確認 Python 是否執行 ui.send_message(),再檢查兩端事件名稱 "led_update" 與欄位 status 是否一致。

也可在 JavaScript listener 內暫時加入 console.log(data),確認瀏覽器是否收到物件,若已收到卻沒有更新,問題就在 DOM 或條件式,若完全沒收到,則回到 Python 推送與 Socket.IO 連線。

現場按鈕也會更新畫面

按下 D9 實體按鈕時,MCU 同樣使用 toggle_led(),完成後會回報 led_status,Python 再推送 led_update,因此頁面也應同步變化。

這表示遠端與現場雖有不同入口,最後都使用同一條狀態回報路徑,瀏覽器不需要分辨切換來源,只要接收 MCU 的真正結果。

多個瀏覽器使用同一事件

ui.send_message() 會把狀態事件推送給連線中的管理頁面,因此不同裝置若同時開啟介面,都能收到相同的 ON/OFF。

本篇不建立每個瀏覽器自己的狀態資料,所有畫面都只是顯示同一份 MCU 回報,這能避免不同裝置各自猜測燈號。

測試時可先用 Web 切換一次,再用 D9 切換一次,兩次都應觸發完全相同的 led_update listener,若只有 Web 操作會更新,代表回報可能被錯放在遠端專用路徑,應回到 MCU 的共同 toggle_led() 檢查。

最終畫面必須同時更新文字與顏色,不能只改 ON/OFF 而保留上一個 class,文字與顏色必須同時一致。

Web 顯示、Python 輸出與實體 LED 三者一致,才代表狀態回程真正完成。

本篇完成內容

  • Python 使用 ui.send_message() 推送狀態。
  • JavaScript 以 socket.on() 接收 led_update
  • 更新狀態文字與 ON/OFF class。
  • 完成 MCU → MPU → Web 狀態鏈。

現在網頁已能依 MCU 回報更新文字與顏色,遠端控制需要的兩條路徑都已建立,下一篇要從 Web 按鈕開始完整驗收整條遠端控制流程。

下一篇|從 Web 串起遠端控制完整路徑


上一篇
Day 25|把前端 Web 操作送到後端 Python
下一篇
Day 27|從 Web 串起遠端控制完整路徑
系列文
一塊板子,兩個腦袋:Arduino UNO Q 30 天實戰30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言