四、 ESP32存取點(AP)模式輸出控制及應用
四、1 直接使用GET(URI)的方式控制輸出
在前面的《三、存取點(AP)模式內建網路伺服器(WebServer)設計—GET請的解析》一節中曾說明過,在HTTP 的GET請求中最重要的部分是請求行(request Line) ,所謂的請求行主要包括兩個部份,其中一部分是所謂的URI(Uniform Resource Identifier),即請求的內容,也就是跟著網頁位址後面的訊息;例如我們使用瀏覽器連上伺服器網頁首頁時,送出的URI內容便是”/”,而當我們在網址輸入欄鍵入「192.168.4.1/test」這樣的網址資料時,URI則是”/test”。在本單元中我們就以這個特性,示範如何去控制ESP32開發模組板上內建LED的亮滅。
◎電路圖:
圖四、1-1 不同類型ESP32開發模組板內建LED(GPIO2)位置
本實習所使用的LED燈為了方便起見所以是採用內建於ESP32開發模組板上GPIO2的LED燈,也就是說所並不需要再外接了!不過並不是所有的ESP32開發模組板上都內建有這顆接在GPIO2的LED燈,上面【圖四、1-1】中的兩款是本實習建議使用的ESP32開發模組板,左邊是「WeMos D1 R32」板,右邊是常見的「ESP32 DEVKIT」板,這顆接在GPIO2的LED燈的位置已標示在圖片中,使用者應該很容易找到才是。
◎ 範例程式功能與動作說明:
1、以ESP32建立一無線WiFi AP存取點,此AP存取點SSID名稱為 『ESP32_softAP01』,而且不使用密碼。
2、此AP存取點內建伺服器的IP位址為:[ 192.168.4.1 ]。
3、當客戶端裝置連線上ESP32內建伺服器首頁時(也就是只鍵入IP網址[ 192.168.4.1 ]),系統會回應下面【圖四、1-2】的畫面給客戶端。畫面上方的『[Soft AP模式] 使用Get控制單一輸出實習』部分固定不變,是用來提示本實習的內容,而下方的『請輸入指令(On/Off)』部分則會依操作狀況改變,在此是當使用者連上網頁首頁,或者是輸入錯誤指令時ESP32開發模組板回應的訊息。
圖四、1-2 系統首頁畫面
4、如果輸入的是: [ 192.168.4.1 /on],則如【圖四、1-3】所示,ESP32開發模組板上內建的LED會點亮,而且系統會回應『GPIO2:High --> LED點亮』的訊息給客戶端。
圖四、1-3 使用URI指令「/on」點亮ESP32開發板內建LED畫面
5、如果輸入的是: [ 192.168.0.100 /LedOff],則如【圖四、1-4】所示,ESP32開發模組板上內建的LED會熄滅,而且系統會回應『GPIO2:Low --> LED熄滅』的訊息給客戶端。
圖四、1-4 使用URI指令「/off」熄滅ESP32開發板內建LED畫面
6、假如使用者輸入的內容不在前面幾種的條件裡面,那麼系統會則如【圖四、1-2】所示,會回應『請輸入指令(On/Off)』這樣的訊息給客戶端,告訴使用者應該輸入什麼樣的指令,在此「On/Off」指令碼中的英文字元大小寫都可以使用,以方便使用者操作。
◎程式列表與說明:
以下是這個範例的完整程式內容:
/*
ESP32 soft AP 範例三 : 四、1 直接使用GET(URI)的方式控制輸出
*/
#include <WiFi.h>
#include "index.h"
const char* ssid = "ESP32_softAP01";
const char* password = "12345678";
const byte indLED=2;
String echoBack="";
WiFiServer server(80);
// 初始化設定程式開始:
void setup()
{
Serial.begin(115200);
pinMode(indLED,OUTPUT);
delay(10);
// We start by connecting to a WiFi network
WiFi.softAP(ssid);
Serial.println("Setting softAP ...");
Serial.println();
Serial.print("Your softAP is : ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
server.begin(); // 啟動伺服器功能
} // 初始化設定程式結束.
// 主迴圈程式開始:
void loop(){
WiFiClient client = server.available(); // 監聽是否有客戶端到來
// wait for a client (web browser) to connect
if (client)
{
echoBack="請輸入指令(On/Off)";
Serial.println("\n[Client connected]");
while (client.connected())
{
// read line by line what the client (web browser) is requesting
if (client.available())
{
String line = client.readStringUntil('\r');
line.toUpperCase();
// Check to see if the client request was "GET /H" or "GET /L":
if (line.indexOf("GET /ON") >= 0) {
echoBack="GPIO2:High --> LED點亮";
Serial.println(line);
Serial.println(echoBack);
digitalWrite(indLED, HIGH); // GET /H turns the LED on
}
if (line.indexOf("GET /OFF") >= 0) {
echoBack="GPIO2:Low --> LED熄滅";
Serial.println(line);
Serial.println(echoBack);
digitalWrite(indLED, LOW); // GET /L turns the LED off
}
// 測試是否為客戶端請求結束空白行:
if (line.length() == 1 && line[0] == '\n')
{
String tmpString = MAIN_page; // 取出html網頁回應程式
tmpString.replace("%echoBack%", echoBack ); //帶入回應字串變數 // 至回應網頁html程式中
client.print( tmpString );
break;
}
}
}
delay(1); // give the web browser time to receive the data
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
}
} // 主迴圈程式結束.
// 以下部分為「index.h」標籤頁面的內容:
const char MAIN_page[] PROGMEM = R"=====(
HTTP/1.1 200 OK
Content-Type:text/html
<!DOCTYPE html>
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0'/>
<meta charset='utf-8'>
<link rel="icon" href="data:,">
<style>
body {font-size:100%;}
#main {display: table; margin: auto; padding: 0 10px 0 10px; }
</style>
<title>Soft AP模式-使用Get控制單一輸出實習</title>
</head>
<body>
<div id='main'>
<h2><center>[Soft AP模式] <br>
使用Get控制單一輸出實習<br><br>
%echoBack%
</center>
</h2>
</div>
</body>
</html>
)=====";
程式名稱:ESP32_softAP4_getRUI.ino
本範例和上一個在初始化程式(setup())部分幾乎完全一樣,只是多了19行的設定GPIO2為輸出的功能:
19. pinMode(indLED,OUTPUT);
而在主迴圈(loop())的部分則多了第41行的預先設定回傳訊息用字串變數「echoBack」的內容為『"請輸入指令(On/Off)"』的程式:
41. echoBack="請輸入指令(On/Off)";
當有客戶端裝置連線到伺服器,主迴圈程式剩下的部分便會開始接收與回應客戶端的請求訊息。43~74行程式是以while()迴圈的方式來持續的接收客戶端傳來的請求訊息,直到接收到代表請求結束的空行字串為止。48~49行程式會逐行讀取客戶端送來的訊息,並把該行字串訊息所有的英文字元轉換成大寫,以方便後面的判斷動作,這樣也可以減少使用者因為輸入大小寫的問題而產生錯誤。
48. String line = client.readStringUntil('\r'); // 逐行讀取客戶端送來的訊息
49. line.toUpperCase(); // 將該行訊息所有的英文字元轉換成大寫
接著的51~56行程式在判斷客戶端所傳來的URI是否為代表點亮LED的字串『"GET /ON"』﹖如果是,則先將回應訊息字串變數「echoBack」的內容改為『" GPIO2:High --> LED點亮"』,並把訊息顯示在Arduino IDE的監控式窗,最後再點亮接在GPIO2的LED(55行)。
51. if (line.indexOf("GET /ON") >= 0) {
52. echoBack="GPIO2:High --> LED點亮";
53. Serial.println(line);
54. Serial.println(echoBack);
55. digitalWrite(indLED, HIGH); // GET /H turns the LED on
56. }
再下來的57~62行程式應改很容看出是在測試所傳來的URI是否為代表熄滅LED的字串『"GET /OFF"』﹖如果是,則會將回應訊息字串變數「echoBack」的內容改為『" GPIO2:Low --> LED熄滅"』外,一樣並把訊息顯示在Arduino IDE的監控式窗之後,再讓接在GPIO2的LED熄滅。
57. if (line.indexOf("GET /OFF") >= 0) {
58. echoBack="GPIO2:Low --> LED熄滅";
59. Serial.println(line);
60. Serial.println(echoBack);
61. digitalWrite(indLED, LOW); // GET /L turns the LED off
62 }
當程式測試接收到代表結束請求傳送的空白行字串時(65~72行),便會把網頁首頁程式MAIN_page[]傳送到tmpString這個字串變數中,同時也把回應訊息字串變數「echoBack」帶入到tmpString這個網頁html程式內,在送出回應網頁程式至客戶端後,以”break”的整令結束while()迴圈。
65. if (line.length() == 1 && line[0] == '\n') // 測試HTTP請求是否結束
66. {
67. String tmpString = MAIN_page; // 取出html網頁回應程式
68. tmpString.replace("%echoBack%", echoBack); // 帶入回應字串變數
69. 至回應網頁html程式中
70. client.print( tmpString ); // 送出回應網頁程式至客戶端
71. break;
72. }
後面剩下的83~110行是「index.h」這個頁面的內容,是一個完整的html網頁程式,在此一樣是使用C++語言中稱為原始字串 (Raw String) 的語法:
const char MAIN_page[] PROGMEM = R"=====( ……….. )=====";
這個html網頁程式的主體(即99~107行的<body>…</body>中間)部分如下:
99. <body>
100. <div id='main'>
101. <h2><center>[Soft AP模式] <br>
102. 使用Get控制單一輸出實習<br><br>
103. %echoBack%
104. </center>
105. </h2>
106 </div>
107. </body>
其中的101、102行用來實現【圖四、1-2】畫面上方的『[Soft AP模式] 使用Get控制單一輸出實習』的提示訊息,而103行則會將前面68行所傳來的「echoBack」字串變數帶入程式中,將最後的測試及輸出結果回應給客戶端的使用者。
◎ 執行結果:
在程式執行之後,開啟手機/平板/筆電的WiFi功能,在看到”ESP32_softAP01”這個AP存取點後點選它,接著啟動瀏覽器,並在網址輸入欄中輸入[ 192.168.4.1 ]這個IP位址並前往。如果連線正常將會看到【圖四、1-2】畫面也就是系統內建伺服器的首頁畫面。
假如在網址輸入欄中輸入[ 192.168.4.1/on ] 的內容並前往,如果連線正常將會看到【圖四、1-3】的畫面,此時ESP32開發板上內建於GPIO2上的LED會點亮。當在瀏覽器輸入[ 192.168.4.1/off ]的內容時,出現的是【圖四、1-4】的畫面,也就是讓LED熄滅的狀態。
如果按照我們前面所訂定的功能與規範,使用者在手機瀏覽器網址輸入欄中輸入的是前三者之外的內容,例如輸入[ 192.168.4.1/o ]也就是錯誤的RUI請求,那麼系統應該會回應【圖四、1-2】畫面;但是如果輸入的是[ 192.168.4.1/onoff ] 或[ 192.168.4.1/offon ]會是什麼結果呢﹖如果讀者有去實作本範例出來將會發現,前者會點亮LED,而後者則是令LED熄滅,也就是說這個範例所能提供的控制動作並不是太精準!當然我們可以把程式改良到很精確,但是由於使用者操作起來也不是很方便,除非只是想設計一個非常簡易的系統,否則這種方式不建議採用。在此只是想讓讀者能熟悉當ESP32定位在一個網頁伺服器時,該如何檢測瀏覽器RUI的請求,並給予正確的回應。
沒有留言:
張貼留言