WiFi Manager(三):在WiFi管理員程式中加入自訂的網站伺服器

延續第一篇貼文的程式碼,本單元將說明結合WiFi管理員的ESP網站伺服器程式的注意事項。由於ESP8266和ESP32的HTTP伺服器程式庫名稱不同,所以引用時必須透過巨集條件式,判斷編譯的目標開發板類型:

#include <WiFiManager.h>  // 引用WiFi管理員程式庫
#ifdef ESP8266                  // 若晶片類型是ESP8266
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>   // ESP8266網站伺服器程式庫
ESP8266WebServer server(80);    // 建立網站伺服器物件
#elif defined(ESP32)            // 若晶片類型是ESP32
#include <ESPmDNS.h>
#include <WebServer.h>    // ESP32網站伺服器程式庫
WebServer server(80);           // 建立網站伺服器物件
#endif

附加網站伺服器物件的路由處理函式,寫在setup()裡面,像這樣:

void setup() {
  WiFi.mode(WIFI_STA);   // Wi-Fi設置成STA模式
   : 略
  // 設定我們自訂的網站伺服器
  server.on("/", []() {    // 處理”/”路徑的路由
    server.send(200, "text/html; charset=utf-8", "人生最大的風險,<br>就是不願意冒險。");
  });
  server.onNotFound([]() { // 處理「找不到指定資源」的路由
    server.send(404, "text/plain", "File NOT found!");
  });

  server.begin(); // 啟動網站伺服器
}

包含自訂的網站伺服器程式的完整但有問題的程式碼如下,這個程式也設定了啟動AP模式的回呼函式“APCallback”:

#include <WiFiManager.h>  // https://github.com/tzapu/WiFiManager
#ifdef ESP8266                  // 若晶片類型是ESP8266
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>   // ESP8266網站伺服器程式庫
ESP8266WebServer server(80);    // 建立網站伺服器物件
#elif defined(ESP32)            // 若晶片類型是ESP32
#include <ESPmDNS.h>
#include <WebServer.h>        // ESP32網站伺服器程式庫
WebServer server(80);           // 建立網站伺服器物件
#endif

#define AP_SSID "JarvisAP"      // 自訂的ESP裝置AP名稱
#define AP_PWD  "12345678"      // 自訂的AP密碼
#define TRIGGER_PIN 0           // 啟用「Wi-Fi設置入口」的按鍵接腳

WiFiManager wm;                 // 建立WiFi管理員物件

unsigned int  timeout   = 120; // Wi-Fi管理員的運作秒數
unsigned int  startTime = millis();
bool portalRunning      = false;
bool startAP = true; // 僅啟動網站伺服器,設成true則啟動AP和網站伺服器。

void APCallback (WiFiManager *ptWM) {
  Serial.print("啟動AP模式,AP的SSID:");
  Serial.println(ptWM->getConfigPortalSSID());
  Serial.print("IP位址:");
  Serial.println(WiFi.softAPIP());
}

void doWiFiManager() {
  if (portalRunning) {
    wm.process();
    if ((millis() - startTime) > (timeout * 1000)) {
      Serial.println("「Wi-Fi設置入口」操作逾時…");
      portalRunning = false;

      if (startAP) {
        wm.stopConfigPortal();
      } else {
        wm.stopWebPortal();
      }
    }
  }

  // 若啟用「Wi-Fi設置入口」的接腳被按一下…
  if (digitalRead(TRIGGER_PIN) == LOW && (!portalRunning)) {    
    if (startAP) {
      Serial.println("按鈕被按下了,啟動設置入口。");
      wm.setConfigPortalBlocking(false);
      wm.startConfigPortal(AP_SSID, AP_PWD);
    } else {
      Serial.println("按鈕被按下了,啟動Web入口。");
      wm.startWebPortal();
    }
    portalRunning = true;
    startTime = millis();
  }
}

void setup() {
  WiFi.mode(WIFI_STA); // Wi-Fi設置成STA模式;預設模式為STA+AP

  Serial.begin(115200);
  Serial.setDebugOutput(true);
  delay(1000);
  pinMode(TRIGGER_PIN, INPUT_PULLUP);

  wm.setHostname("jarvis");     // 設置ESP的主機名稱
  // wm.setDebugOutput(false);  // 關閉除錯訊息
  wm.setAPCallback(APCallback);
  wm.autoConnect(AP_SSID, AP_PWD);
  // 設定我們自訂的網站伺服器
  server.on("/", []() {      // 處理”/”路徑的路由
    server.send(200, "text/html; charset=utf-8", "人生最大的風險,<br>就是不願意冒險。");
  });
  server.onNotFound([]() { // 處理「找不到指定資源」的路由
    server.send(404, "text/plain", "File NOT found!");
  });

  server.begin(); // 啟動網站伺服器
}

void loop() {
#ifdef ESP8266
  MDNS.update();
#endif
  doWiFiManager();       // 確認是否啟動Wi-Fi設置介面
  server.handleClient(); // 處理用戶端連線
}

上面的程式編譯沒問題,但是切換到AP模式,開啟Wi-Fi連線設置入口時,瀏覽器將呈現我們自訂網站伺服器的首頁,而非設置入口的頁面。

錯誤的設置入口網頁

