前面的 Raspberry Pi 實作大多是在 Raspberry Pi 本機執行 Python 程式,例如控制 LED、讀取感測器、操作 LCD1602,或在第 16 章使用 Camera 拍攝照片。
但是實際的 IoT 專案通常不會要求使用者一直坐在 Raspberry Pi 前面操作。
更實用的方式是:
讓 Raspberry Pi 成為一台 Web Server。
如此一來,只要手機、平板或電腦與 Raspberry Pi 位於同一個區域網路,就可以直接開啟瀏覽器:
http://192.168.1.100:5000
然後在網頁上按下:
LED ON
LED OFF
遠端控制 Raspberry Pi GPIO。
本章將使用 Python 非常常見的 Web Framework:
Flask
建立第一個 Raspberry Pi Web Server,並將:
HTML
Flask
Python
GPIO
整合成完整的遠端硬體控制系統。
本章最後將完成:
實作:手機瀏覽器控制 Raspberry Pi LED
一、本章學習目標
完成本章後,你將了解:
- Client 與 Server
- Web Server 基本概念
- HTTP 通訊
- IP Address
- Port
- Flask
- Flask Route
- HTML 基礎
- GET / POST 基本觀念
- Raspberry Pi LAN 網路
- GPIO Zero
- Flask 與 GPIO 整合
- 手機控制 Raspberry Pi GPIO
- Raspberry Pi Web Server 的安全注意事項
並完成:
Raspberry Pi Flask Web GPIO Control System
二、什麼是 Client / Server?
網頁系統最基本的架構就是:
Client
│
│ Request
▼
Server
│
│ Response
▼
Client
其中:
Client
Client 就是發出要求的裝置。
例如:
- 手機
- 平板
- Windows 電腦
- Mac
- 另一台 Raspberry Pi
- Web Browser
本章中的 Client 就是:
手機瀏覽器。
Server
Server 負責接收 Client 的 Request,處理後再回傳 Response。
本章中的 Server 就是:
Raspberry Pi。
架構為:
手機 Browser
│
│ HTTP
▼
Raspberry Pi
Flask Web Server
│
▼
Python
│
▼
GPIO
│
▼
LED
所以手機本身不需要直接連接 LED。
手機只需要把:
開燈
這個要求傳送給 Raspberry Pi。
真正控制 GPIO 的仍然是 Raspberry Pi。
三、什麼是 HTTP?
HTTP 是:
HyperText Transfer Protocol
也就是:
超文字傳輸協定
瀏覽器與 Web Server 之間通常利用 HTTP 或 HTTPS 進行通訊。
例如手機輸入:
http://192.168.1.100:5000/
瀏覽器會向 Raspberry Pi 發出 Request。
Raspberry Pi 的 Flask Server 收到 Request 後,回傳 HTML。
架構:
Browser
│
│ HTTP Request
▼
Flask
│
│ HTML Response
▼
Browser
四、什麼是 IP Address?
網路中的每一台裝置都需要能被識別。
其中最重要的資訊之一就是:
IP Address
例如:
192.168.1.10
192.168.1.20
192.168.1.100
假設:
Raspberry Pi
192.168.1.100
手機:
192.168.1.50
而且都連接同一台 Wi-Fi Router:
Wi-Fi Router
│
┌─────────┴─────────┐
│ │
手機 Raspberry Pi
192.168.1.50 192.168.1.100
手機就可以透過 LAN 存取 Raspberry Pi。
五、如何查 Raspberry Pi IP?
在 Raspberry Pi Terminal 輸入:
hostname -I
可能得到:
192.168.1.100
如果出現多個 IP,例如:
192.168.1.100 172.17.0.1
通常需要找出 Raspberry Pi 實際連接區域網路的 IP。
也可以輸入:
ip addr
查看各 Network Interface。
常見介面:
eth0
wlan0
其中:
eth0
通常代表 Ethernet。
wlan0
通常代表 Wi-Fi。
六、什麼是 Port?
一台 Raspberry Pi 可能同時提供很多網路服務。
例如:
SSH
Web Server
Database
MQTT
所以只有 IP 還不夠。
還需要:
Port Number
概念可以想像成:
IP Address = 大樓地址
Port = 房間號碼
例如:
192.168.1.100:5000
其中:
192.168.1.100
是 Raspberry Pi IP。
而:
5000
是 Port。
七、Flask 預設開發 Port
Flask 開發伺服器常使用:
5000
因此稍後我們的網址會類似:
http://192.168.1.100:5000
Flask 官方 Quickstart 使用 route() 將 URL 與 Python Function 建立對應,這也是本章整個 Web GPIO 控制系統最重要的核心概念。
八、什麼是 Flask?
Flask 是 Python 的 Web Framework。
它可以讓我們使用 Python 建立:
- Web Server
- Web Page
- REST API
- IoT Dashboard
- GPIO 控制頁面
- Sensor Dashboard
- Camera Control
- Database Web Interface
最基本的 Flask 程式甚至只需要幾行 Python。
例如:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello Raspberry Pi"
if __name__ == "__main__":
app.run()
其中:
@app.route("/")
就是告訴 Flask:
當 Browser 存取:
/
時,要執行哪一個 Python Function。
Flask 官方文件也是利用 @app.route() 建立 URL 與 Python Function 的對應。
九、建立 Raspberry Pi Flask 環境
先更新套件資訊:
sudo apt update
在 Raspberry Pi OS 中,可以直接安裝:
sudo apt install -y python3-flask
另外本章 GPIO 控制使用:
GPIO Zero
可以安裝:
sudo apt install -y python3-gpiozero
Raspberry Pi 官方文件將 GPIO Zero 作為 Raspberry Pi Python GPIO 控制方式之一,而且 Raspberry Pi OS 通常已包含 GPIO Zero。
十、為什麼本章使用 GPIO Zero?
很多舊 Raspberry Pi 教學會使用:
import RPi.GPIO as GPIO
但是本系列希望 Raspberry Pi 4 與 Raspberry Pi 5 都能較容易使用,所以本章主要採用:
from gpiozero import LED
GPIO Zero 將 GPIO 裝置封裝成比較容易理解的 Python Object。
例如:
led = LED(17)
開燈:
led.on()
關燈:
led.off()
程式非常直覺。
Raspberry Pi 官方也指出 GPIO Zero 可以簡化利用 Python 控制 GPIO 裝置的工作。
十一、準備材料
本章需要:
| 材料 | 數量 |
|---|---|
| Raspberry Pi | 1 |
| microSD Card | 1 |
| Raspberry Pi OS | 1 |
| LED | 1 |
| 220Ω~330Ω 電阻 | 1 |
| Breadboard | 1 |
| Dupont Jumper Wire | 數條 |
| Wi-Fi / Ethernet 網路 | 1 |
Raspberry Pi 3、4、5 都可以進行本章實驗。
十二、LED 接線
本章使用:
GPIO17
控制 LED。
我們採用 BCM GPIO 編號。
接線:
Raspberry Pi GPIO17
│
│
▼
電阻
220Ω~330Ω
│
▼
LED 長腳 (+)
│
LED
│
LED 短腳 (-)
│
▼
GND
也就是:
| Raspberry Pi | 元件 |
|---|---|
| GPIO17 | 220Ω~330Ω 電阻 |
| 電阻另一端 | LED Anode 長腳 |
| LED Cathode 短腳 | GND |
十三、GPIO17 在哪裡?
GPIO Zero:
LED(17)
這裡的:
17
指的是:
BCM GPIO17
不是實體 Pin 17。
GPIO17 對應 40-pin Header 的:
Physical Pin 11
因此:
GPIO17 = BCM 17 = Physical Pin 11
兩種編號不要混淆。
Raspberry Pi 可以直接在 Terminal 使用:
pinout
查看目前 Raspberry Pi 的 GPIO Pinout;官方文件指出這個工具由 GPIO Zero 提供。
十四、為什麼 LED 一定要串接電阻?
LED 不應直接連接 GPIO。
應使用:
GPIO
│
▼
Resistor
│
▼
LED
│
▼
GND
例如:
220Ω
或:
330Ω
電阻用來限制 LED 電流。
Raspberry Pi 官方文件也明確提醒 LED 應使用限流電阻。
十五、先測試 GPIO LED
在開始 Flask 前,先確認 LED 接線正確。
建立:
nano led_test.py
輸入:
from gpiozero import LED
from time import sleep
led = LED(17)
while True:
led.on()
sleep(1)
led.off()
sleep(1)
執行:
python3 led_test.py
LED 應該:
亮 1 秒
↓
滅 1 秒
↓
亮 1 秒
↓
滅 1 秒
循環執行。
按:
Ctrl + C
停止。
如果這一步成功,表示 GPIO 與 LED 接線正常。
十六、建立第一個 Flask Web Server
建立專案資料夾:
mkdir -p ~/flask_gpio
進入:
cd ~/flask_gpio
建立:
nano app.py
輸入:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return """
<h1>Raspberry Pi Web Server</h1>
<p>Hello Raspberry Pi!</p>
"""
if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=5000,
debug=False
)
十七、啟動 Flask
執行:
python3 app.py
正常情況會看到類似:
Running on http://127.0.0.1:5000
Running on http://192.168.1.100:5000
實際顯示方式會依 Flask 版本與網路環境略有不同。
十八、host=“0.0.0.0” 是什麼?
如果只讓 Web Server 接受 Localhost Request,其他裝置可能無法連入。
因此本章設定:
app.run(
host="0.0.0.0",
port=5000
)
這表示 Flask Development Server 在可用的網路介面上接受連線。
注意:
0.0.0.0
是 Server 的 Bind Address。
手機瀏覽器不要輸入:
http://0.0.0.0:5000
而應輸入 Raspberry Pi 的實際 LAN IP:
http://192.168.1.100:5000
十九、從 Raspberry Pi 本機測試
如果 Raspberry Pi 有 Desktop,可以打開 Browser:
http://127.0.0.1:5000
或:
http://localhost:5000
看到:
Raspberry Pi Web Server
Hello Raspberry Pi!
代表 Flask 已正常運作。
二十、使用手機連線 Raspberry Pi
首先在 Raspberry Pi 查 IP:
hostname -I
假設得到:
192.168.1.100
手機與 Raspberry Pi 必須位於可以互相通訊的 LAN。
然後手機 Browser 輸入:
http://192.168.1.100:5000
如果成功看到:
Raspberry Pi Web Server
就代表:
手機
↓
Wi-Fi
↓
Router
↓
Raspberry Pi
↓
Flask
已經全部連線成功。
二十一、什麼是 Web Route?
現在來理解 Flask 最重要的:
@app.route(...)
例如:
@app.route("/")
def home():
return "HOME"
代表:
http://192.168.1.100:5000/
再增加:
@app.route("/hello")
def hello():
return "Hello"
代表:
http://192.168.1.100:5000/hello
Flask 官方文件稱 Route 是用來指定哪個 URL 應觸發哪個 View Function。
二十二、將 Route 與 GPIO 結合
接下來建立:
/led/on
以及:
/led/off
概念如下:
Browser
│
│ /led/on
▼
Flask
│
▼
led.on()
│
▼
GPIO17 HIGH
│
▼
LED ON
關燈:
Browser
│
│ /led/off
▼
Flask
│
▼
led.off()
│
▼
GPIO17 LOW
│
▼
LED OFF
這就是:
Web Route → Python → GPIO
的核心。
二十三、第一版 Flask GPIO 程式
建立:
nano gpio_web.py
輸入:
from flask import Flask
from gpiozero import LED
app = Flask(__name__)
led = LED(17)
@app.route("/")
def home():
return """
<h1>Raspberry Pi GPIO Control</h1>
<p>
<a href="/led/on">
LED ON
</a>
</p>
<p>
<a href="/led/off">
LED OFF
</a>
</p>
"""
@app.route("/led/on")
def led_on():
led.on()
return """
<h1>LED ON</h1>
<a href="/">Back</a>
"""
@app.route("/led/off")
def led_off():
led.off()
return """
<h1>LED OFF</h1>
<a href="/">Back</a>
"""
if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=5000,
debug=False
)
執行:
python3 gpio_web.py
手機打開:
http://Raspberry-Pi-IP:5000
例如:
http://192.168.1.100:5000
按:
LED ON
LED 就會亮。
按:
LED OFF
LED 就會熄滅。
到這裡,我們已經完成最基本的:
Raspberry Pi 網頁控制 GPIO。
二十四、為什麼還要改良?
剛才的程式可以工作,但還不是很好的 Web 控制設計。
因為我們使用:
GET /led/on
GET /led/off
來改變硬體狀態。
更適合的方式是:
POST
負責執行狀態改變。
所以接下來正式專題版本會使用:
GET /
讀取頁面。
以及:
POST /led/on
POST /led/off
控制 GPIO。
二十五、GET 與 POST 基本觀念
最簡單可以理解成:
GET
通常用來:
取得資料
讀取頁面
查詢狀態
例如:
GET /
取得首頁。
POST
通常用來:
提交資料
改變狀態
執行操作
例如:
POST /led/on
執行 LED ON。
因此:
查看狀態 → GET
控制設備 → POST
是一個更好的設計方式。
二十六、HTML Button
HTML 可以建立按鈕:
<button>LED ON</button>
但是按鈕如果要向 Flask 發送命令,可以使用 Form:
<form action="/led/on" method="post">
<button type="submit">
LED ON
</button>
</form>
代表:
按下按鈕後:
POST /led/on
二十七、實作:手機瀏覽器控制 Raspberry Pi LED
現在開始建立本章正式專題。
系統架構:
Smartphone
│
│ Wi-Fi
▼
Router
│
│ LAN
▼
Raspberry Pi
│
Flask
│
┌─────────┴─────────┐
│ │
Web Page Web Route
│
▼
Python
│
▼
GPIO Zero
│
▼
GPIO17
│
▼
LED
二十八、建立專題目錄
執行:
mkdir -p ~/raspberrypi_web_gpio
進入:
cd ~/raspberrypi_web_gpio
建立:
nano app.py
二十九、完整 Raspberry Pi Flask GPIO 程式
輸入:
from flask import Flask, redirect, url_for
from gpiozero import LED
# -----------------------------
# Flask
# -----------------------------
app = Flask(__name__)
# -----------------------------
# GPIO
# BCM GPIO17
# Physical Pin 11
# -----------------------------
led = LED(17)
# -----------------------------
# 建立 HTML
# -----------------------------
def build_page():
if led.is_lit:
led_status = "ON"
else:
led_status = "OFF"
html = f"""
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
>
<title>
Raspberry Pi GPIO Control
</title>
<style>
body {{
font-family:
Arial,
"Microsoft JhengHei",
sans-serif;
background: #f2f4f7;
text-align: center;
margin: 0;
padding: 30px;
}}
.container {{
max-width: 500px;
margin: auto;
background: white;
padding: 30px;
border-radius: 15px;
box-shadow:
0 4px 15px
rgba(0, 0, 0, 0.15);
}}
h1 {{
color: #333;
}}
.status {{
font-size: 28px;
font-weight: bold;
margin: 30px 0;
}}
button {{
width: 200px;
padding: 18px;
margin: 10px;
border: none;
border-radius: 10px;
font-size: 20px;
cursor: pointer;
}}
.on {{
background: #28a745;
color: white;
}}
.off {{
background: #dc3545;
color: white;
}}
.info {{
margin-top: 30px;
color: #666;
}}
</style>
</head>
<body>
<div class="container">
<h1>
Raspberry Pi
GPIO Control
</h1>
<p>
GPIO17 LED Status
</p>
<div class="status">
{led_status}
</div>
<form
action="/led/on"
method="post"
>
<button
class="on"
type="submit"
>
LED ON
</button>
</form>
<form
action="/led/off"
method="post"
>
<button
class="off"
type="submit"
>
LED OFF
</button>
</form>
<div class="info">
Raspberry Pi Flask
Web GPIO Controller
</div>
</div>
</body>
</html>
"""
return html
# -----------------------------
# Home
# -----------------------------
@app.route("/")
def home():
return build_page()
# -----------------------------
# LED ON
# -----------------------------
@app.route(
"/led/on",
methods=["POST"]
)
def led_on():
led.on()
return redirect(
url_for("home")
)
# -----------------------------
# LED OFF
# -----------------------------
@app.route(
"/led/off",
methods=["POST"]
)
def led_off():
led.off()
return redirect(
url_for("home")
)
# -----------------------------
# Main
# -----------------------------
if __name__ == "__main__":
print(
"Raspberry Pi Flask GPIO Server"
)
print(
"Port: 5000"
)
app.run(
host="0.0.0.0",
port=5000,
debug=False
)
三十、執行專題程式
執行:
cd ~/raspberrypi_web_gpio
然後:
python3 app.py
Server 開始執行。
三十一、查 Raspberry Pi IP
另外開啟 Terminal:
hostname -I
假設為:
192.168.1.100
三十二、手機操作
手機必須連接與 Raspberry Pi 可以互通的網路。
在手機 Chrome、Safari 或其他 Browser 輸入:
http://192.168.1.100:5000
就會看到控制頁面:
Raspberry Pi GPIO Control
GPIO17 LED Status
OFF
[ LED ON ]
[ LED OFF ]
按:
LED ON
傳送:
POST /led/on
Flask 執行:
led.on()
GPIO17 輸出 High。
LED:
ON
按:
LED OFF
則:
POST /led/off
執行:
led.off()
LED:
OFF
三十三、完整控制流程
現在可以把整個系統完整畫出來。
當使用者按:
LED ON
執行流程為:
手機
│
│ HTTP POST
│
│ /led/on
▼
Wi-Fi Router
│
▼
Raspberry Pi
│
▼
Flask
│
▼
@app.route("/led/on")
│
▼
led_on()
│
▼
led.on()
│
▼
GPIO Zero
│
▼
GPIO17 HIGH
│
▼
LED ON
這就是完整的:
Raspberry Pi Web GPIO Control
三十四、LED Status 如何取得?
程式使用:
led.is_lit
例如:
if led.is_lit:
led_status = "ON"
else:
led_status = "OFF"
因此網頁可以知道目前 GPIO 裝置狀態。
架構變成:
GPIO
↓
GPIO Zero
↓
Python
↓
Flask
↓
HTML
↓
Browser
不只是 Browser 控制 Raspberry Pi。
Raspberry Pi 也可以:
把硬體狀態顯示回 Browser。
三十五、Flask 與 HTML 的關係
目前我們直接:
return """
<html>
...
</html>
"""
把 HTML 放在 Python 裡。
這種方式很適合教學。
但是大型專案通常會拆成:
raspberrypi_web_gpio/
│
├── app.py
│
├── templates/
│ └── index.html
│
└── static/
├── css/
├── js/
└── images/
Flask 本身支援 Template 架構,而且 Flask 使用 Jinja Template Engine 來產生動態 HTML。
例如:
from flask import render_template
然後:
return render_template(
"index.html"
)
第 20 章完整智慧環境監控中心就很適合採用這種方式。
三十六、如果手機無法連線
如果 Raspberry Pi 本機正常:
http://127.0.0.1:5000
但是手機無法:
http://192.168.1.100:5000
可以依序檢查。
1. Flask 是否仍在執行?
Terminal 必須仍然執行:
python3 app.py
如果已按:
Ctrl + C
Server 就停止了。
2. IP 是否正確?
重新執行:
hostname -I
確認目前 Raspberry Pi IP。
DHCP 環境下,IP 可能在重新連線或重新開機後發生變化。
3. 手機與 Raspberry Pi 網路是否互通?
確認兩者是否連接可彼此通訊的 LAN。
有些:
Guest Wi-Fi
會開啟 Client Isolation。
即使手機與 Raspberry Pi 看起來連接同一個基地台,也可能禁止裝置彼此存取。
4. Flask 是否使用 0.0.0.0?
確認:
app.run(
host="0.0.0.0",
port=5000
)
而不是只綁定:
127.0.0.1
5. Port 是否正確?
如果 Server 使用:
5000
網址就必須有:
:5000
完整:
http://192.168.1.100:5000
三十七、查看 Flask Request
執行 Flask 時,每次 Browser 發出 Request,Terminal 通常都會顯示存取資訊。
例如:
GET / HTTP/1.1
按 LED ON:
POST /led/on HTTP/1.1
接著 Browser 回首頁:
GET / HTTP/1.1
因此 Flask Console 本身就可以協助 Debug Web Control。
三十八、為什麼按下按鈕後要 Redirect?
我們使用:
return redirect(
url_for("home")
)
意思是:
POST /led/on
↓
LED ON
↓
Redirect
↓
GET /
↓
重新顯示首頁
因此使用者按完按鈕後會回到:
/
並看到最新:
LED Status = ON
三十九、不要直接把 Flask Development Server 開放到 Internet
本章建立的是:
LAN 教學用 Flask Server。
Flask 官方文件明確表示內建 Development Server 主要用於開發,不應直接作為正式 Production Server。正式部署應使用適合 Production 的 WSGI Server,並視架構搭配 nginx 等 Web Server / Reverse Proxy。
因此本章架構建議限定在:
家中 LAN
實驗室 LAN
公司測試 LAN
不要直接在 Router 設定:
Port Forward 5000
然後毫無身份驗證地暴露到 Internet。
因為目前:
/led/on
/led/off
沒有登入驗證。
只要能連到 Server 的人,就可能控制設備。
四十、正式 IoT Web Control 需要什麼?
真正對 Internet 開放時,應進一步考慮:
HTTPS
Authentication
Authorization
Firewall
Reverse Proxy
Session Security
CSRF Protection
Logging
Rate Limiting
架構可能變成:
Internet
│
▼
HTTPS
│
▼
Reverse Proxy
│
▼
Production WSGI Server
│
▼
Flask
│
▼
Authentication
│
▼
GPIO Control
但這已經屬於更進階的 Web / IoT Security 主題。
本章先以:
LAN 遠端控制
為主要目標。
四十一、延伸成繼電器控制
我們目前使用:
from gpiozero import LED
實際上同樣概念也可以延伸到繼電器。
例如:
Browser
↓
Flask
↓
GPIO
↓
Relay Module
↓
Fan
未來就可以設計:
[ FAN ON ]
[ FAN OFF ]
所以本章表面上是在控制 LED,真正學的是:
Web 遠端 GPIO 控制架構
四十二、延伸成多組 GPIO
例如:
GPIO17 → LED
GPIO18 → Relay
GPIO22 → Buzzer
Web Page 可以改成:
Raspberry Pi Control Center
LED
[ ON ] [ OFF ]
FAN
[ ON ] [ OFF ]
BUZZER
[ ON ] [ OFF ]
架構:
Flask
│
┌───────────┼───────────┐
│ │ │
GPIO17 GPIO18 GPIO22
│ │ │
LED Relay Buzzer
│
Fan
這就是第 20 章智慧監控中心的基礎。
四十三、Flask + Sensor
Flask 不只是控制 GPIO Output。
同樣可以讀取 Sensor。
例如:
DHT22
│
▼
Python
│
▼
Flask
│
▼
HTML
│
▼
手機
Web Page 可以顯示:
智慧環境監控
Temperature
28.5 °C
Humidity
68 %
Fan
ON
LED Warning
OFF
因此 Browser 會變成 Raspberry Pi 的:
HMI 人機介面。
四十四、Flask + Raspberry Pi Camera
上一章學過:
Picamera2
所以之後也可以加入:
[ CAMERA PHOTO ]
架構:
手機
│
│ POST /camera/photo
▼
Flask
│
▼
Picamera2
│
▼
Camera Module
│
▼
photo.jpg
第 16 章:
Camera
加上第 17 章:
Flask
就已經可以開始設計:
Raspberry Pi Web Camera。
四十五、Flask + SQLite
第 19 章還會加入:
SQLite
架構將變成:
Sensor
│
▼
Python
│
├──────────────► SQLite
│ │
│ ▼
│ History Data
│
▼
Flask
│
▼
Web Browser
使用者就可以在手機查看:
目前溫度
目前濕度
設備狀態
歷史資料
四十六、Flask + MQTT
下一章會介紹:
MQTT
到時架構會變成:
Raspberry Pi
│
┌───────────┼───────────┐
│ │ │
Flask MQTT GPIO
│ │ │
HTTP Broker LED
│
Browser
Flask 適合:
Web 操作
Dashboard
Browser Control
MQTT 適合:
IoT Message
Sensor Publish
Device Subscribe
Machine-to-Machine
兩者可以同時存在。
四十七、HTTP 與 MQTT 有什麼不同?
簡單比較:
| 項目 | HTTP / Flask | MQTT |
|---|---|---|
| 架構 | Client / Server | Publisher / Broker / Subscriber |
| Web Browser | 非常適合 | 通常需要額外 Client |
| Dashboard | 適合 | 可配合其他系統 |
| IoT Sensor | 可以 | 非常適合 |
| 即時裝置訊息 | 可以 | 很適合 |
| Topic | 無 | 有 |
| Broker | 不需要 | 需要 |
| 本章 | Flask | 下一章 |
因此:
手機操作介面
Flask 很方便。
而:
大量 IoT 裝置交換 Sensor Data
MQTT 通常更適合。
四十八、本章系統與前面章節整合
到目前為止,我們已經逐步建立:
Raspberry Pi OS
│
▼
Linux
│
▼
Python
│
├──────── GPIO
│ │
│ ├── LED
│ ├── Buzzer
│ └── Relay
│
├──────── Sensor
│
├──────── I²C LCD
│
├──────── Camera
│
└──────── Flask
│
▼
Web Browser
Raspberry Pi 已經開始從:
單機嵌入式控制器
進化成:
網路化控制平台。
四十九、本章完整系統資料流
顯示網頁
手機 Browser
│
│ GET /
▼
Flask
│
▼
build_page()
│
▼
讀取 led.is_lit
│
▼
產生 HTML
│
▼
手機 Browser
開啟 LED
手機
│
│ POST /led/on
▼
Flask
│
▼
led_on()
│
▼
led.on()
│
▼
GPIO17
│
▼
LED ON
關閉 LED
手機
│
│ POST /led/off
▼
Flask
│
▼
led_off()
│
▼
led.off()
│
▼
GPIO17
│
▼
LED OFF
這三個流程就是本章最重要的觀念。
五十、本章常用指令整理
更新套件:
sudo apt update
安裝 Flask:
sudo apt install -y python3-flask
安裝 GPIO Zero:
sudo apt install -y python3-gpiozero
查看 GPIO Pin:
pinout
查看 IP:
hostname -I
建立專案:
mkdir -p ~/raspberrypi_web_gpio
進入:
cd ~/raspberrypi_web_gpio
編輯:
nano app.py
執行:
python3 app.py
瀏覽器:
http://Raspberry-Pi-IP:5000
例如:
http://192.168.1.100:5000
停止 Flask:
Ctrl + C
五十一、本章常見錯誤
問題 1:ModuleNotFoundError: No module named ‘flask’
安裝:
sudo apt update
sudo apt install -y python3-flask
問題 2:No module named gpiozero
安裝:
sudo apt install -y python3-gpiozero
問題 3:網頁正常但 LED 不亮
先不要檢查 Flask。
先執行:
python3 led_test.py
確認:
GPIO
電阻
LED 極性
GND
正確。
如果單純 GPIO 測試都無法控制 LED,問題通常不在 Flask。
問題 4:LED 一直亮
檢查:
LED 接線
GPIO 編號
程式是否還在執行
並確認使用:
LED(17)
代表:
BCM GPIO17
問題 5:手機顯示無法連線
確認:
Raspberry Pi IP
手機與 Pi 網路互通
Flask 是否正在執行
Port 5000
host="0.0.0.0"
五十二、Raspberry Pi 重新開機後 IP 改變怎麼辦?
因為一般家用 Router 通常透過 DHCP 配發 IP。
例如原本:
192.168.1.100
重新開機後可能變:
192.168.1.105
因此實際 IoT 專案可以進一步考慮:
- DHCP Reservation
- 固定 LAN IP
- mDNS Hostname
- DNS
例如某些網路環境可使用:
http://raspberrypi.local:5000
不過 .local 是否可以正常解析取決於 Client、網路及 mDNS 環境,因此實驗初期建議直接使用:
Raspberry Pi LAN IP
最容易 Debug。
五十三、為什麼 Raspberry Pi 非常適合當 Web GPIO Server?
Arduino UNO 很適合:
GPIO
Sensor
Motor
Real-time Control
但是 Raspberry Pi 同時具有:
Linux
Python
Wi-Fi
Ethernet
TCP/IP
HTTP
Web Server
Database
Camera
MQTT
SSH
所以 Raspberry Pi 很適合建立:
Web + Hardware
系統。
例如:
Web Smart Home
Web Environment Monitor
Web Camera
Web Relay Controller
Web Robot Controller
IoT Gateway
這也是 Raspberry Pi 與一般微控制器最大的應用差異之一。
五十四、本章完成成果
完成本章後,我們已經建立:
Raspberry Pi 手機 Web GPIO 控制器
硬體:
Raspberry Pi
│
GPIO17
│
220Ω~330Ω
│
LED
│
GND
軟體:
Raspberry Pi OS
│
Python
│
Flask
│
GPIO Zero
網路:
Smartphone
│
Wi-Fi
│
Router
│
Raspberry Pi
控制:
Browser
│
├── LED ON
│
└── LED OFF
這已經是一套完整的小型:
Raspberry Pi IoT Web Control System
五十五、本章重點整理
本章最重要的不是只學會「用手機開 LED」。
真正需要理解的是以下架構:
Client
│
│ HTTP
▼
Server
│
▼
Flask
│
▼
Route
│
▼
Python Function
│
▼
GPIO Zero
│
▼
GPIO
│
▼
Hardware
其中:
Client = 手機 Browser
Server = Raspberry Pi
HTTP = 網路通訊
Flask = Python Web Framework
Route = URL 與程式功能對應
GPIO Zero = GPIO 控制 Library
GPIO17 = 硬體輸出
LED = 最終受控設備
只要理解這個架構,把 LED 換成:
Relay
Fan
Motor
Buzzer
Light
Pump
Camera
控制原理基本上完全相同。
五十六、下一章預告
下一章將正式進入:
第 18 章 Raspberry Pi IoT 入門:MQTT 遠端感測與裝置控制
我們會學習:
- IoT
- MQTT
- Broker
- Publisher
- Subscriber
- Topic
- Mosquitto
- Python MQTT
- Sensor Data
- 遠端控制
- IoT Architecture
並完成:
Raspberry Pi MQTT 溫度監控與 LED 控制
系統會從本章:
手機
↓
HTTP
↓
Flask
↓
Raspberry Pi
↓
LED
進一步發展為:
Raspberry Pi
│
│ MQTT Publish
▼
Mosquitto
Broker
▲ │
│ ▼
Subscriber Publisher
│ │
▼ ▼
Sensor LED Control
Monitor
這將正式進入真正的:
Raspberry Pi IoT 架構。