National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 15

用 Flask 做網頁控制面板

用瀏覽器開關 LED、查看感測值
Interaction 30 minute(s)

Learning Objectives

  • 說明瀏覽器與網頁伺服器之間的 HTTP 請求與回應
  • 用 Flask 的路由把網址對應到 Python 函式,控制 GPIO 上的 LED
  • 用網址變數與查詢字串接收參數,回傳文字、狀態碼與 JSON
  • 說明 host="0.0.0.0"、連接埠與開發伺服器的安全限制

用手機控制樹莓派

到目前為止,要控制樹莓派得連上終端機、執行程式。如果讓樹莓派當一台網頁伺服器, 同一個網路上的任何手機或電腦,打開瀏覽器輸入網址,就能看到感測器的數值、按按鈕開燈。

這一課用 Flask:一個輕量的 Python 網頁框架,幾行程式就能做出網頁伺服器。

瀏覽器和伺服器在說什麼

瀏覽器每打開一個網址,就送出一個 HTTP 請求;伺服器處理之後送回一個 HTTP 回應:

瀏覽器 → 伺服器:GET /led/on HTTP/1.1          (方法、路徑、版本)
伺服器 → 瀏覽器:HTTP/1.1 200 OK               (狀態碼)
                LED 已打開                       (內容)
狀態碼 意思
200 成功
400 請求有問題(例如參數不對)
404 找不到這個路徑
500 伺服器的程式出錯

「計算機概論」軌的 HTTP 課有更完整的介紹。

Flask 的路由

Flask 官方文件裡最小的程式:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"
  • app = Flask(__name__) 建立應用程式物件。
  • @app.route("/") 是裝飾器:把下面的函式登記成「網址 / 的處理函式」。這叫路由(route)。
  • 函式回傳的字串就是回應的內容(預設當成 HTML)。

在樹莓派上執行:

寫法 誰連得到
app.run() 只有樹莓派自己(127.0.0.1),預設連接埠 5000
app.run(host="0.0.0.0", port=5000) 同一個網路上的其他裝置,網址是 http://樹莓派的IP:5000/

網址裡可以有變數:@app.route("/led/<state>") 讓 /led/on、/led/off 都進到同一個函式,state 參數收到 "on" 或 "off"。

模擬器怎麼運作:模擬的 Flask 不會真的開網路連線。電路規格裡有一張「誰在什麼時間送來什麼請求」的時間表, app.run() 依時間收到請求、呼叫你的函式,電路畫面下方會列出收到的請求與送出的回應。

逐步看:網址控制 LED

程式先登記兩個路由,再在第 21 行開始等待。請求的時間表是:0.6 秒 GET /、1.5 秒 GET /led/on、2.5 秒 GET /led/blink(不認得)、3.5 秒 GET /led/off。 看電路畫面下方的請求與回應,以及每次請求執行了哪幾行。

給程式看的網頁:JSON

給人看的網頁回傳 HTML;給其他程式(手機 App、另一台電腦的資料分析程式)用的網址,通常回傳 JSON。 在 Flask 裡,處理函式回傳一個字典,Flask 就會自動轉成 JSON 回應:

@app.route("/api/sensor")
def sensor():
    return {"temp": 26.1, "unit": "C"}      # 回應:{"temp": 26.1, "unit": "C"}

網址後面 ? 開始的部分叫查詢字串(query string),例如 /api/sensor?unit=F。 Flask 用 request.args.get("unit", "C") 取值;第二個引數是沒有傳時的預設值,這樣網址少了參數也不會出錯。

下一個範例的溫度感測器在 4 秒內從 25°C 升到 29°C,每次有請求時才讀一次。

逐步看:感測器 API 與查詢字串

請求時間表:0.8 秒 GET /api/sensor、2 秒 GET /api/sensor?unit=F、3 秒 GET /api/sensors(多打了一個 s)。看第三個請求:沒有任何一行程式執行,Flask 直接回 404。

互動練習:完成燈光控制面板

請求時間表固定是:0.5 秒 GET /、1.5 秒 GET /led/on、2.5 秒 GET /led/off、3.5 秒 GET /status。 起始程式只有開燈。依序完成任務,每次改完按「模擬執行」,看電路畫面下方的回應:

  1. 直接執行,看哪些請求得到 404。
  2. 加上 /led/off 的路由,讓燈在 2.5 秒關掉。
  3. 加上 /status 的路由,回傳字典 {"led": "on"} 或 {"led": "off"}(用 led.is_lit 判斷)。
  4. 回答一個問題。

小測驗:路由與回應

1.

有路由 @app.route("/led/<state>"),瀏覽器請求 /led/on/now,會怎樣?

2.

處理函式寫 return "不認得的指令", 400,瀏覽器收到的狀態碼是多少?

3.

下面的程式模擬 Flask 處理 /api/sensor?unit=F 時的計算,會印出什麼?

args = {"unit": "F"}
temp = 25.0
unit = args.get("unit", "C")
if unit == "F":
    print({"temp": round(temp * 9 / 5 + 32, 1), "unit": "F"})
else:
    print({"temp": temp, "unit": "C"})
第 1 次作答

安全:控制面板只放在自己的網路

能控制硬體的網頁,被陌生人連上就是真實世界的問題(燈被亂開、馬達被亂轉)。Flask 官方文件特別提醒:

  • flask run 或 app.run() 啟動的是開發用的伺服器,適合測試,不適合正式上線;正式部署要換成專門的伺服器(官方文件的「Deploying to Production」一章)。
  • 除錯模式(debug)出錯時會在瀏覽器顯示互動式除錯器,可以執行任意 Python 程式碼;絕對不要在別人連得到的網路上開啟。
  • 只有在關閉除錯器、或信任同一個網路上的使用者時,才用 host="0.0.0.0" 對外開放。

實務上的原則:

  1. 控制面板只放在家裡或實驗室的區域網路,不要直接開放到網際網路(不要在路由器上設定連接埠轉送)。
  2. 會改變狀態的動作(開燈、關門)在正式的系統裡要用 POST 請求並加上登入;本課為了簡單用 GET。
  3. 使用者送來的文字放回網頁前要跳脫(Flask 的範本會自動做),或者像範例一樣不要放回去。

下一課的 MQTT 是另一種讓裝置交換資料的方式,適合很多台裝置一起工作。

小測驗:部署與安全

1.

關於 Flask 的開發伺服器與除錯模式,下面哪一個說法正確?

2.

同學想在宿舍外也能用手機開關房間的燈,最不建議哪一種做法?

第 1 次作答

重點整理

  • 瀏覽器送 HTTP 請求(方法+路徑),伺服器送回應(狀態碼+內容)。
  • app = Flask(__name__) 建立應用程式;@app.route("網址") 把網址對應到處理函式。
  • <state> 是網址變數;request.args.get("key", 預設值) 讀查詢字串。
  • 回傳字串=HTML/文字;回傳 (內容, 狀態碼) 指定狀態碼;回傳字典=JSON。
  • app.run(host="0.0.0.0", port=5000) 讓區域網路上的裝置連線;開發伺服器只用於開發,除錯模式不要對外,控制面板不要直接放上網際網路。
這一課完成了!
Next lesson:MQTT 與物聯網
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。