這是因為我們自訂的server物件仍在偵聽、處理用戶端的連線請求。解決這個問題的辦法有兩種:

  • 啟動連線設置入口(或啟動AP模式)時,停止自訂的server伺服器,並於Wi-Fi設置完畢後,重新啟動server伺服器。
  • 把設置入口的伺服器設在80以外的埠號,例如:3333。如此,兩個HTTP伺服器就能同時運作。

停止與重新啟動自訂的server伺服器

停止與再次啟動server物件的程式敘述都放在doWiFiManager()函式裡面:

void doWiFiManager() {
  if (portalRunning) {   // 如果「設置入口」運行中…
        : 略
server.begin(); // 再次啟動自訂的網站伺服器
    }
  }

  // 若啟用「Wi-Fi設置入口」的接腳被按一下…
  if (digitalRead(TRIGGER_PIN) == LOW && (!portalRunning)) {
    server.stop();  // 停止自訂的網站伺服器
      : 略
  }
}

完整的程式碼請參閱第一篇貼文

設定「設置入口」網站的埠號

設置入口網站的埠號預設是80,可透過setHttpPort()方法設定其他埠號(指令說明請參閱第二篇貼文),底下程式將把AP模式的位址改成10.0.1.2(這不是必要條件),入口網站伺服器的埠號設成3333。如此,設置或修改Wi-Fi網路期間,不必停止自訂的server伺服器。

#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
// include MDNS
#ifdef ESP8266                  // 若晶片類型是ESP8266
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>   // ESP8266網站伺服器程式庫
ESP8266WebServer server(80);    // 建立網站伺服器物件
#elif defined(ESP32)            // 若晶片類型是ESP32
#include <ESPmDNS.h>
#include <WebServer.h>          // ESP32網站伺服器程式庫
WebServer server(80);           // 建立網站伺服器物件
#endif

#define AP_SSID "JarvisAP"      // 自訂的ESP裝置AP名稱
#define AP_PWD  "12345678"      // 自訂的AP密碼
#define TRIGGER_PIN 0           // 啟用「Wi-Fi設置入口」的按鍵接腳

WiFiManager wm;                 // 建立WiFi管理員物件

unsigned int  timeout   = 120; // Wi-Fi管理員的運作秒數
unsigned int  startTime = millis();
bool portalRunning      = false;
bool startAP = true; // 僅啟動網站伺服器,設成true則啟動AP和網站伺服器。

void APCallback (WiFiManager *ptWM) {
  Serial.print("啟動AP模式,AP的SSID:");
  Serial.println(ptWM->getConfigPortalSSID());
  Serial.print("IP位址:");
  Serial.println(WiFi.softAPIP());
}

void doWiFiManager() {
  if (portalRunning) {
    wm.process();
    if ((millis() - startTime) > (timeout * 1000)) {
      Serial.println("「Wi-Fi設置入口」操作逾時…");
      portalRunning = false;

      if (startAP) {
        wm.stopConfigPortal();
      } else {
        wm.stopWebPortal();
      }
    }
  }

  // 若啟用「Wi-Fi設置入口」的接腳被按一下…
  if (digitalRead(TRIGGER_PIN) == LOW && (!portalRunning)) {    
    if (startAP) {
      Serial.println("按鈕被按下了,啟動設置入口。");
      wm.setConfigPortalBlocking(false);
      wm.startConfigPortal(AP_SSID, AP_PWD);
    } else {
      Serial.println("按鈕被按下了,啟動Web入口。");
      wm.startWebPortal();
    }
    portalRunning = true;
    startTime = millis();
  }
}

void setup() {
  WiFi.mode(WIFI_STA); // Wi-Fi設置成STA模式;預設模式為STA+AP
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  delay(1000);
  pinMode(TRIGGER_PIN, INPUT_PULLUP);

  wm.setHostname("jarvis");     // 設置ESP的主機名稱
  wm.setAPStaticIPConfig(IPAddress(10,0,1,2), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
  // wm.setDebugOutput(false);  // 關閉除錯訊息
  wm.setHttpPort(3333);
  // 設置入口頁面的背景色改成Tiffany藍
  wm.setCustomHeadElement("<style>body {background-color: #E3FFFF;}</style>");
  wm.setAPCallback(APCallback);
  wm.autoConnect(AP_SSID, AP_PWD);
  // 確認晶片是否存有Wi-Fi連線資料
  if (WiFi.status() == WL_CONNECTED && wm.getWiFiIsSaved()) {
    Serial.println("\n晶片存有Wi-Fi連線資料!");
  } else {
    Serial.println("\n晶片沒有Wi-Fi連線資料…");
  }
  // 設定自訂的網站伺服器
  server.on("/", []() {      // 處理”/”路徑的路由
    server.send(200, "text/html; charset=utf-8", "人生最大的風險,<br>就是不願意冒險。");
  });
  server.onNotFound([]() { // 處理「找不到指定資源」的路由
    server.send(404, "text/plain", "File NOT found!");
  });

  server.begin();   // 啟動網站伺服器
}

void loop() {
#ifdef ESP8266
  MDNS.update();
#endif
  doWiFiManager();       // 確認是否啟動Wi-Fi設置介面
  server.handleClient(); // 處理用戶端連線
}

編譯並上傳程式碼到ESP8266或ESP32開發板,按一下腳0的開關,即可啟動AP模式連線,也能順利連接「設置入口」頁面。

Posts created 469

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top