2020年11月9日 星期一

四、4 使用超連結(href)的方式控制多重輸出之二


在上一節的《四、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燈同樣是採用GPIO252627這三隻接腳


程式列表與說明

以下是這個範例的完整程式列表內容:



  1. /*

  2.   ESP32 soft AP 範例四 : 四、4  使用超連結(href)的方式控制多重輸出之二

  3.  */

  4.  

  5. #include <WiFi.h>

  6. #include  "index.h"

  7. const char* ssid     = "ESP32_softAP01";

  8. const char* password = "12345678";

  9. const int LED1=26,LED2=25,LED3=17;

  10. String  LED1_Status="<font color=blue>LED1 熄滅</font>",

  11.    LED2_Status="<font color=blue>LED2 熄滅</font>",

  12.    LED3_Status="<font color=blue>LED3 熄滅</font>";

  13. String  LED1_Href="<a href='ON1'> 點亮 </a>",

  14.    LED2_Href="<a href='ON2'> 點亮 </a>",

  15.    LED3_Href="<a href='ON3'> 點亮 </a>";

  16.  

  17. unsigned long connectTime = 0; 

  18. const long timeoutTime = 3000;

  19.  

  20. WiFiServer server(80);

  21.  

  22. // 初始化設定程式開始:

  23. void setup()

  24. {

  25.     Serial.begin(115200);

  26.     pinMode(LED1, OUTPUT);      // set the LED pin mode

  27.     pinMode(LED2, OUTPUT);      // set the LED pin mode

  28.     pinMode(LED3, OUTPUT);      // set the LED pin mode

  29.  

  30.     delay(10);

  31.  

  32.     // We start by connecting to a WiFi network

  33.     WiFi.softAP(ssid);

  34.     Serial.println("Setting softAP ...");

  35.     Serial.println();

  36.     Serial.print("Your softAP is : ");

  37.     Serial.println(ssid);

  38.     Serial.println("IP address: ");

  39.     Serial.println(WiFi.softAPIP());

  40.     

  41.     server.begin();

  42. }   // 初始化設定程式結束.

  43.  

  44. // 主迴圈程式開始:

  45. void loop(){

  46.  

  47.   WiFiClient client = server.available();   // listen for incoming clients

  48.   // wait for a client (web browser) to connect

  49.   if (client)

  50.   {

  51.     connectTime = millis();

  52.     Serial.println("\n[Client connected]");

  53.     while (client.connected() && millis() - connectTime <= timeoutTime)

  54.     {

  55.       // read line by line what the client (web browser) is requesting

  56.       if (client.available())

  57.       {

  58.         String line = client.readStringUntil('\r');

  59. //        Serial.print(line);

  60.         // Check to see if the client request was "GET /H" or "GET /L":

  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.         }

  73.         if (line.indexOf("GET /ON2") >= 0) {

  74.           Serial.println(line);

  75.           digitalWrite(LED2, HIGH);       // GET /H turns the LED on

  76.           LED2_Status="<font color=red>LED2 點亮</font>";

  77.           LED2_Href="<a href='OFF2'> 熄滅 </a>";

  78.         }

  79.         if (line.indexOf("GET /OFF2") >= 0) {

  80.           Serial.println(line);

  81.           digitalWrite(LED2, LOW);        // GET /L turns the LED off

  82.           LED2_Status="<font color=blue>LED2 熄滅</font>";

  83.           LED2_Href="<a href='ON2'> 點亮 </a>";

  84.         }

  85.         if (line.indexOf("GET /ON3") >= 0) {

  86.           Serial.println(line);

  87.           digitalWrite(LED3, HIGH);        // GET /H turns the LED on

  88.           LED3_Status="<font color=red>LED3 點亮</font>";

  89.           LED3_Href="<a href='OFF3'> 熄滅 </a>";

  90.         }

  91.         if (line.indexOf("GET /OFF3") >= 0) {

  92.           Serial.println(line);

  93.           digitalWrite(LED3, LOW);        // GET /L turns the LED off

  94.           LED3_Status="<font color=blue>LED3 熄滅</font>";

  95.           LED3_Href="<a href='ON3'> 點亮 </a>";

  96.         }

  97.         // wait for end of client's request, that is marked with an empty line

  98.         if (line.length() == 1 && line[0] == '\n')

  99.         {

  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 );

  110.           break;

  111.         }

  112.       }

  113.     }

  114.     delay(1); // give the web browser time to receive the data

  115.  

  116.     // close the connection:

  117.     client.stop();

  118.     Serial.println("[Client disonnected]");

  119.   }

  120. } // 主迴圈程式結束.

  121.  

  122. // 以下部分為「index.h」標籤頁面的內容:

  123. const char MAIN_page[] PROGMEM = R"=====(

  124. HTTP/1.1 200 OK

  125. Content-Type:text/html

  126. Connection: close

  127.  

  128. <!DOCTYPE html>

  129. <html>

  130.  <head>

  131.   <meta name='viewport' content='width=device-width, initial-scale=1.0'/>

  132.   <meta charset='utf-8'>

  133.  <meta http-equiv='refresh' content='%rTime%'>

  134.   <style>

  135.     body {font-size:100%;} 

  136.     #main {display: table; margin: auto;  padding: 0 10px 0 10px; } 

  137.   </style>

  138.   <title>Soft AP模式-使用超連結(href)控制多重輸出實習</title>

  139.  </head>

  140.  

  141.  <body> 

  142.    <div id='main'>

  143.      <h2><center>[Soft AP模式] <br>

  144.          使用超連結(href)控制多重輸出實習2<br><br>

  145.  

  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>

  154.          </center>

  155.      </h3>

  156.    </div> 

  157.  </body>

  158. </html>

  159.  

  160. )=====";

程式名稱: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開發板來測試我們的範例程式


沒有留言:

張貼留言

三、使用Line Notify傳送照片之安全監控系統之二---低功耗篇

在前一個章節中 , 我們建構了一個標準照片擷取 、 傳送與儲存的按全監控裝置 , 不過假如我們使用的場域中有許多的地方都必須按裝這類的裝置時 , 例如在一個有許多門 、 窗的家庭或辦公室 , 由於我們的系統使用無線WiFi作為信號傳輸之用 , 所以信號的傳輸除非裝置離WiFi分享...