2020年11月14日 星期六

四、5 使用超連結(href) 方式控制多重輸出之三—採用按鈕介面形式


在上一節的《四、4 使用超連結(href)的方式控制多重輸出之二已經把控制的輸出數目擴充了並且也把操作的連接文字縮減為一行讓畫面看起更精簡一些但是這種使用文字的超連結形式看起來還是不夠美觀與方便接下來我們就把輸出控制的介面再修改成按鈕的形式好讓使用者更容易使用於操作而且畫面看起來更簡潔與美觀


範例程式功能與動作說明

1、以ESP32建立一無線WiFi  AP存取點,此AP存取點SSID名稱為  『ESP32_softAP01』,而且不使用密碼該AP存取點內建伺服器的IP位址為:[ 192.168.4.1 ]

2、當客戶端裝置連線上ESP32內建伺服器首頁時(也就是只鍵入IP網址[ 192.168.4.1 ]),系統會回應下面【圖四、5-1】的首頁網頁畫面給客戶端。畫面中下方共有三組按鈕型的超連結輸出控制在每一組控制輸出的上方即標記1處的輸出提示訊息為『[GPIO25:LOW 🡪 LED1熄滅]一眼即可看出目前該輸出腳的編號與狀態及接在這根輸出腳的LED亮滅情形;而位於標記2文字為「”點亮(On)”」的按鈕式超連結選控制項則是代表按下此鍵的功能也就是讓對應的輸出腳輸出高態好讓LED點亮;這個網頁程式一開啟時所有的輸出都是低態所以輸出提示訊息的文字顏色都是藍色而超連結選控制按鈕的底色則為粉紅色。


圖四、5-1 系統首頁網頁連線啟動後客戶端瀏覽器畫面


3、當使用者點選上圖中標記2的點亮這個超連結選項系統會回應下面【圖四、5-2】的網頁畫面給客戶端除了畫面中標記1的『[GPIO25:LOW 🡪 LED1點亮]』回應訊息文字部分的顏色會變為紅色之外上圖中標記2的點亮超連結選項會改成「熄滅(Off)」。如果使用者點選下面【圖四、5-2】的標記2的熄滅(Off)超連結選項整個LED狀態回應訊息與超連結控制的文字部分又會回到上面的【圖四、5-1】畫面也就是說輸出狀態的切換控制只用一個按鈕式的超連結點就可以了

圖四、5-2 點選”點亮”超連結選項後客戶端瀏覽器畫面


電路圖

圖四、5-3 使用ESP32開發板控制三顆LED亮滅電路


本實習和上一小節一樣使用ESP32開發板(類似NodeMcu)控制三顆LED燈同樣是採用GPIO252627這三隻接腳


