admin管理员组文章数量:1620934
Arduino ESP32Web配网(二)
- 相关篇《Arduino ESP32Web配网》
相对于之前的那篇文章,这篇的配网有不同的地方就是,html页面修饰了一下。
配网操作
1.如果是第一次配网,就可以省略第一步,如果是清空WIFI信息请接下来看这一步。
还是采用的GPIO 0引脚下拉作为清除nvs数据的引脚。我是采用一根导线串联1K的电阻进行与GND短接,如果是串联的是10K的电阻,短接到GND是没有反应的。为什么串电阻短接到地,直接短接到GND不行吗,也可以,为了保护一下引脚。(注意上面的那种板子的GPIO 0引脚是没有引出来的,需要条线进行短接,当然你可以跟换引脚定义也可以,根据个人需求)
- 连接配网wifi
点击连接,即可自动跳转到打浏览器并进入到配网界面
点击保存并连接后,串口打印信息。
3. 配网成功后,只要不主动去清除wifi信息,nvs数据中将永远保存该信息。
4. 主动清空nvs数据操作,非必须项。
从下图可以看出,清空前,
nvs
容量是415
,清空后的容量变大了,变成了421
,清空数据后会重启,自动进入到配网模式。
自动配网源码(采用的VSCode Platform IO进行编译的)
#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"
#define NTP2 "ntp2.aliyun"
#define NTP3 "ntp3.aliyun"
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();
}
}
代码还可以优化,只是演示功能实现,网页配网页面可以添加其他参数配置选项,这里只是做演示,代码是从其他项目里面移植出来的功能。优化后,可以作为其他项目的功能模块来使用。
版权声明:本文标题:Arduino ESP32Web配网(二) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dongtai/1728819087a1175224.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论