Pico 2 W × Thonny|第 3 次課程
Pico Web Server 與網頁控制
前一堂讓 Pico 2 W 加入 Wi-Fi 網路;這一堂進一步讓它成為 Web Server。手機或電腦用瀏覽器連到 Pico 的 IP,讀取它送出的網頁,再透過網址路徑送出控制要求,讓板載 LED 亮起或熄滅。
作者:施朝斌一、瀏覽器與 Pico 如何對話?
當瀏覽器開啟一個網址,它會扮演 Client(用戶端),向提供服務的設備送出 HTTP Request(請求)。Pico 扮演 Server(伺服端),接收請求後回傳 HTTP Response(回應),內容可以是 HTML 網頁,也可以是文字或 JSON。
HTTP 通訊通常使用 TCP 連線。簡化來看,伺服器建立 Socket、綁定連接埠並等待連線;瀏覽器連進來後,伺服器讀取 Request、組成 Response、傳送回去,再關閉這次連線。
二、URL 路徑可以代表控制命令
本課程把不同路徑當作簡單命令:瀏覽器要求 /on,Pico 就開啟 LED;要求 /off,Pico 就關閉 LED;要求 /status,則回傳目前 LED 狀態。瀏覽器並不是直接碰觸 GPIO,而是把 HTTP 要求交給 Pico,由 Pico 程式執行控制。
三、建立第一個 Pico Web Server
以下範例把前一堂的 Wi-Fi 連線與本堂的 HTTP Server 串在一起。請先將 SSID 和 PASSWORD 換成課堂核准的測試網路資訊,執行程式後從 Shell 記下 Pico 顯示的 IP,再用同一個區域網路內的手機或電腦瀏覽器開啟該位址。
import network
import socket
import time
from machine import Pin
SSID = "請填入 Wi-Fi 名稱"
PASSWORD = "請填入 Wi-Fi 密碼"
HTTP_PORT = 80
led = Pin("LED", Pin.OUT)
led.value(0)
# 連接 Wi-Fi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
for attempt in range(20):
if wlan.isconnected():
break
print("Connecting...", attempt + 1)
time.sleep(1)
if not wlan.isconnected():
raise RuntimeError("Wi-Fi connection failed")
ip_address = wlan.ifconfig()[0]
print("Open this address in a browser:", ip_address)
# 建立並啟動 Web Server
address = socket.getaddrinfo("0.0.0.0", HTTP_PORT)[0][-1]
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(address)
server.listen(1)
print("Web Server is ready")
while True:
client, client_address = server.accept()
try:
request = client.recv(1024)
request_text = request.decode()
print("Request:", request_text.split("\r\n")[0])
request_line = request_text.split("\r\n")[0]
parts = request_line.split(" ")
path = parts[1] if len(parts) > 1 else "/"
if path == "/on":
led.value(1)
elif path == "/off":
led.value(0)
if path not in ("/", "/on", "/off", "/status"):
status_line = "HTTP/1.0 404 Not Found"
message = "Page not found"
else:
status_line = "HTTP/1.0 200 OK"
message = "LED is ON" if led.value() else "LED is OFF"
page = """<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Pico Control</title></head>
<body>
<h1>Pico 2 W Control Panel</h1>
<p>Current status: {}</p>
<p><a href="/on">LED ON</a> | <a href="/off">LED OFF</a> | <a href="/status">Refresh status</a></p>
</body>
</html>""".format(message)
response = (
status_line + "\r\n"
+ "Content-Type: text/html; charset=utf-8\r\n"
+ "Connection: close\r\n"
+ "\r\n"
+ page
)
client.send(response.encode())
except Exception as error:
print("Request handling error:", error)
finally:
client.close()
Socket 綁定在 0.0.0.0,表示接受本機各網路介面的連線;HTTP 使用的連接埠是 80。程式在 Shell 印出 IP 後會持續等待瀏覽器連線,所以 Thonny 要保持程式執行中。若按 Stop,Web Server 也會停止。
四、HTML 只是 Pico 傳出的文字
Pico 不會像電腦一樣替你「畫出」網頁;它把 HTML 文字放進 HTTP Response,瀏覽器再負責解析與顯示。範例中的標題、狀態文字和連結都由 HTML 組成。修改標題或按鈕名稱,就能改變瀏覽器看到的控制面板。
這裡使用連結 <a href="/on">與 <a href="/off">,點選後瀏覽器會重新向 Pico 發出新要求。伺服器根據網址路徑執行對應動作,並回傳更新後的狀態。
五、第一次測試與除錯
- 確認 Pico 已連上 Wi-Fi,Shell 顯示取得的 IP 位址。
- 確認程式已印出 Web Server ready,且仍在執行。
- 手機或電腦連到與 Pico 相同、且允許裝置互通的區域網路。
- 在瀏覽器輸入
http://加上 Pico 的 IP 位址,例如http://192.168.x.x;實際 IP 以你的程式輸出為準。 - 點選 LED ON、LED OFF,觀察板載 LED,並查看 Shell 是否印出 Request。
如果網頁打不開,依序確認:Pico 是否有 IP、Server 是否仍在執行、瀏覽器是否使用正確 IP、裝置是否能互相連線,以及 Request 是否到達 Pico。校園或公共 Wi-Fi 可能啟用用戶端隔離,讓同一 Wi-Fi 的裝置也無法彼此連線;這時可改用經教師同意的測試網路。
六、實作挑戰:做自己的控制面板
- 將首頁標題改成自己的裝置名稱。
- 在頁面顯示 Pico 的 IP 與 Wi-Fi 連線狀態。
- 新增
/status路徑,顯示 LED 開或關。 - 加入一個 ADC 或感測器讀值,讓網頁同時呈現狀態與資料。
- 設計不同顏色的按鈕,或加入定時重新整理狀態的功能。
本篇重點回顧
- 瀏覽器是 Client,Pico Web Server 是 Server;兩者透過 HTTP Request 與 Response 溝通。
- Socket 程式負責等待連線、讀取請求、傳送回應與關閉連線。
- 網址路徑可對應控制命令,例如
/on與/off。 - Pico 傳送 HTML 文字,瀏覽器負責呈現畫面。
- 除錯時先確認 IP、伺服器狀態、網路互通與 Request 是否到達。
下一篇將從「瀏覽器連進 Pico」走向「Pico 主動向外送資料」,認識 HTTP GET/POST 與 REST API。
沒有留言:
張貼留言