准备入手ESP网关项目了,手头有一块esp8266的开发小板子,就先从esp8266开始入手。白天搞定了ESP8266 的UDP配网编码和小程序端的控制编码。就一个功能模块给ESP8266配置WIFI网络。这是必须的入门操作,因为WIFI 的SSID和密码不能真的写入到代码中。
网络配置有很多种方式,我选择了SoftAP配网,虽然配置有点繁琐,但这是一种很可靠的配网方案,兼容性极高,不依赖手机硬件的特殊协议。以前做过HTTP配网,这是2025年时做的,到现在已经忘的差不多了。现在捡起来再回忆一下。
准确来说,这不应该算是一个项目,但因为它具有通用性和实用性。我决定把它记录下来,可以方便地应用到我的其它项目中。
Soft配网原理
- 初始化模式:ESP8266 启动后进入 WIFI_AP_STA 模式。它会开启一个无密码(或已知密码)的热点(AP),并运行一个轻量级的 Web 服务器(HTTP Server)。
- 通道建立:手机通过小程序或系统设置连接到该热点。此时手机与 ESP8266 处于同一个局域网内。
- 数据交互:小程序通过 HTTP Post 请求将目标 WiFi 的 SSID 和 Password 发送给 ESP8266 的固定接口(如 /config)。
- 校验与切换:ESP8266 收到参数后,尝试作为客户端(STA)连接路由器。如果连接成功,则关闭 AP 热点,保存参数到 Flash;如果失败,则返回并重置到AP状态。
ESP8266端核心代码(Arduino IDE)和小程序端代码
在Arduino IDE打开项目后,需要安装ESP8266 WebServer库。这个库提供了Web服务,可以接收其它HTTP客户端的连接。
它的核心是实现了一个非常简单的Web服务,它监听/config接口并能够接收WIFI信息,以及接收之后可以本地存储,实现动态配置的功能。
下面是Arduino端的代码片段:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
// 定义AP热点的名称
const char* ap_ssid = "ESP8266_Config_Device";
ESP8266WebServer server(80);
void handleConfig() {
// 处理SSID和密码逻辑
}
void setup() {
// 设置为AP+STA模式
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(ap_ssid);
// 注册接口
server.on("/config", HTTP_POST, handleConfig);
server.begin();
}
void loop() {
server.handleClient();
if (WiFi.status() == WL_CONNECTED) {
// 如果连接成功,可以根据需要在这里处理业务逻辑
}
}
完整代码可以从https://91demo.top/tools/下载。小程序端则充当了HTTP客户端,它用来作为输入WIFI信息的终端。这个界面非常简单,一个WiFi信息提交表单,包含了SSID信息和密码信息,以及一个提交按钮。
下面是小程序端提交WiFi配置信息的核心代码,需要注意的是,在操作的时候,需要将手机先连接到ESP8266热点,然后让用户填写的WIFI账号和密码,并点击提交按钮,调用JS通过HTTP接口传送给ESP8266 Web服务。
sendConfig(e) {
const that = this;
let obj = e.detail.value;
wx.showLoading({ title: '配置中...', mask: true });
const url = "http://192.168.4.1/config";
const requestTask = wx.request({
url: url,
method: "POST",
timeout: 10000, // 10秒超时
header: {
'content-type': 'application/x-www-form-urlencoded',
},
data: {
ssid: obj.ssid,
pass: obj.pass,
},
success: (res) => {
wx.hideLoading();
// 兼容处理:只要服务器返回了200,基本代表ESP8266已收到指令
if (res.statusCode === 200) {
that.setData({ status: "指令下发成功,观察设备状态" });
wx.showModal({
title: '配置已发送',
content: '设备正在尝试连接路由器,请观察设备指示灯或稍后切换网络查看。',
showCancel: false
});
}
},
fail: (err) => {
wx.hideLoading();
}
});
}
小程序在发送 POST 请求时,URL 应设为 192.168.4.1(这是 ESP8266 默认的 AP 地址),如果需要其它地址,需要ESP8266芯片代码和小程序端代码同时修改。
这次我选择了ESP SmartConfig和UDP配网,我对HTTP最熟悉,想尝试一下底层UDP协议。SmartConfig非常简单,esp8266直接支持ESPSmart 和微信的AirKiss。
void startAPConfig()
{
WiFi.mode(WIFI_AP_STA); // 混合模式
// 1. 开启官方 SmartConfig (兼容 EspTouch & AirKiss)
WiFi.beginSmartConfig();
Serial.println(F("配网模块启动:等待 EspTouch/AirKiss ..."));
}
上面的代码就开启了SmartConfig,晚上拿小板子测试时,发现了这几个问题:
1,腾讯连连在登录,获取手机号等操作后,不能也没有入口连接我的小板子。然后我选择ESP APP,从手机应用商店也找不到,最后搜索到ESP Config小程序,只有一个蓝牙选项。没办法,只有使用UDP配网了。本以为这样可以兼容很多客户端呢。
UDP的逻辑和HTTP配网差不多,都是SoftAP配网,除了这个,还有蓝牙配网,这是目前的主流模式,但是ESP8266不支持蓝牙。
这次优化了一下配网体验,启动ESP 8266后,小程序可以自动搜索到附近的ESP 8266热点,当用户点击热点后会先自动获取HOME网络的SSID,并要求用户输入密码,用户提交后自动连接ESP 8266热点,并通过UDP发送WIFI配置,当ESP 8266收到后,会回复小程序收到状态,小程序界面会进行显示,并开始监听ESP 8266回复连接成功的消息。
这是ESP8266 启动AP热点的代码片段:
void startAPConfig()
{
setLedFast();
isConfigured = false;
WiFi.mode(WIFI_AP); // AP模式
WiFi.softAP("ESP_91DEMO_NODE", "12345678"); // 开启热点
// 2. 开启私有 UDP 监听
udp.begin(9194); // 2026年五一劳动节编制
Serial.println(F("配网模块启动:等待私有UDP包..."));
}
它会启动AP热点,并监听9194的UDP端口,当收到消息后,会进行处理消息。
void handlePrivateUdp()
{
char packetBuffer[256]; // 稍微大一点
int len = udp.read(packetBuffer, 255);
if (len <= 0)
return;
packetBuffer[len] = 0;
// 1. 快速解析 JSON
JsonDocument doc;
DeserializationError error = deserializeJson(doc, packetBuffer);
// 检查解析是否成功,并确保 s 和 p 存在且为字符串
if (error || !doc["s"].is<const char *>() || !doc["p"].is<const char *>())
{
Serial.println(F("JSON 解析失败或格式错误(缺失字符串字段)"));
return;
}
const char *ssid = doc["s"];
const char *pass = doc["p"];
Serial.printf("收到私有协议配网: %s / %s\n", ssid, pass);
// --- 关键步骤:在断开 AP 前立即回包 ---
udp.beginPacket(udp.remoteIP(), udp.remotePort()); // 回复给当前发送包的手机
udp.print("{\"status\":\"received\"}");
udp.endPacket();
// 给系统一点点时间把包发出去(20ms足够)
delay(20);
// 2. 切换灯光为慢闪:表示“正在连接中”
setLedSlow();
// 3. 非阻塞发起连接
WiFi.softAPdisconnect(true); // 关闭 AP 热点
WiFi.mode(WIFI_STA); // 明确切回 STA 模式
WiFi.begin(ssid, pass);
// 4. 重要:设置一个标志位或截止时间,让 loop 处理后续
isConnecting = true;
startAttemptTime = millis();
// 函数执行完立即退出,不在这里 while 循环
}
这样处理之后,ESP会尝试WIFI连接,当连接成功后,会在Loop循环中处理收尾逻辑,比如告知小程序端它已经连接成功,并返回客户端IP和MAC地址,这样方便后续业务逻辑。
if (WiFi.status() == WL_CONNECTED)
{
isConnecting = false;
isConfigured = true;
setLedOn(); // 连接成功,灯常亮
startFinishNotification(); // 开始发送通知
}
else if (millis() - startAttemptTime > 15000)
{
// 15秒超时
isConnecting = false;
setLedFast(); // 变回快闪,暗示“回到配网模式”
startAPConfig();
Serial.println(F("连接超时,重新监听 UDP..."));
}
我在startFinishNotification函数中发送上线通知,这里我们将发送十次消息。
void startFinishNotification()
{
isNotifying = true; // 立即标记成功,让主逻辑跑起来
notificationCount = 10; // 计划发10次
Serial.println(F("连接成功,开始后台广播通知..."));
}
void updateNotifications()
{
if (isNotifying && notificationCount > 0)
{
if (millis() - lastNotifyTime > 1000)
{
lastNotifyTime = millis();
// 配网成功后,向全网段广播一个成功信号,让小程序知道
IPAddress ip = WiFi.localIP();
udp.beginPacket(IPAddress(255, 255, 255, 255), 9194);
// 使用字符串拼接性能更高
udp.printf("{\"status\":\"ok\",\"ip\":\"%u.%u.%u.%u\",\"mac\":\"%s\"}",
ip[0], ip[1], ip[2], ip[3],
WiFi.macAddress().c_str());
udp.endPacket();
notificationCount--;
if (notificationCount == 0)
{
isNotifying = false; // 任务结束
udp.stop();
Serial.println(F("广播通知结束,释放 UDP"));
}
}
}
}
需要注意的是,在像小程序发送ok状态时,使用的是广播地址,使用它的原因是当小程序连接HOME网络时,ESP8266并不知道它的IP,使用广播地址,在同一个WIFI下,小程序就可以收到。
在实际测试的时候,小程序碰到了很多问题,这里一起记录一下。小程序遇到的第一个问题,就是权限的问题,当我需要获取周边WIFI的时候,报错提示getWifiList需要userLocation权限。我一番搜索后,找到了解决方法,就是在app.json中添加
"permission": {
"scope.userLocation": {
"desc": "扫描附近的 WiFi 设备需要开启定位权限"
}
}
嗯,添加之后,小程序无法编译,第一次没有仔细看,以为写错了,第二次仔细看时,是因为desc的内容太长了,它还有字数限制,最长30个字符。调整字数后就可以编译。此时就可以通过手机去搜索ESP设备。
当SSID和密码正确时,ESP小板子能正常连上wifi,并按照预设的频率闪烁led。从灯的频率,可以知道连接已经成功了。但是小程序状态还是在连接中。经过排查分析应该是没有收到ESP板子的回应。
推测的原因大概有以下几种情况:
板子发送太快,次数太少,小程序在从esp wifi切换到家用wifi的时候,udp包已经发送完毕。所以需要修改esp发送频率和次数。
小程序需要在收到esp板子的回应后,马上切换到家用wifi,否则无法收到广播消息。
我们一一解决。首先在ESP端当去连接HOME WIFI的时候,明确关闭AP。然后就是小程序端连接动画需要添加超时,最长30秒,如果超时直接显示请查看esp LED灯状态。还有就是ESP发送通知时必须使用广播地址。以前写法逻辑有问题,它使用了小程序发送时的ip,当手机切换网络时,ip已经切换了。所以也会发送不成功。
经过几次调整后,现在已经可以正常UDP配网了。
项目源码下载地址:https://91demo.top/tools/
查看我的演示视频:基于 ESP8266 的智能设备配网与控制系统:UDP 配网 + mDNS 发现 + Modbus TCP 控制