ESP32C3 的配网方式有好多种,这里主要使用AP配网方式。在 ESP32C3 上建立热点AP,使用手机连接上后在浏览器打开配置网页,输入WIFI信息,完成配网。这种方式很可靠,而且允许在电脑端完成配网。
配网流程
AP配网(Soft AP)
ESP32C3配置为AP模式
手机or电脑连接ESP32热点,发送WiFi和密码
ESP32设置为STA模式,连接WIFI。
手机登录页面
手机连接到"ESP32-C3-1"
登录“ESP32-C3-1”
配网用到的
ConfigWiFi.h
#ifndef __CONFIGWIFI_H__
#define __CONFIGWIFI_H__#include <WiFi.h>
#include <DNSServer.h>
#include <WebServer.h>
#include <ESPmDNS.h> //用于设备域名 MDNS.begin("esp32")
#include <esp_wifi.h> //用于esp_wifi_restore() 删除保存的wifi信息#define ROOT_HTML "<!DOCTYPE html><html><head><title>设置WIFI</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><style type=\"text/css\">.input{display: block; margin-top: 10px;}.input span{width: 200px; float: left; float: left; height: 36px; line-height: 36px;}.input input{height: 30px;width: 200px;}.btn{width: 150px; height: 35px; background-color: #3CBC8D; border:0px; color:#000000; margin-top:15px; }</style><body><h3>设置 WIFI</h3><form method=\"POST\" action=\"configwifi\"><table><tr><td><label class=\"input\"><span>WiFi SSID</span></label></td></tr><ty><td><label><input type=\"text\" name=\"ssid\" value=\"\"></label></td></tr><tr><td><label class=\"input\"><span>WiFi PASS</span></label></td></tr><tr><td><label> <input type=\"text\" name=\"pass\"></label></td></tr><tr><td><label><input class=\"btn\" type=\"submit\" name=\"submit\" value=\"确 定\"></label></td></tr><tr><td> <h3> 附 近 wifi:</h3></td></tr></table></form>"#define DNS_PORT 53 //设置DNS端口号
#define webPort 80 //设置Web端口号
#define HOST_NAME "MY_ESP32" //设置设备名//==============================================
class ConfigWifi{public:ConfigWifi( char *aAP_ssid="AutoConnectAP");// ConfigWifi( char *aAP_ssid, char *aAP_pass);void connectToWiFi(int timeOut_s); //连接WiFivoid checkConnect(bool reConnect); //检测wifi是否已经连接请求void restoreWiFi(); //删除保存的wifi信息static void handleRoot(); //处理网站根目录的访问请求static void handleConfigWifi() ; //提交数据后的提示页面static void handleNotFound(); //处理404情况的函数'handleNotFound'void initSoftAP(); //进入AP模式void initDNS(); //开启DNS服务器void initWebServer(); //初始化WebServerbool scanWiFi(); //扫描附近的WiFi,为了显示在配网界面char* iAP_ssid = "AutoConnectAP"; //设置AP热点名称// char* iAP_pass = ""; //设置AP热点密码
};
#endif
ConfigWiFi.cpp
#include "ConfigWifi.h"String scanNetworksID = ""; //用于储存扫描到的WiFi ID
String iWifi_ssid = ""; //暂时存储wifi账号密码
String iWifi_pass = ""; //暂时存储wifi账号密码IPAddress AP_IP(192, 168, 4, 1); //设置AP的IP地址
DNSServer dnsServer; //创建dnsServer实例
WebServer server(webPort); //开启web服务, 创建TCP SERVER,参数: 端口号,最大连接数ConfigWifi::ConfigWifi(char *aAP_ssid){iAP_ssid = aAP_ssid;}// ConfigWifi::ConfigWifi(char *aAP_ssid,char *aAP_pass){
// iAP_ssid = aAP_ssid;
// iAP_pass = aAP_pass;
// }void ConfigWifi::connectToWiFi(int timeOut_s){WiFi.hostname(HOST_NAME); //设置设备名Serial.println("进入connectToWiFi()函数");WiFi.mode(WIFI_STA); //设置为STA模式并连接WIFIWiFi.setAutoConnect(true); //设置自动连接 Serial.println("用nvs保存的信息连接.");WiFi.begin(); //begin()不传入参数,默认连接上一次连接成功的wifiint Connect_time = 0; //用于连接计时,如果长时间连接不成功,复位设备while ((WiFi.status() != WL_CONNECTED)&(Connect_time <= 2 * timeOut_s)) { //等待WIFI连接成功Serial.print("."); //一共打印30个点点delay(500);Connect_time ++;}while(WiFi.status() != WL_CONNECTED){initSoftAP(); initDNS(); initWebServer(); scanWiFi(); while(iWifi_ssid == ""){dnsServer.processNextRequest(); //检查客户端DNS请求server.handleClient(); //检查客户端(浏览器)http请求}delay(2000);WiFi.softAPdisconnect(true); //参数设置为true,设备将直接关闭接入点模式,即关闭设备所建立的WiFi网络。server.close(); //关闭web服务WiFi.softAPdisconnect(); //在不输入参数的情况下调用该函数,将关闭接入点模式,并将当前配置的AP热点网络名和密码设置为空值.Serial.println("WiFi Connect SSID:" + iWifi_ssid + " PASS:" + iWifi_pass);WiFi.hostname(HOST_NAME); //设置设备名WiFi.mode(WIFI_STA); //设置为STA模式并连接WIFIWiFi.setAutoConnect(true); //设置自动连接 Serial.println("用web配置信息连接.");WiFi.begin(iWifi_ssid.c_str(),iWifi_pass.c_str()); //连接wifiiWifi_ssid = "";iWifi_pass = "";int Connect_time = 0; //用于连接计时,如果长时间连接不成功,复位设备while ((WiFi.status() != WL_CONNECTED)&(Connect_time <= 2 * timeOut_s)) { //等待WIFI连接成功Serial.print("."); //一共打印30个点点delay(500);Connect_time ++;}}if (WiFi.status() == WL_CONNECTED){Serial.println("WIFI连接成功."); } }void ConfigWifi:: checkConnect(bool reConnect){if (WiFi.status() != WL_CONNECTED) { //wifi连接失败if (reConnect == true && WiFi.getMode() != WIFI_AP && WiFi.getMode() != WIFI_AP_STA ) {Serial.println("WIFI未连接.");Serial.println("WiFi Mode:");Serial.println(WiFi.getMode());Serial.println("正在连接WiFi...");WiFi.begin(); //连接wifi delay(30000); }if (WiFi.status() == WL_CONNECTED){Serial.println("WIFI连接成功."); }}
}
void ConfigWifi:: restoreWiFi(){delay(500);esp_wifi_restore(); //删除保存的wifi信息Serial.println("连接信息已清空,准备重启设备..");delay(10);}void ConfigWifi:: handleRoot() {if (server.hasArg("selectSSID")) {server.send(200, "text/html", ROOT_HTML + scanNetworksID + "</body></html>"); //scanNetWprksID是扫描到的wifi} else {server.send(200, "text/html", ROOT_HTML + scanNetworksID + "</body></html>"); }}void ConfigWifi:: handleConfigWifi(){if (server.hasArg("ssid")) { //判断是否有账号参数Serial.print("got ssid:");iWifi_ssid = server.arg("ssid"); //获取html表单输入框name名为"ssid"的内容Serial.println(iWifi_ssid);} else { //没有参数Serial.println("error, not found ssid");server.send(200, "text/html", "<meta charset='UTF-8'>error, not found ssid"); //返回错误页面return;}//密码与账号同理if (server.hasArg("pass")) {Serial.print("got password:");iWifi_pass = server.arg("pass"); //获取html表单输入框name名为"pwd"的内容Serial.println(iWifi_pass);} else { Serial.println("error, not found password");server.send(200, "text/html", "<meta charset='UTF-8'>error, not found password");return;}server.send(200, "text/html", "<meta charset='UTF-8'><h2>SSID:" + iWifi_ssid + "<br />password:" + iWifi_pass + "<br />已取得WiFi信息,正在尝试连接,请手动关闭此页面。</h2>"); //返回保存成功页面}void ConfigWifi:: handleNotFound(){ // 当浏览器请求的网络资源无法在服务器找到时通过此自定义函数处理handleRoot(); //访问不存在目录则返回配置页面// server.send(404, "text/plain", "404: Not found");
}void ConfigWifi::initSoftAP(){WiFi.mode(WIFI_AP); //配置为AP模式WiFi.softAPConfig(AP_IP, AP_IP, IPAddress(255, 255, 255, 0)); //设置AP热点IP和子网掩码if (WiFi.softAP(iAP_ssid/*,iAP_pass*/)) //开启AP热点,如需要密码则添加第二个参数{ //打印相关信息Serial.println("ESP-32S SoftAP is right.");Serial.print("Soft-AP IP address = ");Serial.println(WiFi.softAPIP()); //接入点ipSerial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str()); //接入点mac} else { //开启AP热点失败Serial.println("WiFiAP Failed");delay(1000);Serial.println("restart now...");ESP.restart(); //重启复位esp32}}void ConfigWifi:: initDNS(){if (dnsServer.start(DNS_PORT, "*", AP_IP)) { //判断将所有地址映射到esp32的ip上是否成功Serial.println("start dnsserver success.");} else {Serial.println("start dnsserver failed.");}}void ConfigWifi:: initWebServer(){if (MDNS.begin("esp32")) { //给设备设定域名esp32,完整的域名是esp32.localSerial.println("MDNS responder started");}//必须添加第二个参数HTTP_GET,以下面这种格式去写,否则无法强制门户server.on("/", HTTP_GET, handleRoot); // 当浏览器请求服务器根目录(网站首页)时调用自定义函数handleRoot处理,设置主页回调函数,必须添加第二个参数HTTP_GET,否则无法强制门户server.on("/configwifi", HTTP_POST, handleConfigWifi); // 当浏览器请求服务器/configwifi(表单字段)目录时调用自定义函数handleConfigWifi处理server.onNotFound(handleNotFound); //当浏览器请求的网络资源无法在服务器找到时调用自定义函数handleNotFound处理server.begin(); //启动TCP SERVERSerial.println("WebServer started!");}bool ConfigWifi:: scanWiFi(){Serial.println("scan start");Serial.println("--------->");// 扫描附近WiFiint n = WiFi.scanNetworks();Serial.println("scan done");if (n == 0) {Serial.println("no networks found");scanNetworksID = "no networks found";return false;} else {Serial.print(n);Serial.println(" networks found");for (int i = 0; i < n; ++i) {// Print SSID and RSSI for each network foundSerial.print(i + 1);Serial.print(": ");Serial.print(WiFi.SSID(i));Serial.print(" (");Serial.print(WiFi.RSSI(i));Serial.print(")");Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");scanNetworksID += "<P>" + WiFi.SSID(i) + "</P>";delay(10);}return true;}
}
示例
#include "Arduino.h"
#include "ConfigWifi.h"ConfigWifi configwifi("ESP32-C3-1"); //创建实例,AP热点名:ESP32-C3-1void setup() {// put your setup code here, to run once:Serial.begin(115200);configwifi.connectToWiFi(30); //连接配网,30秒超时。/*调试WIFI配网时用,可删除WIFI保存的SSID和PASS,通过串口监视器操作*/// Serial.println("删除WIFI信息?:");// char temp[1];// while(temp[0] !='y' && temp[0]!='n' ){// if (Serial.available())// {// temp[0] = Serial.read();// } // }// if( temp[0] == 'y' ){// configwifi.restoreWiFi(); // ESP.restart(); //重启复位esp32// }
//==================END=================================}void loop() {// put your main code here, to run repeatedly:configwifi.checkConnect(true); // 检查是否断网,断网自动连接。
}