赞
踩
相对于之前的那篇文章,这篇的配网有不同的地方就是,html页面修饰了一下。
1.如果是第一次配网,就可以省略第一步,如果是清空WIFI信息请接下来看这一步。
还是采用的GPIO 0引脚下拉作为清除nvs数据的引脚。我是采用一根导线串联1K的电阻进行与GND短接,如果是串联的是10K的电阻,短接到GND是没有反应的。为什么串电阻短接到地,直接短接到GND不行吗,也可以,为了保护一下引脚。(注意上面的那种板子的GPIO 0引脚是没有引出来的,需要条线进行短接,当然你可以跟换引脚定义也可以,根据个人需求)
点击连接,即可自动跳转到打浏览器并进入到配网界面
点击保存并连接后,串口打印信息。
3. 配网成功后,只要不主动去清除wifi信息,nvs数据中将永远保存该信息。
4. 主动清空nvs数据操作,非必须项。
从下图可以看出,清空前,
nvs
容量是415
,清空后的容量变大了,变成了421
,清空数据后会重启,自动进入到配网模式。
#include <Arduino.h> #include <WiFi.h> //#include <WiFiUdp.h> #include <HTTPClient.h> #include <Preferences.h> #include "SetWiFi.h" //Web配网 #include <esp_wifi.h> //用于esp_wifi_restore() 删除保存的wifi信息 String PrefSSID, PrefPassword, cityCode; //在VSCode Platform IO里面,板子led灯需要注释掉,不然报警告,在ArduinoIDE中需要启用这个宏定义,不然找不到该定义的错误信息产生。 #define LED_BUILTIN (2) //板载led灯 #define NTP1 "ntp1.aliyun.com" #define NTP2 "ntp2.aliyun.com" #define NTP3 "ntp3.aliyun.com" unsigned long wifiTimes = 0; bool ledState = LOW; const unsigned long interval = 6000UL; //设置延时时间间隔 unsigned long previousMillis = 0; //const char* ssid = "MERCURY_D268G"; //const char* password = "pba5ayzk"; //强制门户Web配网 const int resetPin = 0; //设置重置按键引脚,用于删除WiFi信息 bool setWiFi_Flag = false; String NowTime(); void setWiFi() { initSoftAP(); initWebServer(); initDNS(); while (setWiFi_Flag == false) { server.handleClient(); dnsServer.processNextRequest(); if (WiFi.status() == WL_CONNECTED) { server.stop(); setWiFi_Flag = true; } } } //删除保存的wifi信息 void DeleteWiFi(){ Preferences prefs; prefs.begin("wifi",false);//为false才能删除键值 Serial.println(prefs.freeEntries());//查询清除前的剩余空间 prefs.remove("ssid"); // 删除当前命名空间中键名为"ssid"的元素 prefs.remove("password"); // 删除当前命名空间中键名为"ssid"的元素 prefs.clear(); delay(500); Serial.println(prefs.freeEntries());//查询清除后的剩余空间 prefs.end(); esp_wifi_restore(); //删除保存的wifi信息 Serial.println("连接信息已清空,准备重启设备.."); } void setup() { Serial.begin(115200); pinMode(LED_BUILTIN, OUTPUT); //板载led灯作为指示 pinMode(resetPin, INPUT_PULLUP); //按键上拉输入模式(默认高电平输入,按下时下拉接到低电平) //首次使用自动进入配网模式,读取NVS存储空间内的ssid、password和citycode Preferences prefs; prefs.begin("wifi"); if (prefs.isKey("ssid"),"nano") PrefSSID = prefs.getString("ssid","nano");//如果键值为空,返回0 if (prefs.isKey("password")) PrefPassword = prefs.getString("password"); if (prefs.isKey("citycode")) cityCode = prefs.getString("citycode"); prefs.end();//从nvs获取到wifi信息后,关闭Preferences if (PrefSSID == "nano") { setWiFi(); }else{ Serial.println(PrefSSID); Serial.println(PrefPassword); Serial.println(cityCode); WiFi.mode(WIFI_STA);//切换为STA模式,进行入网 WiFi.begin(PrefSSID.c_str(), PrefPassword.c_str()); Serial.println("正在连接" + PrefSSID + "...Connecting to WiFi..."); Serial.println("-------------"); } byte i = 0; while (WiFi.status() != WL_CONNECTED) { i++; Serial.print('.'); delay(500); if (i > 10) { setWiFi(); } digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //板载led灯闪烁 } Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str()); Serial.printf("PSW:%s\r\n", WiFi.psk().c_str()); Serial.println(WiFi.localIP()); configTime(8 * 3600, 0, NTP1, NTP2, NTP3); } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { ledState = !ledState; //状态翻转 digitalWrite(LED_BUILTIN, ledState); struct tm timeInfo; //声明一个结构体 if (!getLocalTime(&timeInfo)) { //一定要加这个条件判断,否则内存溢出 Serial.println("Failed to obtain time"); } Serial.println(&timeInfo, "%F %T %A"); previousMillis = currentMillis; } if(!digitalRead(resetPin)){ delay(3000); if(!digitalRead(resetPin)){ //1Kde 下来电阻,10K的拉不动 Serial.println("\n按键已长按3秒,正在清空NVS保存的信息."); DeleteWiFi(); //删除保存的wifi信息 ESP.restart(); //重启复位esp32 Serial.println("已重启设备."); } } }
SetWiFi.h
代码#include <WiFi.h> #include <DNSServer.h> #include <WebServer.h> #include <Preferences.h> const char* AP_NAME = "ESP32WiFiAP";//Web配网模式下的AP-wifi名字 extern String PrefSSID, PrefPassword,cityCode; //暂时存储wifi账号密码 char sta_ssid[32] = {0}; char sta_password[64] = {0}; char sta_citycode[32] = {0}; //配网页面代码 String page_html = R"( <!DOCTYPE html> <html lang='en'> <head> <meta charset='UTF-8'> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"> <title>ESP32参数配置页面</title> <style type="text/css"> * { margin: 0; padding: 0; } html { height: 100%; } h2 {text-align: center;color: #fff;line-height: 2.2;} body { height: 100%; background-color: #1F6F4A; 50% 50% no-repeat; background-size: cover;} .dowebok { position: absolute; left: 50%; top: 30%; width: 380px; height: 500px; margin: -200px 0 0 -200px; border: 3px solid #fff; border-radius: 10px; overflow: hidden;} .form-item { position: relative; width: 360px; margin: 0 auto; padding-bottom: 20px;} .form-item input { width: 288px; height: 48px; padding-left: 10px; border: 1px solid #fff; border-radius: 25px; font-size: 18px; color: #fff; background-color: transparent; outline: none;} .send_button { width: 360px; height: 50px; border: 0; border-radius: 25px; font-size: 18px; color: #1f6f4a; outline: none; cursor: pointer; background-color: #fff; } .tip { display: none; position: absolute; left: 20px; top: 52px; font-size: 14px; color: #f50; } .reg-bar { width: 360px; margin: 20px auto 0; font-size: 14px; overflow: hidden;} .reg-bar a { color: #fff; text-decoration: none; } .reg-bar a:hover { text-decoration: underline; } .reg-bar .reg { float: left; } .reg-bar .forget { float: right; } .dowebok ::-webkit-input-placeholder { font-size: 18px; line-height: 1.4; color: #fff;} .dowebok :-moz-placeholder { font-size: 18px; line-height: 1.4; color: #fff;} .dowebok ::-moz-placeholder { font-size: 18px; line-height: 1.4; color: #fff;} .dowebok :-ms-input-placeholder { font-size: 18px; line-height: 1.4; color: #fff;} @media screen and (max-width: 500px) { * { box-sizing: border-box; } .dowebok { position: static; width: auto; height: auto; margin: 0 30px; border: 0; border-radius: 0; } .logo { margin: 50px auto; } .form-item { width: auto; } .form-item input, .form-item button, .reg-bar { width: 100%; } } </style> </head> <body> <div class="dowebok"> <h2>参 数 配 置</h2> <form style='text-align: center;padding-top: 20px' name='input' action='/' method='POST'> <div class="form-item"> <input id="username" type="text" name='ssid' autocomplete="off" placeholder="WiFi名称"> </div> <div class="form-item"> <input id="password" type="password" name='password' autocomplete="off" placeholder="WiFi密码"> </div> <div class="form-item"> <input id="citycode" type="citycode" name='citycode' autocomplete="off" placeholder="城市代码,留空则自动定位获取"> </div> <div class="form-item"> <div id=""> <input id="send_button" type='submit' value='保存并连接'> </div> </div> <div class="form-item"> <div class="user_text"> <br> <p><h3>如何获取cityCode:</h3></p> <h5> 1、城市代码由9位阿拉伯数字组成,超过位数会导致获取不到数据而无限重启 </h5> </p> </div> </div> </form> </div> </body> </html> )"; const byte DNS_PORT = 53;//DNS端口号 IPAddress apIP(192, 168, 4, 1);//esp32-AP-IP地址 DNSServer dnsServer;//创建dnsServer实例 WebServer server(80);//创建WebServer void handleRoot() {//访问主页回调函数 server.send(200, "text/html", page_html); } void initSoftAP(void){//初始化AP模式 WiFi.mode(WIFI_AP); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); Serial.println(WiFi.softAPIP()); // Serial.print("本地IP: "); // Serial.println(WiFi.localIP()); if(WiFi.softAP(AP_NAME)){ Serial.println("ESP32 SoftAP is right"); } } void initDNS(void){//初始化DNS服务器 if(dnsServer.start(DNS_PORT, "*", apIP)){//判断将所有地址映射到esp8266的ip上是否成功 Serial.println("start dnsserver success."); } else Serial.println("start dnsserver failed."); } void handleRootPost() {//Post回调函数 String wifiid="",wifipass="",cityid=""; Serial.println("handleRootPost"); if (server.hasArg("ssid")) {//判断是否有账号参数 Serial.print("got ssid:"); strcpy(sta_ssid, server.arg("ssid").c_str());//将账号参数拷贝到sta_ssid中 Serial.println(sta_ssid); } else {//没有参数 Serial.println("error, not found ssid"); server.send(200, "text/html", "<meta charset='UTF-8'>提示:请输入WiFi名称");//返回错误页面 return; } //密码与账号同理 if (server.hasArg("password")) { Serial.print("got password:"); strcpy(sta_password, server.arg("password").c_str()); Serial.println(sta_password); } else { Serial.println("error, not found password"); server.send(200, "text/html", "<meta charset='UTF-8'>提示:请输入WiFi密码"); return; } if (server.hasArg("citycode")) { Serial.print("got citycode:"); strcpy(sta_citycode, server.arg("citycode").c_str()); Serial.println(sta_citycode); } else { Serial.println("error, not found citycode"); server.send(200, "text/html", "<meta charset='UTF-8'>提示:请输入城市代码"); return; } Preferences prefs; prefs.begin("wifi"); wifiid=sta_ssid;wifipass=sta_password;cityid=sta_citycode; prefs.putString( "ssid" ,wifiid); prefs.putString( "password", wifipass); prefs.putString( "citycode", cityid); prefs.end(); server.send(200, "text/html", "<meta charset='UTF-8'><h1>保存成功,ESP32重启中...</h1>");//返回保存成功页面 delay(2000); //连接wifi //connectNewWifi(); ESP.restart(); //重启ESP32 } void initWebServer(void){//初始化WebServer //server.on("/",handleRoot); //上面那行必须以下面这种格式去写否则无法强制门户 server.on("/", HTTP_GET, handleRoot);//设置主页回调函数 server.onNotFound(handleRoot);//设置无法响应的http请求的回调函数 server.on("/", HTTP_POST, handleRootPost);//设置Post请求回调函数 server.begin();//启动WebServer Serial.println("WebServer started!"); } void connectNewWifi(void){ Preferences prefs; prefs.begin("wifi"); if(prefs.isKey("ssid")) PrefSSID = prefs.getString("ssid"); Serial.println(PrefSSID); if(prefs.isKey("password")) PrefPassword = prefs.getString("password"); Serial.println(PrefPassword); if(prefs.isKey("citycode")) cityCode = prefs.getString("citycode"); Serial.println(cityCode); prefs.end(); // WiFi.mode(WIFI_STA); WiFi.begin(PrefSSID.c_str(), PrefPassword.c_str()); WiFi.mode(WIFI_STA);//切换为STA模式 WiFi.setAutoConnect(true);//设置自动连接 // WiFi.begin(PrefSSID.c_str(), PrefPassword.c_str());//连接上一次连接成功的wifi Serial.println(""); Serial.print("Connect to wifi"); int count = 0; while (WiFi.status() != WL_CONNECTED) { delay(500); count++; if(count > 20){//如果10秒内没有连上,就开启Web配网 可适当调整这个时间 initSoftAP(); initWebServer(); initDNS(); break;//跳出 防止无限初始化 } Serial.print("."); } Serial.println(""); if(WiFi.status() == WL_CONNECTED){ Serial.println("WIFI Connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); server.stop(); } }
代码还可以优化,只是演示功能实现,网页配网页面可以添加其他参数配置选项,这里只是做演示,代码是从其他项目里面移植出来的功能。优化后,可以作为其他项目的功能模块来使用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。