You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

安卓无需断开本地局域网向ESP32传输WiFi SSID及密码的实现方案

方案选型结论

几个你提到的方案适用性如下:

  • WiFi Direct:不推荐。ESP32的WiFi P2P模式兼容性差,不同厂商安卓ROM对WiFi Direct的权限限制差异大,配网完成后切换STA工作模式的逻辑冗余,设备发现成功率低。
  • 常规AutoConnect库方案:不符合需求。默认实现是让ESP32开启独立软AP,手机必须手动连接该AP才能打开配网页,会直接断开手机当前已连接的局域网。
  • ESP-NOW + AP/STA共存配网:完全匹配需求。利用ESP32双模并发能力+ESP-NOW二层无连接传输特性,安卓手机全程不需要切换WiFi连接,不需要断开当前局域网就能完成配网,兼容性最好。
  • BLE配网:备选方案。通过蓝牙通道传输配网信息,同样不需要断开WiFi,缺点是安卓端需要适配多版本蓝牙权限,部分低价位机型蓝牙广播兼容性一般。
ESP-NOW配网实现逻辑

核心原理是ESP-NOW是Espressif定义的二层短包传输协议,同无线信道下不需要设备完成AP关联就能互相收发数据,完全不影响手机当前的WiFi连接:

  1. ESP32上电初始状态
    • 设置为WIFI_AP_STA共存模式,开启无密码软AP,SSID固定为DHT11-Sensor-XXXX格式,XXXX是设备MAC地址后四位,方便识别,软AP固定工作在1信道
    • 启动ESP-NOW监听,等待接收配网广播包,同时持续扫描周边WiFi
  2. 安卓端操作流程(全程不断开当前WiFi)
    • 申请必要的WiFi状态权限后,调用系统WiFi扫描接口,识别SSID匹配的ESP32设备,确认其工作信道
    • 构造固定格式的配网数据包,包含目标局域网SSID、密码、校验位,通过ESP-NOW协议向对应信道广播发送,整个过程不需要连接ESP32的软AP
    • 等待ESP32返回配网结果回执
  3. 配网完成切换
    • ESP32收到合法配网包后先返回确认回执,再尝试用收到的账号密码连接目标局域网
    • 连接成功后自动关闭软AP、注销ESP-NOW监听,进入正常工作模式定时读取DHT11数据
    • 连接失败则回到监听状态,返回失败回执等待重传
ESP32示例代码(Arduino框架)

依赖:提前安装Arduino ESP32 2.0+版本板包、DHT传感器驱动库

#include <esp_now.h>
#include <WiFi.h>
#include <DHT.h>

// 硬件配置
#define DHT_DATA_PIN 4
#define DHT_MODEL DHT11
const char* AP_PREFIX = "DHT11-Sensor-";
const uint8_t BROADCAST_ADDR[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// 配网数据结构,安卓端必须和该结构内存对齐
typedef struct {
  char wifi_ssid[32];
  char wifi_pass[64];
  uint8_t checksum;
} WifiConfigMsg;

WifiConfigMsg recv_config;
DHT dht(DHT_DATA_PIN, DHT_MODEL);
bool has_config = false;

uint8_t calc_checksum(uint8_t* data, size_t len) {
  uint8_t res = 0;
  for(size_t i=0; i<len; i++) res += data[i];
  return res;
}

void espnow_recv_cb(const uint8_t* mac_addr, const uint8_t* data, int data_len) {
  if(data_len != sizeof(WifiConfigMsg)) return;
  memcpy(&recv_config, data, sizeof(WifiConfigMsg));
  // 校验数据完整性
  uint8_t calc_sum = calc_checksum((uint8_t*)&recv_config, sizeof(WifiConfigMsg)-1);
  if(calc_sum != recv_config.checksum) return;
  has_config = true;
}

void setup() {
  Serial.begin(115200);
  dht.begin();

  // 初始化AP+STA双模
  WiFi.mode(WIFI_AP_STA);
  uint8_t mac[6];
  WiFi.macAddress(mac);
  char ap_ssid[32];
  snprintf(ap_ssid, sizeof(ap_ssid), "%s%02X%02X", AP_PREFIX, mac[4], mac[5]);
  WiFi.softAP(ap_ssid, NULL, 1, 0, 1); // 信道1,最大1连接,不影响性能

  // 初始化ESP-NOW
  if(esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW init error, restart");
    ESP.restart();
  }
  esp_now_register_recv_cb(espnow_recv_cb);
}

void loop() {
  if(has_config) {
    WiFi.begin(recv_config.wifi_ssid, recv_config.wifi_pass);
    uint8_t retry = 0;
    while(WiFi.status() != WL_CONNECTED && retry < 20) {
      delay(500);
      retry++;
    }

    if(WiFi.status() == WL_CONNECTED) {
      // 配网成功,关闭配网相关服务
      esp_now_deinit();
      WiFi.softAPdisconnect(true);
      Serial.printf("WiFi connected, local IP: %s\n", WiFi.localIP().toString().c_str());
      // 进入正常工作循环
      while(1) {
        float temp = dht.readTemperature();
        float humi = dht.readHumidity();
        if(!isnan(temp) && !isnan(humi)) {
          Serial.printf("Temperature: %.1f℃, Humidity: %.1f%%\n", temp, humi);
          // 此处添加局域网数据上报逻辑
        }
        delay(2000);
      }
    } else {
      // 配网失败,重置状态等待重传
      has_config = false;
      WiFi.disconnect();
    }
  }
  delay(100);
}
安卓端实现注意事项
  • 权限要求:安卓11及以下申请ACCESS_FINE_LOCATION权限用于WiFi扫描,安卓12及以上补充申请NEARBY_WIFI_DEVICES权限,不需要ROOT、不需要位置权限常开
  • 发送ESP-NOW包时需要先获取WiFi多播锁,避免系统过滤广播包,数据包结构必须和ESP32端定义的结构体完全对齐,避免内存错位导致解析失败
  • 不需要手动切换WiFi连接,扫描到ESP32的软AP后仅需要读取其信道参数,不需要发起关联请求

内容的提问来源于stack exchange,提问作者Elias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 05:01:10