在上一節的《四、3 使用超連結(href)的方式控制多重輸出之一》中,已經把控制的輸出數目擴充了,但是以這種文字形式的超連接方式,一個輸出點要使用兩個連接點,在畫面上會感覺有些擁擠,如果增加更多的控制輸出點時這個問題會更加嚴重!在這個範例中將示範如何把操作的連接文字縮減為一行,讓畫面看起更精簡一些,但是可以達到一樣的輸出控制效果。
◎ 範例程式功能與動作說明:
1、以ESP32建立一無線WiFi AP存取點,此AP存取點SSID名稱為 『ESP32_softAP01』,而且不使用密碼,該AP存取點內建伺服器的IP位址為:[ 192.168.4.1 ]。
2、當客戶端裝置連線上ESP32內建伺服器首頁時(也就是只鍵入IP網址[ 192.168.4.1 ]),系統會回應下面【圖四、4-1】的首頁網頁畫面給客戶端。畫面中下方共有三組文字型的超連結輸出控制,在此只有一個超連接的控制文字,也就標記2的「”點亮”」這個超連結選項;這個網頁程式一開啟時所有的輸出都是低態,所以會出現標記1的『[LED熄滅]』輸出提示訊息,其文字部分的顏色是藍色。
圖四、4-1 系統首頁網頁連線啟動後客戶端瀏覽器畫面
3、當使用者點選上圖中標記2的「”點亮”」這個超連結選項時,系統會回應下面【圖四、4-2】的網頁畫面給客戶端,除了畫面中標記1的『[LED點亮]』回應訊息文字部分的顏色會變為紅色之外,上圖中標記2的「”點亮”」超連結選項會改成「”熄滅”」。如果使用者點選下面【圖四、4-2】的標記2的「”熄滅”」超連結選項時,整個LED狀態回應訊息與超連結控制的文字部分又會回到上面的【圖四、4-1】畫面,也就是說輸出狀態的切換控制只用一個超連結點就可以了。
圖四、4-2 點選”點亮”超連結選項後客戶端瀏覽器畫面
◎電路圖:
圖四、4-3 使用ESP32開發板控制三顆LED亮滅電路
本實習和上一小節一樣,使用ESP32開發板(類似NodeMcu)控制三顆LED燈,同樣是採用GPIO25、26、27這三隻接腳。
◎程式列表與說明:
以下是這個範例的完整程式列表內容:
/*
ESP32 soft AP 範例四 : 四、4 使用超連結(href)的方式控制多重輸出之二
*/
#include <WiFi.h>
#include "index.h"
const char* ssid = "ESP32_softAP01";
const char* password = "12345678";
const int LED1=26,LED2=25,LED3=17;
String LED1_Status="<font color=blue>LED1 熄滅</font>",
LED2_Status="<font color=blue>LED2 熄滅</font>",
LED3_Status="<font color=blue>LED3 熄滅</font>";
String LED1_Href="<a href='ON1'> 點亮 </a>",
LED2_Href="<a href='ON2'> 點亮 </a>",
LED3_Href="<a href='ON3'> 點亮 </a>";
unsigned long connectTime = 0;
const long timeoutTime = 3000;
WiFiServer server(80);
// 初始化設定程式開始:
void setup()
{
Serial.begin(115200);
pinMode(LED1, OUTPUT); // set the LED pin mode
pinMode(LED2, OUTPUT); // set the LED pin mode
pinMode(LED3, OUTPUT); // set the LED pin mode
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.println("IP address: ");
Serial.println(WiFi.softAPIP());
server.begin();
} // 初始化設定程式結束.
// 主迴圈程式開始:
void loop(){
WiFiClient client = server.available(); // listen for incoming clients
// wait for a client (web browser) to connect
if (client)
{
connectTime = millis();
Serial.println("\n[Client connected]");
while (client.connected() && millis() - connectTime <= timeoutTime)
{
// read line by line what the client (web browser) is requesting
if (client.available())
{
String line = client.readStringUntil('\r');
// Serial.print(line);
// Check to see if the client request was "GET /H" or "GET /L":
if (line.indexOf("GET /ON1") >= 0) {
Serial.println(line);
digitalWrite(LED1, HIGH); // GET /H turns the LED on
LED1_Status="<font color=red>LED1 點亮</font>";
LED1_Href="<a href='OFF1'> 熄滅 </a>";
}
if (line.indexOf("GET /OFF1") >= 0) {
Serial.println(line);
digitalWrite(LED1, LOW); // GET /L turns the LED off
LED1_Status="<font color=blue>LED1 熄滅</font>";
LED1_Href="<a href='ON1'> 點亮 </a>";
}
if (line.indexOf("GET /ON2") >= 0) {
Serial.println(line);
digitalWrite(LED2, HIGH); // GET /H turns the LED on
LED2_Status="<font color=red>LED2 點亮</font>";
LED2_Href="<a href='OFF2'> 熄滅 </a>";
}
if (line.indexOf("GET /OFF2") >= 0) {
Serial.println(line);
digitalWrite(LED2, LOW); // GET /L turns the LED off
LED2_Status="<font color=blue>LED2 熄滅</font>";
LED2_Href="<a href='ON2'> 點亮 </a>";
}
if (line.indexOf("GET /ON3") >= 0) {
Serial.println(line);
digitalWrite(LED3, HIGH); // GET /H turns the LED on
LED3_Status="<font color=red>LED3 點亮</font>";
LED3_Href="<a href='OFF3'> 熄滅 </a>";
}
if (line.indexOf("GET /OFF3") >= 0) {
Serial.println(line);
digitalWrite(LED3, LOW); // GET /L turns the LED off
LED3_Status="<font color=blue>LED3 熄滅</font>";
LED3_Href="<a href='ON3'> 點亮 </a>";
}
// wait for end of client's request, that is marked with an empty line
if (line.length() == 1 && line[0] == '\n')
{
String tmpString = MAIN_page; // 取出html網頁回應程式
tmpString.replace("%LED1_Status%", LED1_Status ); // 帶入LED1
狀態至回應網頁
tmpString.replace("%LED2_Status%", LED2_Status );
tmpString.replace("%LED3_Status%", LED3_Status );
tmpString.replace("%LED1_Href%", LED1_Href ); // 帶入LED1超連
結狀態至回應網頁
tmpString.replace("%LED2_Href%", LED2_Href );
tmpString.replace("%LED3_Href%", LED3_Href );
client.println( tmpString );
break;
}
}
}
delay(1); // give the web browser time to receive the data
// close the connection:
client.stop();
Serial.println("[Client disonnected]");
}
} // 主迴圈程式結束.
// 以下部分為「index.h」標籤頁面的內容:
const char MAIN_page[] PROGMEM = R"=====(
HTTP/1.1 200 OK
Content-Type:text/html
Connection: close
<!DOCTYPE html>
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0'/>
<meta charset='utf-8'>
<meta http-equiv='refresh' content='%rTime%'>
<style>
body {font-size:100%;}
#main {display: table; margin: auto; padding: 0 10px 0 10px; }
</style>
<title>Soft AP模式-使用超連結(href)控制多重輸出實習</title>
</head>
<body>
<div id='main'>
<h2><center>[Soft AP模式] <br>
使用超連結(href)控制多重輸出實習2<br><br>
[ %LED1_Status% ]<br>
請按這裡 %LED1_Href% LED1.<br><br>
[ %LED2_Status% ]<br>
請按這裡 %LED2_Href% </a> LED2.<br><br>
[ %LED3_Status% ]<br>
請按這裡 %LED3_Href% LED3.<br>
</center>
</h3>
</div>
</body>
</html>
)=====";
程式名稱:ESP32_softAP42_3Href1.ino
在本範例程式中變數定義部分,新增加了三個回應給客戶端的動態超聯結字串變數,即「LED1_Href」~ 「LED3_Href」:
13. String LED1_Href="<a href='ON1'> 點亮 </a>",
14. LED2_Href="<a href='ON2'> 點亮 </a>",
15. LED3_Href="<a href='ON3'> 點亮 </a>";
至於初始化程式(setup())部分(23~42行),則是和上一個範例完全相同。
而在主迴圈(loop())的部分(45~120行)和上一個範例的差異,主要是在”while()”(53~113行)這個流程控制中測試URI請求的部分,其中61~72行在判斷客戶端所傳來的URI是代表點亮LED1的字串『"GET /ON1"』﹖還是熄滅LED1的『"GET /OFF1"』﹖再依照測試結果控制LED1的亮滅,並把訊息顯示在Arduino IDE的監控式窗,而且也把對應的輸出回應訊息放到字串變數「LED1_Status」上,並把下一次要使用的超連結控制字串傳送到字串變數「LED1_Href」,最後再帶入html網頁程式中。
61. if (line.indexOf("GET /ON1") >= 0) {
62. Serial.println(line);
63. digitalWrite(LED1, HIGH); // GET /H turns the LED on
64. LED1_Status="<font color=red>LED1 點亮</font>";
65. LED1_Href="<a href='OFF1'> 熄滅 </a>";
66. }
67. if (line.indexOf("GET /OFF1") >= 0) {
68. Serial.println(line);
69. digitalWrite(LED1, LOW); // GET /L turns the LED off
70. LED1_Status="<font color=blue>LED1 熄滅</font>";
71. LED1_Href="<a href='ON1'> 點亮 </a>";
72 }
至於輸出2及輸出3部分,則分別由73~84行與85~96行負責。
再來就是回傳到html網頁程式部分(100~109行),除了之前已經介紹過代表LED輸出狀態的字串變數「LED1_Status」~「LED3_Status」之外,還多了三個動態的超連結控制字串變數「LED1_Href」~ 「LED3_Href」:
100. String tmpString = MAIN_page; // 取出html網頁回應程式
101. tmpString.replace("%LED1_Status%", LED1_Status ); // 帶入LED1
102. 狀態至回應網頁
103. tmpString.replace("%LED2_Status%", LED2_Status );
104. tmpString.replace("%LED3_Status%", LED3_Status );
105. tmpString.replace("%LED1_Href%", LED1_Href ); // 帶入LED1超連
106. 結狀態至回應網頁
107. tmpString.replace("%LED2_Href%", LED2_Href );
108. tmpString.replace("%LED3_Href%", LED3_Href );
109. client.println( tmpString );
後面的123~160行是「index.h」這個頁面的內容,是回應給發出請求的客戶端的html網頁程式,在此也是使用C++語言中稱為原始字串 (Raw String) 的語法;其中的143、144行會實現【圖四、4-1】畫面上方的『[Soft AP模式] 使用超連結(href)控制多重輸出實習2』的提示訊息,而146~153行則會將前面迴圈主程式所傳來的「LED1_Status」~「LED3_Status」與LED1_Href」~ 「LED3_Href」這兩組字串變數帶入這個html網頁程式中,將最後的輸出結果回應給客戶端的瀏覽器。
146. [ %LED1_Status% ]<br>
147. 請按這裡 %LED1_Href% LED1.<br><br>
148.
149. [ %LED2_Status% ]<br>
150. 請按這裡 %LED2_Href% </a> LED2.<br><br>
151.
152. [ %LED3_Status% ]<br>
153. 請按這裡 %LED3_Href% LED3.<br>
◎ 執行結果:
在開啟手機/平板/筆電的WiFi功能,看到”ESP32_softAP01”這個AP存取點後點選它,接著啟動瀏覽器,並在網址輸入欄中輸入[ 192.168.4.1 ]這個IP位址並前往。如果連線正常將會看到前面【圖四、4-1】的畫面,下方的【圖四、4-4】是客戶端瀏覽器在不同的輸出控制狀態的畫面,當LED輸出狀態的提示訊息是【LED點亮】時,該組下方的控制超連接點選選項是「”熄滅”」,反之當LED輸出狀態的提示訊息是【LED熄滅】時,該組下方的控制超連接點選選項會變成「”點亮”」。 這樣的網頁界面可以讓我們只用一組超連結文字便可以控制一個輸出端點,也讓整個螢幕畫面看起來簡潔許多!
圖四、4-4 客戶端瀏覽器各種輸出控制回應畫面
圖四、4-5 ESP32開發板電路各種輸出控制對應狀況畫面
【圖四、4-5】照片的內容,是對應【圖四、4-4】四種客戶端瀏覽器畫面的實際電路輸出狀況,同樣也是使用WeMos D1/R32 ESP32開發板來測試我們的範例程式。
沒有留言:
張貼留言