程式列表與說明

  1. /*

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

  3. 採用按鈕介面形式

  4.  */

  5.  

  6. #include <WiFi.h>

  7. #include  "index.h"

  8. const char* ssid     = "ESP32_softAP01";

  9. const char* password = "12345678";

  10. const int LED1=25,LED2=26,LED3=27;

  11. String  LED1_Status="<font color=blue>GPIO25:Low --> LED1 熄滅</font>",

  12.        LED2_Status="<font color=blue>GPIO26:Low --> LED2 熄滅</font>",

  13.        LED3_Status="<font color=blue>GPIO27:Low --> LED3 熄滅</font>";

  14. String  buttonOn="ON'> <button class='button'>點亮(On)</button> </a>",

  15.        buttonOff="OFF'> <button class='button2'>熄滅(Off)</button>";

  16. String  LED1_Href="<a href='1"+buttonOn,

  17.        LED2_Href="<a href='2"+buttonOn,

  18.        LED3_Href="<a href='3"+buttonOn;

  19.  

  20. unsigned long connectTime = 0; 

  21. const long timeoutTime = 3000;

  22.  

  23. WiFiServer server(80);

  24.  

  25. void setup()

  26. {

  27.     Serial.begin(115200);

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

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

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

  31.  

  32.     delay(10);

  33.  

  34.     WiFi.softAP(ssid);

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

  36.     Serial.println();

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

  38.     Serial.println(ssid);

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

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

  41.     

  42.     server.begin();

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

  44.  

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

  46. void loop(){

  47.  

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

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

  50.   if (client)

  51.   {

  52. //    currentTime = millis();

  53.     connectTime = millis();

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

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

  56.     {

  57. //      currentTime = millis();

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

  59.       if (client.available())

  60.       {

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

  62. //        Serial.print(line);

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

  64.         if (line.indexOf("GET /1ON") >= 0) {

  65.           Serial.println(line);

  66.           digitalWrite(LED1, HIGH);      // GET /H turns the LED on

  67.        LED1_Status="<font color=red>GPIO25:High --> LED1 點亮</font>";

  68.           LED1_Href="<a href='1"+buttonOff;

  69.         }

  70.         if (line.indexOf("GET /1OFF") >= 0) {

  71.           Serial.println(line);

  72.           digitalWrite(LED1, LOW);      // GET /L turns the LED off

  73.        LED1_Status="<font color=blue>GPIO25:Low --> LED1 熄滅</font>";

  74.           LED1_Href="<a href='1"+buttonOn;

  75.         }

  76.         if (line.indexOf("GET /2ON") >= 0) {

  77.           Serial.println(line);

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

  79.        LED2_Status="<font color=red>GPIO26:High --> LED2 點亮</font>";

  80.           LED2_Href="<a href='2"+buttonOff;

  81.         }

  82.         if (line.indexOf("GET /2OFF") >= 0) {

  83.           Serial.println(line);

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

  85.        LED2_Status="<font color=blue>GPIO26:Low --> LED2 熄滅</font>";

  86.           LED2_Href="<a href='2"+buttonOn;

  87.         }

  88.         if (line.indexOf("GET /3ON") >= 0) {

  89.           Serial.println(line);

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

  91.        LED3_Status="<font color=red>GPIO27:High --> LED3 點亮</font>";

  92.           LED3_Href="<a href='3"+buttonOff;

  93.         }

  94.         if (line.indexOf("GET /3OFF") >= 0) {

  95.           Serial.println(line);

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

  97.        LED3_Status="<font color=blue>GPIO27:Low --> LED3 熄滅</font>";

  98.           LED3_Href="<a href='3"+buttonOn;

  99.         }

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

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

  102.         {

  103.           String tmpString = MAIN_page;    // 取出html網頁回應程式

  104.   tmpString.replace("%LED1_Status%", LED1_Status ); // 帶入LED1

  105.                 狀態至回應網頁

  106.        tmpString.replace("%LED2_Status%", LED2_Status ); 

  107.        tmpString.replace("%LED3_Status%", LED3_Status );

  108.          tmpString.replace("%LED1_Href%", LED1_Href ); // 帶入LED1超連

  109. 結狀態至回應網頁

  110.        tmpString.replace("%LED2_Href%", LED2_Href ); 

  111.        tmpString.replace("%LED3_Href%", LED3_Href ); 

  112.           client.println( tmpString );

  113.           break;

  114.         }

  115.       }

  116.     }

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

  118.  

  119.     // close the connection:

  120.     client.stop();

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

  122.   }

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

  124.  

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

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

  127. HTTP/1.1 200 OK

  128. Content-Type:text/html

  129. Connection: close

  130.  

  131. <!DOCTYPE html>

  132. <html>

  133.  <head>

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

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

  136.   <link rel=\"icon\" href=\"data:,\">

  137.   <style>

  138.     body {font-size:110%;} 

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

  140.       .button {padding:10px 10px 10px 10px; width:50%; background-color:pink; font-

  141. size:110%;}

  142.       .button2 {padding:10px 10px 10px 10px; width:50%; background-color:yellowgreen;

  143. font-size:110%;}    

  144.   </style>

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

  146.  </head>

  147.  

  148.  <body> 

  149.    <div id='main'>

  150.      <h3><center>[Soft AP模式] <br>

  151.          使用超連結(href)按鈕控制多重輸出實習3<br><br>

  152.  

  153.          [ %LED1_Status% ]<br>

  154.          %LED1_Href%<br><br>

  155.          

  156.          [ %LED2_Status% ]<br>

  157.          %LED2_Href%<br><br>

  158.          

  159.          [ %LED3_Status% ]<br>

  160.          %LED3_Href%<br>

  161.          </center>

  162.      </h3>

  163.    </div> 

  164.  </body>

  165. </html>

  166.  

  167. )=====";

程式名稱:ESP32_softAP42_3Href2.ino


在本範例程式中變數定義部分,三個回應給客戶端的訊息字串變數「LED1_Status」~ 「LED1_Status」有稍作修改以顯示所使用I/O腳位:


11. String  LED1_Status="<font color=blue>GPIO25:Low --> LED1 熄滅</font>",

12.       LED2_Status="<font color=blue>GPIO26:Low --> LED2 熄滅</font>",

13.       LED3_Status="<font color=blue>GPIO27:Low --> LED3 熄滅</font>";


此外為了配合新增的兩種按鈕元件也增加了兩個不同功能的字串變數


14. String  buttonOn="ON'> <button class='button'>點亮(On)</button> </a>",

15.       buttonOff="OFF'> <button class='button2'>熄滅(Off)</button>";


當然三個回應給客戶端的動態超聯結字串變數LED1_Href~ LED3_Href」也必須跟修改以配合所使用的按鈕元件:


16. String  LED1_Href="<a href='1"+buttonOn,

17.       LED2_Href="<a href='2"+buttonOn,

18.    LED3_Href="<a href='3"+buttonOn;



至於初始化程式(setup())部分(25~43行)和上一個範例完全相同

而在主迴圈(loop())的部分(46~120行)和上一個範例的差異主要是在”while()”(54~113行)這個流程控制中測試URI請求的部分,其中61~72行在判斷客戶端所傳來的URI是代表點亮LED1的字串『"GET /ON1"』﹖還是熄滅LED1的『"GET /OFF1"』﹖再依照測試結果控制LED1的亮滅,並把訊息顯示在Arduino IDE的監控式窗而且也把對應的輸出回應訊息放到字串變數「LED1_Status」上,並把下一次要使用的超連結控制按鈕傳送到字串變數LED1_Href最後再帶入html網頁程式中。


61.        if (line.indexOf("GET /1ON") >= 0) {

62.          Serial.println(line);

63.          digitalWrite(LED1, HIGH);      // GET /H turns the LED on

64.       LED1_Status="<font color=red>GPIO25:High --> LED1 點亮</font>";

65.          LED1_Href="<a href='1"+buttonOff;

66.        }

67.        if (line.indexOf("GET /1OFF") >= 0) {

68.          Serial.println(line);

69.          digitalWrite(LED1, LOW);      // GET /L turns the LED off

70.       LED1_Status="<font color=blue>GPIO25:Low --> LED1 熄滅</font>";

71.          LED1_Href="<a href='1"+buttonOn;

72.        }


至於輸出2及輸出3部分則分別由73~84行與85~96行負責

再來就是回傳到html網頁程式部分(100~109行)和上一個範例完全一樣:


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~164行是「index.h」這個頁面的內容,是回應給發出請求的客戶端的html網頁程式;和之前範例的主要差異之處是在137~144行的CSS語法區(<style>……</style>)中多了兩個按鈕外觀的定義:


140.      .button {padding:10px 10px 10px 10px; width:50%; 

141. background-color:pink; font-size:110%;}

142.      .button2 {padding:10px 10px 10px 10px; width:50%; 

143. background-color:yellowgreen; font-size:110%;}    


接著在146、147行中實現【圖四、5-1】畫面上方的『[Soft AP模式] 使用超連結(href)按鈕控制多重輸出實習3』的提示訊息,而153~160行則會將前面迴圈主程式所傳來的「LED1_Status」~「LED3_Status」與「LED1_Href~ LED3_Href這兩組字串變數帶入這個html網頁程式中,最後把輸出結果回應給客戶端的瀏覽器。


153.         [ %LED1_Status% ]<br>

154.         %LED1_Href%<br><br>

155.         

156.         [ %LED2_Status% ]<br>

157.         %LED2_Href%<br><br>

158.         

159.         [ %LED3_Status% ]<br>

160.         %LED3_Href%<br>


執行結果:

在程式執行之後,開啟手機/平板/筆電的WiFi功能,在看到”ESP32_softAP01”這個AP存取點後點選它,接著啟動瀏覽器,並在網址輸入欄中輸入[ 192.168.4.1 ]這個IP位址並前往。如果連線正常將會看到【圖四、5-1】的畫面,而下面的【圖四、5-4】網頁畫面是客戶端瀏覽器各種輸出控制回應畫面,當上方訊息是LED點亮或輸出腳輸出為High時下面的超連結選項按鈕文字會呈現「”熄滅”」,反之如果上方訊息是LED熄滅或輸出腳輸出為Low時下面的超連結選項按鈕文字會呈現「”點亮”」。

圖四、5-4 客戶端瀏覽器各種輸出控制回應畫面


沒有留言:

張貼留言

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

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