佈署物聯網裝置時,經常需要設定Wi-Fi連線到本地的無線路由器(分享器)。例如,假設你購買了一台Wi-Fi攝影監視器,必須先將它連到家裡的Wi-Fi分享器,才能透過網路遠端監看。
Tzapu寫了一個WiFiManager(WiFi管理員),從2.x版開始同時支援ESP8266和ESP32開發板(以下合稱ESP開發板),提供ESP開發板一個方便實用的設置Wi-Fi網路連線的操作介面。底下先介紹它的操作方式和介面外觀。
本文的範例採WEMOS D1 mini開發板,筆者也用ESP32開發板測試過,功能一樣。請在開發板的GPIO 0(D1 mini板的D3腳)連接一個開關,另一腳接地,當作「啟用WiFi設置模式」的按鍵開關。
WiFi Manager的無線網路設置介面
燒錄WiFi管理員程式的ESP開發板初次開機時,尚未連到本地無線分享器,它會自動切換到AP模式(無線接入點),其SSID識別名稱預設為“ESP”+MAC位址,筆者將它設成“JarvisAP”。
先用手機或電腦的Wi-Fi連接到ESP開發板“JarvisAP”:
然後用瀏覽器開啟IP位址“192.168.4.1”,ESP開發板將傳回如下的設置畫面,網頁底部顯示“尚未設定AP”。
點擊「設置WiFi」,ESP開發板將掃描並列舉周遭的Wi-Fi分享器:
點擊Wi-Fi分享器的識別名稱、輸入密碼、按下「儲存」,ESP開發板將傳回底下的訊息頁面:
ESP開發板將關閉AP模式、切換到STA模式並連接指定的Wi-Fi分享器。此後,手機或電腦便能透過相同的Wi-Fi分享器連接ESP開發板。
日後若需要修改ESP板的Wi-Fi分享器的設定,或者要觀看它從Wi-Fi分享器取得的IP位址,請先按一下接在腳0的按鍵開關,ESP將再次啟動AP模式,讓人透過預設的192.168.4.1位址連線到它的設置頁面。
從底下的畫面可看到它已經連線到Wi-Fi分享器並取得IP位址:
點擊「設置WiFi」可重新設定Wi-Fi分享器連線;點擊「資訊」可看到ESP開發板的韌體版本、晶片ID、運作時脈、快閃記憶體容量、主記憶體的可用空間(heap,堆積)大小…等資訊,若按下其中的「清除WiFi設置」,現有的Wi-Fi連線資料將被清空,需要重新指定Wi-Fi分享器。
替ESP開發板設定連線之後,以本文的範例來說,用瀏覽器開啟它的首頁,將能看到如下的訊息,代表ESP開發板的網站伺服器如預期運作。
安裝WiFiManager程式庫
選擇Arduino IDE主功能表的「草稿碼→匯入程式庫→管理程式庫」指令,搜尋關鍵字“wifimanager”,即可找到tzapu, tablaronix開發的程式庫。請按下「安裝」鈕安裝它:
筆者撰寫本文時,WiFiManager的最新版本是2.0.3-alpha測試版,因此可能有些功能尚未完善。
WiFiManager程式庫1.6版的Wi-Fi設置網頁的HTML原始碼,定義在WiFiManager.h標頭檔的這些字元常數:
const char HTTP_HEADER[] PROGMEM const char HTTP_STYLE[] PROGMEM const char HTTP_SCRIPT[] PROGMEM const char HTTP_HEADER_END[] PROGMEM const char HTTP_PORTAL_OPTIONS[] PROGMEM const char HTTP_ITEM[] PROGMEM const char HTTP_FORM_START[] PROGMEM const char HTTP_FORM_PARAM[] PROGMEM const char HTTP_FORM_END[] PROGMEM const char HTTP_SCAN_LINK[] PROGMEM const char HTTP_SAVED[] PROGMEM const char HTTP_END[] PROGMEM
2.0版則是把Wi-Fi設置網頁的HTML碼單獨存放在“strings_en.h”標頭檔。筆者已經把Wi-Fi設置頁面的文字翻譯成中文,有正體(strings_tw.h檔)和簡體(strings_cn.h檔)兩個版本,請按此連結下載。
除了文字和用詞不同,正體版網頁字體預設成“微軟正黑體”,”黑體-繁”,sans-serif;而簡體版網頁字體則默認為“微软雅黑”,”黑体-简”,sans-serif。
下載中文的設置頁面標頭檔,將它解壓縮存入“WiFi管理員”程式庫的所在路徑裡面(亦即,“文件/Arduino/libraries/WiFiManager”):
使用文字或程式編輯器開啟此資料夾裡的WiFiManager.h標頭檔,搜尋”strings_en.h“,找到這一行敘述:
#include "strings_en.h" // 英文設置介面檔
將它改成引用正體或簡體譯本:
#include "strings_tw.h" // 正體中文版Wi-Fi設置介面
編譯與測試Wi-Fi網路設置功能程式碼
這個程式修改自“WiFi管理員”提供的“OnDemandNonBlocking”範例:
#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 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.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(); // 處理用戶端連線 } void doWiFiManager() { if (portalRunning) { wm.process(); if ((millis() - startTime) > (timeout * 1000)) { Serial.println("「Wi-Fi設置入口」操作逾時…"); portalRunning = false; if (startAP) { wm.stopConfigPortal(); } else { wm.stopWebPortal(); } server.begin(); // 再次啟動我們的網站伺服器 } } // 若啟用「Wi-Fi設置入口」的接腳被按一下… if (digitalRead(TRIGGER_PIN) == LOW && (!portalRunning)) { server.stop(); // 停止我們自訂的網站伺服器程式 if (startAP) { Serial.println("按鈕被按下了,啟動設置入口。"); wm.setConfigPortalBlocking(false); wm.startConfigPortal(AP_SSID, AP_PWD); } else { Serial.println("按鈕被按下了,啟動Web入口。"); wm.startWebPortal(); } portalRunning = true; startTime = millis(); } }
編譯並上傳程式碼到ESP8266或ESP32開發板,並於腳0連接一個開關,即可依照本文開頭的說明測試連線。WiFi管理員的程式碼解說,參閱下一篇文章。
昨天有留言簿不能編譯的問題
後來我把wifimanager版本改成跟你一樣的2.0.3alpha版本後就能正常執行了
謝謝
感謝告知!
D:\C\Documents\Arduino\libraries\WiFiManager/strings_en.h:358:7: error: ‘wifi_country_t’ does not name a type
const wifi_country_t WM_COUNTRY_US{“US”,1,11,WIFI_COUNTRY_POLICY_AUTO};
可以請問這類型的錯誤是什麼嗎?
那個錯誤訊息代表Wi-Fi設置成美國地區時出錯。
請問你用什麼開發板?我使用ESP32,開發環境是1.0.6版,測試編譯最新的WiFiManager程式沒問題,但是中文翻譯檔不相容。
老師您好:
謝謝分享這篇教學文,這樣總算可以不把密碼寫死進程式裡,另外想問esp32一開始是ap模式,供手機等連入無網路的區域熱點(就是他的頁面),輸入其他ap接入點,一旦連上則轉成sta模式,這樣理解有誤嗎?
因為wifimanager下的範例basic,這邊WiFi.mode是預設是sta模式
對,STA模式才能連線到IP分享器。
那個…我想問一下,為什麼jarvisap的那個wifi需要密碼?
把WiFiManager.h裡的strings_en.h改成strings_tw.h會出現
開發板 NodeMCU 1.0 (ESP-12E Module) 編譯時出錯
這要怎麼辦?我好想用中文介面