ESP32 同時當基地台又能上網!
水井三寶智慧互動展覽系統 AP+STA 共存實測
ESP32 Arduino SoftAP STA Edge Web IoT USR
經過實際測試,答案是:可以。 本次成功讓 ESP32 的 SoftAP 與 STA 同時運作,而且 AP 端的手機控制與 STA 端的 Internet 連線可以共存。
一、為什麼水井三寶故事機需要 AP+STA?
一般 ESP32 IoT 專題常見的做法,是讓 ESP32 連接既有 Wi-Fi,也就是 STA(Station)模式。 但「水井三寶智慧互動展覽系統」的使用情境不同。
展覽現場可能有大量參觀者,而且展場 Internet 並不一定穩定。因此,我們希望故事機即使沒有 Internet, 工作人員仍然可以拿手機直接連上 ESP32,進入內嵌控制網站進行播放、診斷與設備管理。
另一方面,如果展場具有 Internet,ESP32 又應該能將匿名互動事件傳送到遠端 Django 平台, 形成長期的展覽數據。
│
│ Wi-Fi
▼
【ESP32 SoftAP】
Shuijing-Treasures
192.168.4.1
│
├──── Edge Web 現場控制
│
└──── ESP32 同時使用 STA
│
▼
【手機熱點/展場 Wi-Fi】
│
▼
Internet
│
▼
【Django 雲端平台】
二、AP 與 STA 分別做什麼?
| 模式 | 用途 | 水井三寶應用 |
|---|---|---|
| AP | ESP32 自己建立 Wi-Fi | 手機直接連入故事機 |
| SoftAP IP | ESP32 本地控制網址 | 192.168.4.1 |
| STA | ESP32 連接外部 Wi-Fi | 取得 Internet |
| Internet | 連接遠端伺服器 | Django 匿名事件平台 |
三、這次實測成功
本次使用 ESP32 實際測試 AP+STA 共存。 ESP32 一方面建立自己的 Wi-Fi:
SSID:Shuijing-Treasures Local control:http://192.168.4.1
另一方面,再透過 STA 連接名為 ChiYuan 的外部 Wi-Fi。 實際取得:
STA CONNECTED STA SSID : ChiYuan STA IP : 192.168.1.119 RSSI : -21 dBm ============================== SYSTEM READY ============================== Local control: http://192.168.4.1 Internet: YES
ESP32 不需要在「本地控制」與「Internet」之間二選一。
它可以同時提供 192.168.4.1 Edge Web, 又透過另一個 Wi-Fi 介面連上 Internet。
四、連線過程
程式的核心概念其實很簡單:先建立 SoftAP,再使用
WiFi.begin() 建立 STA 連線。
STEP 1|ESP32 建立 SoftAP
if (!WiFi.softAP(AP_SSID, AP_PASSWORD)) {
Serial.println("SoftAP FAILED");
while (1) {
delay(1000);
}
}
Serial.println("SoftAP OK");
Serial.print("AP IP : ");
Serial.println(WiFi.softAPIP());
成功後,ESP32 本身就是一個 Wi-Fi 基地台。 手機可以搜尋到:
Shuijing-Treasures
連線後即可進入:
http://192.168.4.1
STEP 2|ESP32 再連接 Internet Wi-Fi
WiFi.begin(STA_SSID, STA_PASSWORD);
這時 ESP32 又以 STA 身分連接外部 AP。 程式最多等待 15 秒:
unsigned long start = millis();
while (
WiFi.status() != WL_CONNECTED &&
millis() - start < 15000
) {
Serial.print(".");
delay(500);
}
STEP 3|確認兩個 IP 同時存在
這是理解 AP+STA 最重要的地方。 ESP32 此時具有兩個不同用途的 IP。
| 介面 | 本次實測 IP | 功能 |
|---|---|---|
| SoftAP | 192.168.4.1 | 手機連 ESP32 |
| STA | 192.168.1.119 | ESP32 連 Internet |
五、還能知道有幾台手機連進 ESP32
程式使用:
WiFi.softAPgetStationNum()
取得目前連接 ESP32 AP 的裝置數。 本次測試畫面持續出現:
AP Clients = 1
代表測試當下確實有一台裝置連著 Shuijing-Treasures。
六、RSSI 也能成為展覽維護資訊
程式每五秒輸出 STA 狀態:
AP Clients = 1 | STA = ONLINE | IP = 192.168.1.119 | RSSI = -28 AP Clients = 1 | STA = ONLINE | IP = 192.168.1.119 | RSSI = -21 AP Clients = 1 | STA = ONLINE | IP = 192.168.1.119 | RSSI = -29
這些資訊未來可以直接整合進水井三寶 Edge Web 的「設備診斷」頁面, 讓工作人員不必接電腦,就可以從手機知道:
- AP 是否正常
- 目前有多少裝置連線
- STA 是否 ONLINE
- STA IP
- Wi-Fi RSSI
- Internet 是否可用
七、完整 Arduino 測試程式
以下是本次 AP+STA 共存實際測試使用的 Arduino 程式。 正式使用時只需要修改 STA 的 Wi-Fi 名稱與密碼。
#include <Arduino.h>
#include <WiFi.h>
#include <NetworkClient.h>
#include <WiFiAP.h>
// ===============================
// ESP32 AP + Internet STA TEST
// ===============================
// ESP32 本地 AP
const char *AP_SSID = "Shuijing-Treasures";
const char *AP_PASSWORD = "12345678";
// 可上網的 Wi-Fi
// 先用手機熱點測試最容易排除展場網路問題
const char *STA_SSID = "您的手機熱點名稱";
const char *STA_PASSWORD = "您的手機熱點密碼";
NetworkServer server(80);
void setup() {
Serial.begin(115200);
delay(1500);
Serial.println();
Serial.println("==============================");
Serial.println("SHUIJING AP + STA TEST");
Serial.println("==============================");
// --------------------------------
// STEP 1
// 建立 SoftAP
// --------------------------------
Serial.println();
Serial.println("[1] Starting SoftAP...");
if (!WiFi.softAP(AP_SSID, AP_PASSWORD)) {
Serial.println("SoftAP FAILED");
while (1) {
delay(1000);
}
}
Serial.println("SoftAP OK");
Serial.print("AP SSID : ");
Serial.println(AP_SSID);
Serial.print("AP IP : ");
Serial.println(WiFi.softAPIP());
// --------------------------------
// STEP 2
// 建立 STA Internet
// --------------------------------
Serial.println();
Serial.println("[2] Starting STA...");
WiFi.begin(STA_SSID, STA_PASSWORD);
unsigned long start = millis();
while (
WiFi.status() != WL_CONNECTED &&
millis() - start < 15000
) {
Serial.print(".");
delay(500);
}
Serial.println();
// --------------------------------
// STEP 3
// 檢查 STA
// --------------------------------
if (WiFi.status() == WL_CONNECTED) {
Serial.println("STA CONNECTED");
Serial.print("STA SSID : ");
Serial.println(WiFi.SSID());
Serial.print("STA IP : ");
Serial.println(WiFi.localIP());
Serial.print("RSSI : ");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
} else {
Serial.println("STA NOT CONNECTED");
Serial.println("Local AP should still work.");
}
// --------------------------------
// STEP 4
// 啟動本地 Web Server
// --------------------------------
server.begin();
Serial.println();
Serial.println("==============================");
Serial.println("SYSTEM READY");
Serial.println("==============================");
Serial.print("Local control: http://");
Serial.println(WiFi.softAPIP());
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Internet: YES");
} else {
Serial.println("Internet: NO");
}
}
void loop() {
// ===============================
// 本地 AP Web Server
// ===============================
NetworkClient client = server.accept();
if (client) {
String currentLine = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n') {
if (currentLine.length() == 0) {
client.println("HTTP/1.1 200 OK");
client.println(
"Content-Type: text/html; charset=utf-8"
);
client.println("Connection: close");
client.println();
client.println(
"<!DOCTYPE html>"
"<html>"
"<head>"
"<meta charset='UTF-8'>"
"<meta name='viewport' "
"content='width=device-width,initial-scale=1'>"
"</head>"
"<body>"
);
client.println(
"<h1>水井三寶 AP + STA 測試</h1>"
);
client.print("<p>AP IP:");
client.print(WiFi.softAPIP());
client.println("</p>");
client.print("<p>STA:");
if (WiFi.status() == WL_CONNECTED) {
client.println("CONNECTED</p>");
client.print("<p>Internet IP:");
client.print(WiFi.localIP());
client.println("</p>");
client.print("<p>RSSI:");
client.print(WiFi.RSSI());
client.println(" dBm</p>");
} else {
client.println("OFFLINE</p>");
}
client.println("</body></html>");
break;
} else {
currentLine = "";
}
} else if (c != '\r') {
currentLine += c;
}
}
}
client.stop();
}
// ===============================
// STA 斷線診斷
// ===============================
static unsigned long lastPrint = 0;
if (millis() - lastPrint > 5000) {
lastPrint = millis();
Serial.print("AP Clients = ");
Serial.print(WiFi.softAPgetStationNum());
Serial.print(" | STA = ");
if (WiFi.status() == WL_CONNECTED) {
Serial.print("ONLINE");
Serial.print(" | IP = ");
Serial.print(WiFi.localIP());
Serial.print(" | RSSI = ");
Serial.println(WiFi.RSSI());
} else {
Serial.println("OFFLINE");
}
}
}
八、為什麼這次測試對「水井三寶」很重要?
這不只是一個 ESP32 Wi-Fi 技術測試,而是決定「水井三寶智慧互動展覽系統」 能不能真正進入展覽現場的一個重要基礎。
ESP32+ToF+三按鈕+JQ6500+RGB, 負責故事播放與現場互動。
ESP32 提供 192.168.4.1, 即使 Internet 中斷仍可現場控制。
ESP32 透過 STA 與 Internet, 將匿名互動事件送往遠端平台。
白馬、烏龜、姻緣花、三寶故事與創作者資訊, 提供更完整的數位延伸閱讀。
九、最重要的展覽設計原則:Internet 不是故事機的開關
因此,水井三寶智慧互動展覽系統採取的是 Edge First 的思考方式。
ToF、三個實體按鈕、JQ6500 故事播放、RGB 燈光與 192.168.4.1 本地控制都應該在 ESP32 本機完成。
STA 與 Internet 則是「加值能力」,主要負責匿名事件同步與遠端資料分析。
未來即使展場 Wi-Fi 暫時中斷:
JQ6500 → 繼續播放 三按鈕 → 繼續操作 ToF → 繼續偵測 RGB → 繼續互動 192.168.4.1 → 繼續控制 Internet → 暫時離線 Django Event → 暫存,恢復後補傳
十、下一步:從「會上網」進入「真正的四層系統」
本次測試已經完成一個重要的技術驗證: ESP32 SoftAP 與 Internet STA 可以穩定共存。
下一階段就可以把這項成果正式整合進「水井三寶智慧互動展覽系統」:
水井三寶作品
│
▼
ESP32 智慧互動層
ToF+Button+JQ6500+WS2812
│
▼
Edge Web
192.168.4.1
│
├──────── 現場手機控制
│
▼
STA / Internet
│
▼
Django
匿名事件資料庫
│
▼
展覽 Dashboard
當地方工藝遇上 ESP32、Edge Web 與 Django, 科技不再只是放在作品旁邊的設備, 而是開始成為地方故事與參觀者之間的互動媒介。
白馬行土地、烏龜守清水、姻緣花牽人情;
三寶同行,水井共生。
沒有留言:
張貼留言