一、為什麼需要 Wi-Fi AP 模式?
一般 ESP32 範例通常直接把 Wi-Fi 帳密寫死在程式中:
const char* ssid = "MyHome";
const char* password = "12345678";
這種寫法雖然簡單,但每換一個 Wi-Fi,就要重新修改程式並燒錄。對智慧養殖、智慧農業或社區 IoT 設備而言,現場維護並不方便。
二、完整流程
三、ESP32 建立 AP 熱點
當 ESP32 找不到 Wi-Fi 設定,或連線逾時,就建立自己的 AP:
String apName = "Shuijing-Setup-A1B2C3";
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(apName.c_str(), "shuijing123");
手機搜尋 Wi-Fi 時,就會看到:
Shuijing-Setup-A1B2C3
四、建立手機設定頁
ESP32 可透過內建 WebServer 建立設定頁。手機連上 AP 後,在瀏覽器輸入:
http://192.168.4.1
設定頁包含 Wi-Fi SSID、Wi-Fi 密碼與「儲存並重新連線」按鈕。
WebServer configServer(80);
configServer.on("/", HTTP_GET, handleConfigRoot);
configServer.begin();
五、手機送出設定
實際測試時,部分手機的 Captive Portal 對 POST 相容性不佳,因此後來改用 GET,並指定完整網址:
<form method="GET" action="http://192.168.4.1/save">
ESP32 端接受所有 HTTP 方法:
configServer.on("/save", HTTP_ANY, handleConfigSave);
六、NVS 是什麼?
NVS 是 Non-Volatile Storage,中文可理解為「非揮發性儲存」。它使用 ESP32 內建 Flash,資料在斷電與重新啟動後仍會保留。
| 項目 | 說明 |
|---|---|
| 函式庫 | Preferences |
| 儲存位置 | ESP32 內建 Flash 的 NVS 分區 |
| 斷電後 | 資料仍保留 |
| 適合資料 | SSID、密碼、裝置編號、API 參數 |
七、把 SSID 與密碼寫入 NVS
#include <Preferences.h>
Preferences preferences;
bool saveWiFiCredentials(const String& ssid, const String& password) {
preferences.begin("wifi-config", false);
size_t ssidResult = preferences.putString("ssid", ssid);
size_t passwordResult = preferences.putString("password", password);
preferences.end();
return ssidResult > 0;
}
這段程式開啟名為 wifi-config 的 namespace,並以 ssid 與 password 作為 Key。
八、寫入後立即回讀驗證
本次開發中曾遇到重新啟動後顯示「尚未儲存 SSID」。因此加入寫入後立即回讀驗證:
String verifySsid = preferences.getString("ssid", "");
String verifyPassword = preferences.getString("password", "");
bool ssidOK = verifySsid == ssid;
bool passwordOK = verifyPassword == password;
九、顯示設定完成並重新啟動
設定成功後,手機顯示完成頁;ESP32 再排程重新啟動:
restartScheduled = true;
restartAt = millis() + 5000;
在 loop() 中檢查:
if (restartScheduled && millis() - restartAt >= 0) {
configServer.stop();
dnsServer.stop();
WiFi.softAPdisconnect(true);
delay(500);
ESP.restart();
}
十、重新開機後讀取 NVS
這一步非常重要。即使資料已經寫入 Flash,重新啟動後仍必須主動讀回:
void loadWiFiCredentials() {
preferences.begin("wifi-config", true);
wifiSsid = preferences.getString("ssid", "");
wifiPassword = preferences.getString("password", "");
preferences.end();
}
正確的 setup 流程是:
十一、自動連線 Wi-Fi
bool connectWiFi() {
if (wifiSsid.length() == 0) return false;
WiFi.mode(WIFI_STA);
WiFi.begin(wifiSsid.c_str(), wifiPassword.c_str());
unsigned long startedAt = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startedAt < 20000) {
delay(500);
}
return WiFi.status() == WL_CONNECTED;
}
十二、序列監控應看到什麼?
========== NVS 寫入結果 ==========
[NVS] SSID 寫入 bytes:10
[NVS] 密碼寫入 bytes:9
[NVS] SSID 回讀:成功
[NVS] 密碼回讀:成功
=================================
[AP] 設定已寫入,5 秒後重新啟動
========== NVS Wi-Fi 設定 ==========
[NVS] SSID key:存在
[NVS] Password key:存在
[WiFi] 已儲存 SSID:Home_WiFi
===================================
[WiFi] 嘗試連線:Home_WiFi
[WiFi] 連線成功
[WiFi] IP:192.168.1.120
十三、從 Wi-Fi 到 Django Dashboard
完成 AP 模式與 NVS 設定後,ESP32 就不再綁定單一網路。設備移到新的魚塭或養殖戶,只要用手機重新設定 Wi-Fi,就能繼續上傳資料。
十四、本篇重點
- ESP32 無法連線時,可自動啟動 Soft-AP。
- 手機可透過 192.168.4.1 開啟設定頁。
- SSID 與密碼使用 Preferences 寫入 NVS Flash。
- 寫入後應立即回讀驗證。
- 重新啟動後必須再次讀取 NVS。
- 成功連線後即可恢復 Django REST API 上傳。
結語
將 Wi-Fi 帳密寫死在程式中,適合實驗室測試,但不適合實際場域部署。透過 AP 模式、WebServer、DNSServer 與 Preferences,ESP32 可以在沒有螢幕與鍵盤的情況下,由手機完成 Wi-Fi 設定,並在重新啟動後自動連線。這讓智慧養殖系統從開發板實驗,進一步成為真正可交付、可維護的 IoT 設備。
