本篇繼續 MicroPython 網路存取之網頁伺服器測試, 我五年前直接使用 socket 模組測試過網頁伺服器, 這回則改用陳會安老師大作 "超簡單Python/MicroPython物聯網應用" 這本書中提供的 xtools.py 與 ESP8266WebServer.py 等函式庫重測, 程式碼會更精簡, 我把這當作是睽違五年後的 MicroPython 複習, 看看能否順便將之前想做的物聯網專案一併做完.
本系列之前的文章參考 :
5. 用 ESP8266WebServer 模組建立網頁伺服器 :
ESP8266WebServer.py 是一個極輕量的網頁伺服器模組, 可用來在 ESP8266/ESP32 開發板上建立網頁伺服器, 這比直接用 socket 實作簡單方便得多, 且支援網頁模板用法, 但目前僅支援客戶端用用 GET 方法提出請求. 此模組最新版本可在 GitHub 下載 (8 KB) :
但是我使用最新版去測試時會出現如下的 TypeError :
Traceback (most recent call last):
File "<stdin>", line 24, in <module>
File "ESP8266WebServer.py", line 60, in handleClient
File "ESP8266WebServer.py", line 215, in handle
TypeError: function takes 2 positional arguments but 5 were given
應該是新版的 handlers 函式介面的參數增加所致, 故以下測試使用 "超簡單Python/MicroPython物聯網應用" 這本書範例程式所附的舊版模組, 我將其放在 GitHub (7 KB) :
# https://github.com/tony1966/tony1966.github.io/blob/master/test/MicroPython/lib/ESP8266WebServer.py
直接用 Socket 建立網頁伺服器的原始做法參考以前的文章 :
下面先來測試可回應 'Hello World!' 的網頁伺服器.
首先來檢視 ESP8266WebServer 模組的內容 :
MicroPython v1.19.1 on 2022-06-18; ESP module with ESP8266
Type "help()" for more information.
>>> import ESP8266WebServer
>>> dir(ESP8266WebServer)
['__class__', '__name__', 'close', 'machine', 'network', 'socket', 'uselect', 'os', 'poller', 'server', 'handlers', 'notFoundHandler', 'docPath', 'tplData', 'mimeTypes', 'begin', 'handleClient', 'handle', '__sendPage', 'err', 'ok', '__fileExist', 'onPath', 'onNotFound', 'setDocPath', 'setTplData']
>>> help(ESP8266WebServer)
object <module 'ESP8266WebServer'> is of type module
handle -- <function handle at 0x3ffeff30>
mimeTypes -- {'.png': 'image/png', '.jpg': 'image/jpg', '.css': 'text/css'}
close -- <function close at 0x3ffefdf0>
os -- <module 'uos'>
__name__ -- ESP8266WebServer
socket -- <module 'lwip'>
ok -- <function ok at 0x3ffeff10>
network -- <module 'network'>
onPath -- <function onPath at 0x3ffeff40>
onNotFound -- <function onNotFound at 0x3ffeff50>
__fileExist -- <function __fileExist at 0x3ffeff20>
err -- <function err at 0x3ffeff00>
notFoundHandler -- None
__sendPage -- <function __sendPage at 0x3ffefef0>
docPath -- /
begin -- <function begin at 0x3ffefec0>
uselect -- <module 'uselect'>
handlers -- {}
tplData -- {}
setDocPath -- <function setDocPath at 0x3ffeff60>
setTplData -- <function setTplData at 0x3fff00b0>
handleClient -- <function handleClient at 0x3ffefee0>
server -- <socket state=0 timeout=-1 incoming=0 off=0>
machine -- <module 'umachine'>
poller -- <poll>
常用函式如下表 :
ESP8266WebServer 函式 | 說明 |
begin(port) | 指定 port=80 啟動網頁伺服器 |
ok(socket, code, mime, html) | 以 code='200', mime='text/html' 回應 html 字串 |
onPath(path, handler) | 指定請求路徑 path 時之處理函式 handler |
setDocPath(path) | 指定存放 HTML 文件之路徑 path |
setTplData(data) | 指定要傳給模板檔案 index.p.html 的字典變數 data |
handleClient() | 在無限迴圈中呼叫此函式以監聽是否有客戶端請求出現 |
使用 ESP8266WebServer 建立網頁伺服器首先要匯入 xtools, config, 以及 ESP8266WebServer, 然後呼叫 xtools.connect_wifi_led() 連線 WiFi 基地台 :
>>> import xtools
>>> import config
>>> ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
>>> print("ip : ", ip)
network config: ('192.168.43.54', '255.255.255.0', '192.168.43.1', '192.168.43.1')
ip : 192.168.43.54
這個 ip 就是伺服器的網址. 接著用長字串定義要回應的網頁內容變數 html :
>>> html="""
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>"""
接著定義一個伺服器根目錄請求處理函式 handleRoot() :
>>> def handleRoot(socket, args):
global html
ESP8266WebServer.ok(socket, "200", "text/html", html)
此函式要傳入兩個參數 socket 與 args, 其中 socket 為模組內建立的 Socket 物件, 而 args 則是 GET 請求所傳遞的參數字典, 例如若請求網址為 /?para1=a¶2=b 則傳入之 args 為 {'para1': 'a', 'para2': 'b'}, 此例因為是請求根目錄沒有傳遞參數所以用不到, 而是直接用 global 宣告取用外部全域變數 html (即要回應之網頁內容) 後呼叫 ESP8266WebServer.ok() 函式將 html 網頁內容回應給客戶端.
然後呼叫 ESP8266WebServer.begin() 啟動網頁伺服器, 傳入參數是埠號, 一般是 80 埠 :
>>> ESP8266WebServer.begin(80)
接下來呼叫 ESP8266WebServer.onPath() 定義路由 (routing), 其第一參數為資源路徑, 此處為網站根目錄 '/'; 第二參數為對應此資源請求之路由處理函式, 也就是上面所定義的回應函式 handleRoot :
>>> ESP8266WebServer.onPath("/", handleRoot)
最後在無限迴圈中呼叫 ESP8266WebServer.handleClient() 函式監視是否有客戶端請求即可 :
>>> while True:
ESP8266WebServer.handleClient()
這時在瀏覽器網址列輸入上面的伺服器連線網址即可看到 'Hello World!' 頁面了 :
連線時會出現找不到 favicon.ico, 這是正常的, 因為網站上並未提供此圖示檔 :
/favicon.ico
Not Found.
以上測試完整程式碼如下 :
測試 5-1 : 回應 Hello World! 的簡單網頁伺服器 [看原始碼]
import ESP8266WebServer
import xtools
import config
ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
html="""
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>"""
def handleRoot(socket, args): # 目錄請求之處理函式
global html
ESP8266WebServer.ok(socket, "200", "text/html", html) # 回應網頁
ESP8266WebServer.begin(80)
ESP8266WebServer.onPath("/", handleRoot) # 定義根目錄請求之處理函式
while True:
ESP8266WebServer.handleClient() # 監聽 80 埠是否有客戶端請求
ESP8266WebServer 模組支援網頁文件路徑功能, 這樣就可以把網頁檔案單獨存成 .htm 或 .html 檔放在開發板的特定檔案路徑下, 然後呼叫 ESP8266WebServer.setDocPath() 函式指定網頁檔路徑即可, 不需要像上面範例那樣在 MicroPython 程式中定義 html 變數來存放回應網頁.
首先在本機工作目錄下建立一個 www 資料夾, 將上面範例的 html 變數內容存成 www 底下的 index.htm 檔 :
<!-- index.htm -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
然後將 www 資料夾上傳到板子的根目錄下 :
這是因為 Thonny 的上傳功能只能傳到根目錄下的關係. 最後用下列指令指定網頁文件檔案在 www 下, 替換上面範例的 ESP8266WebServer.onPath() 而且也不需要定義 handlerRoot() 函式 :
ESP8266WebServer.setDocPath("/www")
完整程式碼如下 :
測試 5-2 : 使用 setDocPath() 設定網頁文件路徑 [看原始碼]
import ESP8266WebServer
import xtools
import config
ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
ESP8266WebServer.begin(80)
ESP8266WebServer.setDocPath("/www")
while True:
ESP8266WebServer.handleClient()
注意, 這時在瀏覽器網址列輸入網址時必須輸入完整的網頁路徑 (例如 192.168.43.54/www/index.htm) 才會顯示與上面範例 1 之網頁結果 :
如果只輸入到資料夾 192.168.43.54/www 則顯示 "Not found" :
這是測試時必須注意的, 否則會誤以為程式有問題. 不過這與我的期待不符, 我以為呼叫 setDocPath() 後輸入網址 192.168.43.54 就應該要自動到 www 底下找預設的首頁檔 index.htm 或 index.html 才對, 但實測結果卻不是這樣. 其實不呼叫 setDocPath() 還是可以運作, 所以覺得此版的 setDocPath() 功能也許尚不完整.
參考 :
另外 ESP8266WebServer 模組也提供網頁模板 (Template) 功能, 可透過呼叫 setTplData() 函式將字典型態的變數傳遞給模板網頁, 用法如下 :
- 模板網頁檔名必須以 .p.htm 或 .p.html 結尾
- 所傳遞之變數 var (即字典的 key) 以中括號 {var} 嵌入模板網頁中
首先將上面 /www 底下的 index.htm 改名為 index.p.html, 注意, 與上面兩個範例用 .htm 或 .html 都可以的情況不同, 此處一定要用 .p.html, 如果用 .p.htm 變數將無法傳遞, 而是直接顯示變數名稱. 其次, 編輯 index.p.html 網頁內容, 在 Hello 後面嵌入一個變數 name 為 Hello {name} :
<!-- index.p.html -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>Hello {name}</h1>
</body>
</html>
然後將 /www 資料夾上傳到板子 :
接下來就可以呼叫 xtools.connect_wifi_led() 將板子連上 WiFi, 呼叫 ESP8266WebServer.begin() 啟動網頁伺服器, 呼叫 ESP8266WebServer.setDocPath() 設定 HTML 文件資料夾 (雖然這指令如上例所述似乎可有可無) :
ESP8266WebServer.begin(80)
ESP8266WebServer.setDocPath("/www")
然後定義要傳給模板網頁 index.p.html 的變數 name, 將其放入 data 字典中傳給 ESP8266WebServer.setTplData() :
data={"name": "Tony"}
ESP8266WebServer.setTplData(data)
最後在無限迴圈中呼叫 ESP8266WebServer.handleClient() 函式監視是否有客戶端請求 :
while True:
ESP8266WebServer.handleClient()
完整程式碼如下 :
測試 5-3 : 呼叫 setTplData() 函式傳遞變數給 .p.html 網頁模板 [看原始碼]
import ESP8266WebServer
import xtools
import config
ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
ESP8266WebServer.begin(80)
ESP8266WebServer.setDocPath("/www")
data={"name": "Tony"}
ESP8266WebServer.setTplData(data)
while True:
ESP8266WebServer.handleClient()
與上面範例 2 一樣, 瀏覽器網址列必須輸入完整的網頁路徑才會顯示正確的結果 (例如此處為 192.168.43.54/www/index.p.html), 否則會出現 Bad request 或 Not found.
結果如下 :
可見字典 data 中的變數 name 已經傳遞到模版網頁 index.p.html 並內嵌到 {name} 裡面了.
如果有多個頁面可以用超連結或按鈕來切換, 下面範例使用兩個網頁 page1.htm 與 page2.htm 利用超連結來切換, 先在本機建立 www2 資料夾, 裡面放兩個網頁檔 :
第一頁網頁內容如下 :
<!-- page1.html -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>這是第 1 頁</h1>
<h1><a href="/www2/page2.html">前往第 2 頁</a></h1>
</body>
</html>
第二頁網頁內容如下 :
<!-- page2.html -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>這是第 2 頁</h1>
<h1><a href="/www2/page1.html">返回第 1 頁</a></h1>
</body>
</html>
將此 www2 資料夾上傳板子, 然後如上面範例 2 啟動伺服器, 完整程式碼如下 :
測試 5-4 : 用超連結切換多頁面 [看原始碼]
import ESP8266WebServer
import xtools
import config
ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
ESP8266WebServer.begin(80)
ESP8266WebServer.setDocPath("/www2")
while True:
ESP8266WebServer.handleClient()
瀏覽 page1.htm 完整網址 (例如 192.168.43.54/www2/page1.html), 結果如下 :
按 "前往第 2 頁" 超連結會切換到 page2.htm 網頁 :
按 "返回第 1 頁" 又回到 page1.html 了.
前面的測試顯示, 我使用的這版 ESP8266WebServer.setDocPath() 並不會自動去指定資料夾下找尋首頁檔, 而是必須用完整的網頁路徑. 解決辦法就是以 RESTful 方式使用多個請求處理函式.
下面範例改編自前一個測試, 網站總共有三個網頁 : index.html, page1.html, 以及 page2.html, 透過超連結以 RESTful 網址 /, /page1, 以及 /page2 切換, 首先在本機鍵一個 www3 資料夾, 編輯如下三個網頁檔後以 utf-8 編碼存檔 (因為網頁內容有中文) :
下面是首頁檔案 :
<!-- index.html -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>這是首頁</h1>
<h1><a href="/page1">前往第 1 頁</a></h1>
</body>
</html>
下面是第一頁檔案 :
<!-- page1.html -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>這是第 1 頁</h1>
<h1><a href="/page2">前往第 2 頁</a></h1>
<h1><a href="/">返回首頁</a></h1>
</body>
</html>
下面是第二頁檔案 :
<!-- page2.html -->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>這是第 2 頁</h1>
<h1><a href="page1">返回第 1 頁</a></h1>
<h1><a href="/">返回首頁</a></h1>
</body>
</html>
將 www3 資料夾上傳到板子 :
接下來修改 MicroPython 程式, 為 /, /page1, 與 /page2 這三個網址建立請求處理函式 :
def handleRoot(socket, args):
with open('./www3/index.html', 'r', encoding='utf-8') as f:
html=f.read()
print(html)
ESP8266WebServer.ok(socket, "200", "text/html", html)
def handlePage1(socket, args):
with open('./www3/page1.html', 'r', encoding='utf-8') as f:
html=f.read()
print(html)
ESP8266WebServer.ok(socket, "200", "text/html", html)
def handlePage2(socket, args):
with open('./www3/page2.html', 'r', encoding='utf-8') as f:
html=f.read()
print(html)
ESP8266WebServer.ok(socket, "200", "text/html", html)
這三個函式都使用 open() 開啟位於 www3 資料夾下的網頁檔 (須指定 utf-8 編碼), 讀取後傳給 ESP8266WebServer.ok() 回應給客戶端.
然後呼叫 onPath() 將網址對應到請求處理函式 :
ESP8266WebServer.onPath("/", handleRoot)
ESP8266WebServer.onPath("/page1", handlePage1)
ESP8266WebServer.onPath("/page2", handlePage2)
完整程式碼如下 :
測試 5-5 : 用多個 onPath() 切換多個 RESTful 網址 [看原始碼]
import ESP8266WebServer
import xtools
import config
ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
ESP8266WebServer.begin(80)
def handleRoot(socket, args):
with open('./www3/index.html', 'r', encoding='utf-8') as f:
html=f.read()
print(html)
ESP8266WebServer.ok(socket, "200", "text/html", html)
def handlePage1(socket, args):
with open('./www3/page1.html', 'r', encoding='utf-8') as f:
html=f.read()
print(html)
ESP8266WebServer.ok(socket, "200", "text/html", html)
def handlePage2(socket, args):
with open('./www3/page2.html', 'r', encoding='utf-8') as f:
html=f.read()
print(html)
ESP8266WebServer.ok(socket, "200", "text/html", html)
ESP8266WebServer.onPath("/", handleRoot) # / 處理函式
ESP8266WebServer.onPath("/page1", handlePage1) # /page1 處理函式
ESP8266WebServer.onPath("/page2", handlePage2) # /page2 處理函式
while True:
ESP8266WebServer.handleClient()
瀏覽器網址列只要輸入 ip 即顯示首頁 index.html :
按 "前往第 1 頁" 會切換到 page1.html :
按 "前往第 2 頁" 會切換到 page2.html :
按 "返回首頁" 切換至 index.html, 按 "返回第 1 頁" 切換至 page1.html; 按 "返回第 2 頁" 切換至 page2.html, 這樣就完全不用去管網址列的網頁檔路徑了.
下面範例使用如下超連結按鈕傳遞參數 led 來控制板載 LED (GPIO2) 的明滅 :
/?led=on : 開啟 LED
/?led=off : 關閉 LED
傳入 URL 請求處理函式的第二個參數 args 將是如下的字典 :
{'led': 'on'}
{'led': 'off'}
這樣就可以透過判斷 led 參數之值 args['led'] 是 'on' 還是 'off' 來設定 GPIO2 的值以控制板載 LED 的明滅了.
首先在本機建立一個 www4 資料夾, 建立一個模板網頁 index.p.html :
<!-- index.p.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>LED 狀態 : {0}</h1>
<a href="/?led=on"><button style="font-size:40px;">點亮</button></a>
<a href="/?led=off"><button style="font-size:40px;">熄滅</button></a>
</body>
</html>
此模板網頁中有兩個超連結按鈕, 透過 href 屬性設定 GET 方法的請求網址 /?led=on 與 /?led=off 分別用來控制板載 LED (GPIO2) 的明滅. 其次, LED 狀態後面的 {0} 用在程式中以字串的 format() 方法將 LED 狀態字串 ('點亮' 或 '熄滅') 嵌入此位置.
將此 www4 資料夾用 Thonny 上傳到開發板根目錄下 :
然後從 machine 模組匯入 Pin 類別, 先將板載 LED 設為關閉 (滅) :
from machine import Pin
led=Pin(2, Pin.OUT)
led.value(0)
接著撰寫根目錄請求處理函式 :
def handleRoot(socket, args):
print(args)
with open('./www4/index.p.html', 'r', encoding='utf-8') as f:
html=f.read()
state='熄滅'
if 'led' in args:
if args['led']=='on':
state='點亮'
led.value(1)
elif args['led']=='off':
state='熄滅'
led.value(0)
response=html.format(state)
ESP8266WebServer.ok(socket, "200", "text/html", response)
此函式從 /www4 底下讀取模板網頁 index.p.html 為 html 字串, 然後判斷傳入參數字典 args 是否有 led 參數, 有的話就依據其值為 'on' 或 'off' 來控制 LED 的明滅, 並將狀態字串利用 format() 方法嵌入 html 字串的 {0} 位置, 完整原始碼如下 :
測試 5-6 : 用超連結按鈕點亮與熄滅板載 LED [看原始碼]
import ESP8266WebServer
import xtools
import config
from machine import Pin
ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
led=Pin(2, Pin.OUT)
led.value(1) # 預設狀態: 熄滅
ESP8266WebServer.begin(80)
ESP8266WebServer.setDocPath("/www4")
def handleRoot(socket, args):
print(args)
with open('./www4/index.p.html', 'r', encoding='utf-8') as f:
html=f.read()
state='熄滅'
if 'led' in args:
if args['led']=='on':
state='點亮'
led.value(0) # GPIO2 板載 LED 輸出 low 為亮
elif args['led']=='off':
state='熄滅'
led.value(1) # GPIO2 板載 LED 輸出 high 為滅
response=html.format(state)
ESP8266WebServer.ok(socket, "200", "text/html", response)
ESP8266WebServer.onPath("/", handleRoot)
data={"state": "熄滅"}
ESP8266WebServer.setTplData(data)
while True:
ESP8266WebServer.handleClient()
注意, 由於板載 LED 使用 sink current 接法, 亦即 LED 是陽極經限流電阻接 GPIO2, 陰極則接至 VCC, 故輸出 0 為點亮 LED, 輸出 1 熄滅 LED (負邏輯), 這在 NodeMCU, D1 mini, 或 Witty Cloud 開發板皆是如此 (但 Witty Cloud 上的全彩 LED 則使用 source current, 即正邏輯).
執行後在瀏覽器輸入網址, 例如 192.168.2.141 會顯示 index.p.html 網頁, 預設狀態是熄滅 :
按 "點亮" 鈕板載 LED 亮, 且網頁中 LED 狀態也顯示 "點亮" :
按 "熄滅" 鈕板載 LED 會暗掉, LED 狀態恢復為 "熄滅".
上面的範例每次按 "點亮" 或 "熄滅" 按鈕都會重新載入 index.p.html 網頁, 下面改用 jQuery 函式庫所提供的 Ajax 非同步功能向伺服器提出請求, 利用伺服器回傳的資料更新網頁中特定元素的內容, 不需要重新載入網頁即可改變網頁內容.
首先在本機建立一個 www5 資料夾, 並在底下建立一個 index.html 網頁 :
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
</head>
<body>
<h1>LED 狀態 : <span id='status'>熄滅</span></h1>
<button id="btn_on" style="font-size:40px;">點亮</button>
<button id="btn_off" style="font-size:40px;">熄滅</button>
<script>
$(function(){
$("#btn_on").click(function() {
$.get({
url: "/on",
dataType: "html",
success: function(data) {
$("#status").html(data);
}
});
});
$("#btn_off").click(function() {
$.get({
url: "/off",
dataType: "html",
success: function(data) {
$("#status").html(data);
}
});
});
});
</script>
</body>
</html>
此網頁在 head 標籤內從 jQuery 官網 CDN 匯入 jQuery 函式庫 (目前最新為 3.6.1 版), 雖然也可以下載後上傳到 ESP8266/ESP32 開發板, 但這會佔 Flash 空間語頻寬, 不建議這麼做. 其次, 網頁中的 LED 狀態顯示改用一個具有 id=status 屬性的 span 元素取代, 預設狀態為 "熄滅". 按鈕也直接使用具有 id 屬性 btn_on 與 btn_off 之 button 元素, 去除超連結. 在按下 "點亮" 與 "熄滅" 按鈕時呼叫 jQuery 的捷徑函式 $.get() 對 /on 與 /off 這兩個網址提出 Ajax 請求, 利用傳回來 data 更新 span 元素的內容.
關於 jQuery 的 Ajax 函式參考 :
將 www5 資料夾上傳開發板 :
在 MicroPython 網頁伺服器程式中要針對根目錄 / 與兩個按鈕請求 URL 進行路由處理 :
def handleRoot(socket, args):
with open('./www5/index.html', 'r', encoding='utf-8') as f:
html=f.read()
ESP8266WebServer.ok(socket, "200", "text/html", html)
def handleOn(socket, args):
led.value(0)
ESP8266WebServer.ok(socket, "200", "text/html", "點亮")
def handleOff(socket, args):
led.value(1)
ESP8266WebServer.ok(socket, "200", "text/html", "熄滅")
ESP8266WebServer.onPath("/", handleRoot)
ESP8266WebServer.onPath("/on", handleOn)
ESP8266WebServer.onPath("/off", handleOff)
完整程式碼如下 :
測試 5-7 : 用 jQuery 的 Ajax 功能點亮與熄滅板載 LED [看原始碼]
import ESP8266WebServer
import xtools
import config
from machine import Pin
def handleRoot(socket, args):
with open('./www5/index.html', 'r', encoding='utf-8') as f:
html=f.read()
ESP8266WebServer.ok(socket, "200", "text/html", html)
def handleOn(socket, args):
led.value(0) # GPIO2 板載 LED 輸出 low 為亮
ESP8266WebServer.ok(socket, "200", "text/html", "點亮")
def handleOff(socket, args):
led.value(1) # GPIO2 板載 LED 輸出 high 為滅
ESP8266WebServer.ok(socket, "200", "text/html", "熄滅")
ip=xtools.connect_wifi_led(config.SSID, config.PASSWORD)
led=Pin(2, Pin.OUT)
led.value(1)
ESP8266WebServer.setDocPath("/www5")
ESP8266WebServer.begin(80)
ESP8266WebServer.onPath("/", handleRoot)
ESP8266WebServer.onPath("/on", handleOn)
ESP8266WebServer.onPath("/off", handleOff)
while True:
ESP8266WebServer.handleClient()
結果與上面超連結按鈕範例一樣 (但 index.html 網頁只會載入一次).
沒有留言:
張貼留言