不想了解代码实现,可直接到代码部分copy!ESP32亲测可用。
使用设备ESP32开发板(ESP32-WROOM-32)
搜了好多别人写的资料,很多都是copy+copy,也没有什么解释。啪,代码放在那里,自己看吧。
我不是说他们写的都是垃圾哈 ~ 那我承认,我就是这么想的,有的说是教程也啥都没写
不能怪人家不能怪人家,咱还是自己学!!!
咱的代码也是copy了再改的,没脸说人家。
让我自己写的话,那不叫写代码,那叫写bug。
在学习中进步!!
正题开始了
设备热点配网(Soft AP)
- ESP32配置为AP模式
- 手机or电脑连接ESP32热点,发送WiFi和密码
- ESP32设置为STA模式
很抱歉C++的基础不好,没封装成库的形式,创建类后有一部分函数总是报错,没有解决。
但是也分成了文件的形式,要是拷贝使用也非常方便。
说明:LED显示配网状态
LED闪烁:表示正在尝试连接网络。
LED常亮:表示网络连接成功
LED常灭:表示等待配网
LED闪烁5次:表示已清除wifi信息
配网状态下ESP32开发板还挺温乎的!
配网页面
实话实说,这是我抄的!!
但是我忘记在哪里抄的了。
(我的手机截图)
配网完成界面
网页的HTML
我是在这个网站看嫖来的配网界面好不好看的。
在线的,目前免费,试了一试还挺好用的
在这个软件中,新建工程复制进去这个代码就能看网页效果了。
配网界面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: 100px; float: left; float: left; height: 36px; line-height: 36px;}.input input{height: 30px;width: 200px;}.btn{width: 120px; height: 35px; background-color: #000000; border:0px; color:#ffffff; margin-top:15px; margin-left:100px;}</style><body><form method="POST" action="configwifi"><label class="input"><span>WiFi SSID </span><input type="text" name="ssid"></label><label class="input"><span>WiFi PASS</span> <input type="text" name="pass"></label><input class="btn" type="submit" name="submit" value="Submie"> <p><span> Nearby wifi:</P></form></body>
</html>
串口打印
红线上为配网前打印
红线后为配网后打印
以上就是代码之外的资料了 ~
现在开始代码分析
本次工程包含三个文件main.ino、WiFiUser.cpp、WiFiUser.h
有关配网的函数都在WiFiUser.cpp、WiFiUser.h文件中,可直接添加这两个文件到工程目录下进行调用。
如果不想学习怎么实现,可直接复制这两个文件,两分钟内实现配网操作!
由于官方命名原因,ESP8266的库文件需要更改为ESP8266+库文件的形式,但函数可通用。(此条说明未验证)
-
如果想了解实现原理,需配合串口打印信息来分析。
WiFiUser.h
很遗憾没有设置成类的形式,以后要改!!
在此文件夹下,声明了函数。可以见得,include此文件,只需要在自己写的函数中调用3个函数即可实现配网全操作。5个文件中一个是LED、一个是清除wifi保存在flash的信息、只有三个才是配网所需函数!
#ifndef __WIFIUSER_H__
#define __WIFIUSER_H__#include <WiFi.h>
#include <DNSServer.h>
#include <WebServer.h>
#include <ESPmDNS.h> //用于设备域名 MDNS.begin("esp32")
#include <esp_wifi.h> //用于esp_wifi_restore() 删除保存的wifi信息extern const int LED; //设置LED引脚
extern const char* HOST_NAME; //设置设备名
extern int connectTimeOut_s; //WiFi连接超时时间,单位秒//===========需要调用的函数===========
void checkConnect(bool reConnect); //检测wifi是否已经连接
void restoreWiFi(); //删除保存的wifi信息
void LEDinit(); //LED初始化
void checkDNS_HTTP(); //检测客户端DNS&HTTP请求
void connectToWiFi(int timeOut_s); //连接WiFi//===========内部函数===========
void handleRoot(); //处理网站根目录的访问请求
void handleConfigWifi() ; //提交数据后的提示页面
void handleNotFound(); //处理404情况的函数'handleNotFound'
void initSoftAP(); //进入AP模式
void initDNS(); //开启DNS服务器
void initWebServer(); //初始化WebServer
bool scanWiFi(); //扫描附近的WiFi,为了显示在配网界面
void wifiConfig(); //配置配网功能
void blinkLED(int led, int n, int t); //LED闪烁函数 //用不上LED可删除#endif
WiFiUser.cpp
这就是所有有关配网的函数的定义了 ~
这里有一点应该注意的是:HTML放在代码中时在 " 前应该加 \ (转义符)
#include "WiFiUser.h"const byte DNS_PORT = 53; //设置DNS端口号
const int webPort = 80; //设置Web端口号const char* AP_SSID = "ESP32-4_1"; //设置AP热点名称
//const char* AP_PASS = ""; //这里不设置设置AP热点密码const char* HOST_NAME = "MY_ESP32"; //设置设备名
String scanNetworksID = ""; //用于储存扫描到的WiFi IDIPAddress apIP(192, 168, 4, 1); //设置AP的IP地址String wifi_ssid = ""; //暂时存储wifi账号密码
String wifi_pass = ""; //暂时存储wifi账号密码const int LED = 2; //设置LED引脚DNSServer dnsServer; //创建dnsServer实例
WebServer server(webPort); //开启web服务, 创建TCP SERVER,参数: 端口号,最大连接数#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: 100px; float: left; float: left; height: 36px; line-height: 36px;}.input input{height: 30px;width: 200px;}.btn{width: 120px; height: 35px; background-color: #000000; border:0px; color:#ffffff; margin-top:15px; margin-left:100px;}</style><body><form method=\"POST\" action=\"configwifi\"><label class=\"input\"><span>WiFi SSID</span><input type=\"text\" name=\"ssid\" value=\"\"></label><label class=\"input\"><span>WiFi PASS</span> <input type=\"text\" name=\"pass\"></label><input class=\"btn\" type=\"submit\" name=\"submit\" value=\"Submie\"> <p><span> Nearby wifi:</P></form>"/** 处理网站根目录的访问请求*/
void 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 handleConfigWifi() //返回http状态
{if (server.hasArg("ssid")) //判断是否有账号参数{Serial.print("got ssid:");wifi_ssid = server.arg("ssid"); //获取html表单输入框name名为"ssid"的内容Serial.println(wifi_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:");wifi_pass = server.arg("pass"); //获取html表单输入框name名为"pwd"的内容Serial.println(wifi_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'>SSID:" + wifi_ssid + "<br />password:" + wifi_pass + "<br />已取得WiFi信息,正在尝试连接,请手动关闭此页面。"); //返回保存成功页面delay(2000);WiFi.softAPdisconnect(true); //参数设置为true,设备将直接关闭接入点模式,即关闭设备所建立的WiFi网络。server.close(); //关闭web服务WiFi.softAPdisconnect(); //在不输入参数的情况下调用该函数,将关闭接入点模式,并将当前配置的AP热点网络名和密码设置为空值.Serial.println("WiFi Connect SSID:" + wifi_ssid + " PASS:" + wifi_pass);if (WiFi.status() != WL_CONNECTED) //wifi没有连接成功{Serial.println("开始调用连接函数connectToWiFi()..");connectToWiFi(connectTimeOut_s);} else {Serial.println("提交的配置信息自动连接成功..");}
}/** 处理404情况的函数'handleNotFound'*/
void handleNotFound() // 当浏览器请求的网络资源无法在服务器找到时通过此自定义函数处理
{ handleRoot(); //访问不存在目录则返回配置页面// server.send(404, "text/plain", "404: Not found");
}/** 进入AP模式*/
void initSoftAP() {WiFi.mode(WIFI_AP); //配置为AP模式WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); //设置AP热点IP和子网掩码if (WiFi.softAP(AP_SSID)) //开启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}
}/** 开启DNS服务器*/
void initDNS()
{if (dnsServer.start(DNS_PORT, "*", apIP)) //判断将所有地址映射到esp32的ip上是否成功{Serial.println("start dnsserver success.");} else {Serial.println("start dnsserver failed.");}
}/** 初始化WebServer*/
void initWebServer()
{if (MDNS.begin("esp32")) //给设备设定域名esp32,完整的域名是esp32.local{Serial.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!");
}/** 扫描附近的WiFi,为了显示在配网界面*/
bool 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;}
}/** 连接WiFi*/
void connectToWiFi(int timeOut_s) {WiFi.hostname(HOST_NAME); //设置设备名Serial.println("进入connectToWiFi()函数");WiFi.mode(WIFI_STA); //设置为STA模式并连接WIFIWiFi.setAutoConnect(true); //设置自动连接 if (wifi_ssid != "") //wifi_ssid不为空,意味着从网页读取到wifi{Serial.println("用web配置信息连接.");WiFi.begin(wifi_ssid.c_str(), wifi_pass.c_str()); //c_str(),获取该字符串的指针wifi_ssid = "";wifi_pass = "";} else //未从网页读取到wifi{Serial.println("用nvs保存的信息连接.");WiFi.begin(); //begin()不传入参数,默认连接上一次连接成功的wifi}int Connect_time = 0; //用于连接计时,如果长时间连接不成功,复位设备while (WiFi.status() != WL_CONNECTED) //等待WIFI连接成功{ Serial.print("."); //一共打印30个点点digitalWrite(LED, !digitalRead(LED)); delay(500);Connect_time ++;if (Connect_time > 2 * timeOut_s) //长时间连接不上,重新进入配网页面{ digitalWrite(LED, LOW);Serial.println(""); //主要目的是为了换行符Serial.println("WIFI autoconnect fail, start AP for webconfig now...");wifiConfig(); //开始配网功能return; //跳出 防止无限初始化}}if (WiFi.status() == WL_CONNECTED) //如果连接成功{Serial.println("WIFI connect Success");Serial.printf("SSID:%s", WiFi.SSID().c_str());Serial.printf(", PSW:%s\r\n", WiFi.psk().c_str());Serial.print("LocalIP:");Serial.print(WiFi.localIP());Serial.print(" ,GateIP:");Serial.println(WiFi.gatewayIP());Serial.print("WIFI status is:");Serial.print(WiFi.status());digitalWrite(LED, HIGH);server.stop(); //停止开发板所建立的网络服务器。}
}/** 配置配网功能*/
void wifiConfig()
{initSoftAP(); initDNS(); initWebServer(); scanWiFi();
}/** 删除保存的wifi信息,这里的删除是删除存储在flash的信息。删除后wifi读不到上次连接的记录,需重新配网*/
void restoreWiFi() {delay(500);esp_wifi_restore(); //删除保存的wifi信息Serial.println("连接信息已清空,准备重启设备..");delay(10);blinkLED(LED, 5, 500); //LED闪烁5次 //关于LED,不需要可删除 digitalWrite(LED, LOW); //关于LED,不需要可删除
}/** 检查wifi是否已经连接*/
void checkConnect(bool reConnect)
{if (WiFi.status() != WL_CONNECTED) //wifi连接失败{if (digitalRead(LED) != LOW) digitalWrite(LED, LOW);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...");connectToWiFi(connectTimeOut_s); //连接wifi函数 }} else if (digitalRead(LED) != HIGH) digitalWrite(LED, HIGH); //wifi连接成功
}/** LED闪烁函数 //用不上LED可删除*/
void blinkLED(int led, int n, int t)
{for (int i = 0; i < 2 * n; i++) {digitalWrite(led, !digitalRead(led));delay(t);}
}/** LED初始化*/
void LEDinit()
{pinMode(LED, OUTPUT); //配置LED口为输出口digitalWrite(LED, LOW); //初始灯灭
}/** 检测客户端DNS&HTTP请求*/
void checkDNS_HTTP()
{dnsServer.processNextRequest(); //检查客户端DNS请求server.handleClient(); //检查客户端(浏览器)http请求
}
main.ino
#include "WiFiUser.h"const int resetPin = 0; //设置重置按键引脚,用于删除WiFi信息
int connectTimeOut_s = 15; //WiFi连接超时时间,单位秒void setup()
{pinMode(resetPin, INPUT_PULLUP); //按键上拉输入模式(默认高电平输入,按下时下拉接到低电平)Serial.begin(115200); //波特率LEDinit(); //LED用于显示WiFi状态connectToWiFi(connectTimeOut_s); //连接wifi,传入的是wifi连接等待时间15s
}void loop()
{if (!digitalRead(resetPin)) //长按5秒(P0)清除网络配置信息{delay(5000); //哈哈哈哈,这样不准确if (!digitalRead(resetPin)) {Serial.println("\n按键已长按5秒,正在清空网络连保存接信息.");restoreWiFi(); //删除保存的wifi信息ESP.restart(); //重启复位esp32Serial.println("已重启设备.");//有机会读到这里吗?}}checkDNS_HTTP(); //检测客户端DNS&HTTP请求,也就是检查配网页面那部分checkConnect(true); //检测网络连接状态,参数true表示如果断开重新连接delay(30);
}
不想了解代码实现的就不用往下看了,没必要没必要
代码详细解释
从setup()中调用了connectToWiFi(connectTimeOut_s);函数,进入连接wifi的入口。
connectToWiFi(int timeOut_s) //连接wifi
/** 连接WiFi*/
void connectToWiFi(int timeOut_s)
{WiFi.hostname(HOST_NAME); //设置设备名Serial.println("进入connectToWiFi()函数");WiFi.mode(WIFI_STA); //设置为STA模式并连接WIFIWiFi.setAutoConnect(true); //设置自动连接 if (wifi_ssid != "") //wifi_ssid不为空,意味着从网页读取到wifi{Serial.println("用web配置信息连接.");WiFi.begin(wifi_ssid.c_str(), wifi_pass.c_str()); //c_str(),获取该字符串的指针wifi_ssid = "";wifi_pass = "";} else //未从网页读取到wifi{Serial.println("用nvs保存的信息连接.");WiFi.begin(); //begin()不传入参数,默认连接上一次连接成功的wifi}int Connect_time = 0; //用于连接计时,如果长时间连接不成功,复位设备while (WiFi.status() != WL_CONNECTED) //等待WIFI连接成功{ Serial.print("."); //一共打印30个点点digitalWrite(LED, !digitalRead(LED)); delay(500);Connect_time ++;if (Connect_time > 2 * timeOut_s) //长时间连接不上,重新进入配网页面{ digitalWrite(LED, LOW);Serial.println(""); //主要目的是为了换行符Serial.println("WIFI autoconnect fail, start AP for webconfig now...");wifiConfig(); //开始配网功能return; //跳出 防止无限初始化}}if (WiFi.status() == WL_CONNECTED) //如果连接成功{Serial.println("WIFI connect Success");Serial.printf("SSID:%s", WiFi.SSID().c_str());Serial.printf(", PSW:%s\r\n", WiFi.psk().c_str());Serial.print("LocalIP:");Serial.print(WiFi.localIP());Serial.print(" ,GateIP:");Serial.println(WiFi.gatewayIP());Serial.print("WIFI status is:");Serial.print(WiFi.status());digitalWrite(LED, HIGH);server.stop(); //停止开发板所建立的网络服务器。}
}
本函数先检测wifi_ssid是否读进了参数,尝试用wifi_ssid方式和用上次连接成功保存的参数两种方式尝试连接,等待连接后未连接成功将调用wifiConfig()开始配网,连接成功则打印连接数据。
我要是每个函数都拿出来讲是不是很烦人啊~
WiFi.hostname(HOST_NAME); //设置设备名
此函数定义在ESP32官方库的WiFiGenerice库中
函数定义:输入参数手动给ESP32模块设置hostname(主机名)
当联网成功后打开路由器界面,可查看到连接设备:
说明我们设置的没问题。
WiFi.mode(WIFI_STA); //设置为STA模式并连接WIFI
此函数定义在WiFiGenerice库中
函数定义:配置WiFi的工作模式
工作模式一共有三种:接入点模式(AP)、无线终端模式(Station)以及混合模式。
- WIFI_OFF,(关闭WiFi)
- WIFI_STA,(无线终端模式)
- WIFI_AP, (接入点模式)
- WIFI_AP_STA,(接入点-无线终端双模式)
WiFi.setAutoConnect(true); //设置自动连接
此函数定义在WiFiSTA库中
函数定义:激活ESP32模块的自动连接模式。模块会在通电后自动连接到最近连接过的WiFi接入点。
ture:启动自动连接。false:禁用自动连接。
WiFi.begin(wifi_ssid.c_str(), wifi_pass.c_str()); //c_str(),获取该字符串的指针
此函数定义在WiFiSTA库中
函数定义:此函数用于连接WiFi,需要传入的函数是指针类型的。如果不传入参数,默认连接已保存的wifi。
WiFi.status() != WL_CONNECTED
此函数定义在WiFiSTA库中
函数定义:判断wifi连接状态
- WL_IDLE_STATUS:0,正在尝试连接
- WL_NO_SSID_AVAIL:1,没有找到SSID网络
- WL_SCAN_COMPLETED:2,网络扫描完毕
- WL_CONNECTED:3,网络连接成功
- WL_CONNECT_FAILED:4,连接失败
- WL_CONNECTION_LOST:5,连接丢失
- WL_DISCONNECTED:6,未连接
//WebServer server(webPort);
server.stop();
此函定义在WebServer库中
函数定义:本函数用于停止开发板所建立的网络服务器。
wifiConfig() //配置配网功能
/** 配置配网功能*/
void wifiConfig()
{initSoftAP(); initDNS(); initWebServer(); scanWiFi();
}
此函数调用四个函数实现配网功能的开启。
initSoftAP() //进入AP模式
/** 进入AP模式*/
void initSoftAP() {WiFi.mode(WIFI_AP); //配置为AP模式WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); //设置AP热点IP和子网掩码if (WiFi.softAP(AP_SSID)) //开启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}
}
主要是配置为AP热点模式
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); //设置AP热点IP和子网掩码
此函数定义在WiFiAP库
函数定义:配置接入点网络信息
三个参数分别为:接入点ip地址,网关ip地址,子虚掩码(均为IPAddress类型)
网关_百度百科 IP地址_百度百科 子网掩码_百度百科
不懂就照着写吧!
WiFi.softAP(AP_SSID)
此函数定义在WiFiAP库
函数定义:启动校验式wifi网络或开放式wifi网络。
bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4, bool ftm_responder = false);
此函数参数有:网络名称、密码、信道、wifi是否隐藏标志变量、最大允许接入数量(最多4个)
其他都默认就行。密码默认NULL
一般用不到其他功能。
WiFi.softAPmacAddress()
此函数定义在WiFiAP库
函数定义:建立wifi接入点后,我们可以使用本函数获取开发板的mac地址。
另一种使用方法
WiFi.softAPmacAddress(macAddr)
读mac地址:
macAddr[0]:macAddr[1]:macAddr[2]:macAddr[3]:macAddr[4]:macAddr[5]这种形式!!
initDNS() //开启DNS服务器
void initDNS()
{if (dnsServer.start(DNS_PORT, "*", apIP)) //判断将所有地址映射到esp32的ip上是否成功{Serial.println("start dnsserver success.");} else {Serial.println("start dnsserver failed.");}
}
DNS:域名服务器。域名服务器_百度百科
此函数没有考虑开启失败的问题!!
dnsServer.start(DNS_PORT, "*", apIP)
此函数定义在DNSServer库
函数定义:以无线终端模式工作时,调用本函数可以启动ESP32模块的DNS服务
函数有三个参数:
- DNS服务端口号(默认53)
- 映射的域名,也就是开启服务后可以直接访问的用于代替IP地址的域名
- 映射的IP地址
返回值:是否开启成功
这里的 * 替换成你想要的网站,例如:www.example.com 。可以替换成你想要的网址。当做项目时,替换成一个能代表你的网址就显得专业了~哈哈哈哈!实际访问的还是配网的ip地址。
initWebServer() //设置访问功能
void initWebServer()
{if (MDNS.begin("esp32")) //给设备设定域名esp32,完整的域名是esp32.local{Serial.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!");
}
此函数创建了网络服务器。
MDNS.begin("esp32") //给设备设定域名esp32,完整的域名是esp32.local
多播DNS
域名_百度百科
这个问题我不会!尴尬了!!
server.on("/", HTTP_GET, handleRoot); // 当浏览器请求服务器根目录(网站首页)时调用自定义函数handleRoot处理,设置主页回调函数,必须添加第二个参数HTTP_GET,否则无法强制门户
此函数定义在 WebServer库
函数定义:每当有客户端向服务器发送HTTP请求时,我们可以利用on函数来设置HTTP请求回调函数。
通过HTTP请求回调函数,我们可以让ESP32服务器生成响应信息并发送给HTTP请求客户端。
第二个参数为数据传输方法。
关键字:
- HTTP_ANY
- HTTP_GET
- HTTP_POST
- HTTP_PUT
- HTTP_PATCH
- HTTP_DELETE
- HTTP_OPTIONS
server.onNotFound(handleNotFound); //当浏览器请求的网络资源无法在服务器找到时调用自定义函数handleNotFound处理
此函数定义在 WebServer库
函数定义:每当有客户端向服务器发送HTTP请求时,我们可以利用onNotFound函数来设置HTTP请求无效地址的回调函数。
参数:处理无效地址请求的回调函数
server.begin(); //启动TCP SERVER
此函数定义在 WebServer库
函数定义:启动开发板所建立的网络服务器。
scanWiFi() //扫描附近的WiFi,为了显示在配网界面
/** 扫描附近的WiFi,为了显示在配网界面*/
bool 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;}
}
此函数扫描可搜索到的wifi,附加在HTML代码后。
WiFi.scanNetworks()
此函数定义在WiFiScan库
函数定义:扫描到ESP8266开发板所在环境中的可用WIFI网络,并且将WiFi网络信息保存到内存中。通过调用SSID、RSSI等函数,我们还可以得到这些扫描到的WIFI的更多信息。
此函数一次性得到完整的WiFi列表,并且将WiFi列表保存在内存中。
返回值:扫描到可用的网络数量
(WiFi.encryptionType(i) == WIFI_AUTH_OPEN
此函数定义在WiFiScan库
函数定义:通过此函数,我们可以获取扫描到的WiFi网络信息中的网络加密类型。
参数为扫描到的wifi的序列号
返回值:返回的wifi加密类型
WiFi.SSID(i)
此函数定义在WiFiScan库
函数定义:获取扫描到的WiFi网络信息中的网络名称(SSID)信息。
返回:扫描到的WiFi网络信息中的网络名称(SSID)信息(类型:String)
handleRoot()处理网站根目录的访问请求
/** 处理网站根目录的访问请求*/
void 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>"); }
}
server.hasArg("selectSSID")
此函数定义在WebServer库中
函数定义:可以获取客户端向ESP32物联网服务器发送的请求信息中有无指定的参数。
传入参数:需要确认的请求体中的参数名
返回值:是否存在指定参数
server.send(200, "text/html", ROOT_HTML + scanNetworksID + "</body></html>"); //这里拆开是为了添加上wifi目录
此函数定义在WebServer库中
函数定义:如果有客户端向ESP8266服务器发送HTTP请求,ESP8266服务器可使用本函数向客户端发送响应信息。
参数:响应状态码,响应内容类型,响应内容
handleConfigWifi() //提交数据后的提示页面
/** 提交数据后的提示页面*/
void handleConfigWifi() //返回http状态
{if (server.hasArg("ssid")) //判断是否有账号参数{Serial.print("got ssid:");wifi_ssid = server.arg("ssid"); //获取html表单输入框name名为"ssid"的内容Serial.println(wifi_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:");wifi_pass = server.arg("pass"); //获取html表单输入框name名为"pwd"的内容Serial.println(wifi_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'>SSID:" + wifi_ssid + "<br />password:" + wifi_pass + "<br />已取得WiFi信息,正在尝试连接,请手动关闭此页面。"); //返回保存成功页面delay(2000);WiFi.softAPdisconnect(true); //参数设置为true,设备将直接关闭接入点模式,即关闭设备所建立的WiFi网络。server.close(); //关闭web服务WiFi.softAPdisconnect(); //在不输入参数的情况下调用该函数,将关闭接入点模式,并将当前配置的AP热点网络名和密码设置为空值.Serial.println("WiFi Connect SSID:" + wifi_ssid + " PASS:" + wifi_pass);if (WiFi.status() != WL_CONNECTED) //wifi没有连接成功{Serial.println("开始调用连接函数connectToWiFi()..");connectToWiFi(connectTimeOut_s);} else {Serial.println("提交的配置信息自动连接成功..");}
}
读输入的参数,写入wifi账号密码。
wifi_ssid = server.arg("ssid"); //获取html表单输入框name名为"ssid"的内容
此函数定义在WebServer库中
函数定义:获取客户端向ESP8266物联网服务器发送的指定参数的数值。
参数:请求体中的参数名(参数类型: String)
返回值:指定参数的数值(类型:String)
WiFi.softAPdisconnect(true); //参数设置为true,设备将直接关闭接入点模式,即关闭设备所建立的WiFi网络。
此函数定义在WiFiAP库
函数定义:可用于关闭开发板的接入点模式,即关闭开发板所建立的WiFi网络。
传入参数:
参数类型为bool。如果将该参数设置为true,设备将直接关闭接入点模式。
在不输入参数的情况下调用该函数,设备会将当前配置的网络名和密码设置为空值。
返回值:返回设置是否成功的结果。设置成功返回true。数据类型为bool型。
server.close(); //关闭web服务
此函数定义在WebServer库
函数定义:本函数用于停止ESP32开发板所建立的网络服务器。
handleNotFound() //当浏览器请求的网络资源无法在服务器找到时通过此自定义函数处理
/** 处理404情况的函数'handleNotFound'*/
void handleNotFound() { // 当浏览器请求的网络资源无法在服务器找到时通过此自定义函数处理handleRoot(); //访问不存在目录则返回配置页面// server.send(404, "text/plain", "404: Not found");
}
restoreWiFi() //删除保存的wifi信息
/** 删除保存的wifi信息,这里的删除是删除存储在flash的信息。删除后wifi读不到上次连接的记录,需重新配网*/
void restoreWiFi() {delay(500);esp_wifi_restore(); //删除保存的wifi信息Serial.println("连接信息已清空,准备重启设备..");delay(10);blinkLED(LED, 5, 500); //LED闪烁5次 //关于LED,不需要可删除 digitalWrite(LED, LOW); //关于LED,不需要可删除
}
#include <esp_wifi.h> //用于esp_wifi_restore() 删除保存的wifi信息esp_wifi_restore(); //删除保存的wifi信息
checkConnect(bool reConnect) //检测wifi是否连接
/** 检查wifi是否已经连接*/
void checkConnect(bool reConnect)
{if (WiFi.status() != WL_CONNECTED) //wifi连接失败{if (digitalRead(LED) != LOW) digitalWrite(LED, LOW);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...");connectToWiFi(connectTimeOut_s); //连接wifi函数 }} else if (digitalRead(LED) != HIGH) digitalWrite(LED, HIGH); //wifi连接成功
}
里面包含的函数上面都说过了。
checkDNS_HTTP() //检测客户端DNS&HTTP请求
/** 检测客户端DNS&HTTP请求*/
void checkDNS_HTTP()
{dnsServer.processNextRequest(); //检查客户端DNS请求server.handleClient(); //检查客户端(浏览器)http请求
}
要放在loop函数中,检测http和dns消息。然后 server.on 函数定义的回调函数。
LED函数
/** LED闪烁函数 //用不上LED可删除*/
void blinkLED(int led, int n, int t)
{for (int i = 0; i < 2 * n; i++) {digitalWrite(led, !digitalRead(led));delay(t);}
}/** LED初始化*/
void LEDinit()
{pinMode(LED, OUTPUT); //配置LED口为输出口digitalWrite(LED, LOW); //初始灯灭
}
这一部分没啥好说的了吧 ~
呼 ~ 累死我了!!
终于写完了,不怕以后忘记了!!!哈哈哈哈哈哈
如果你看到这里了,觉得本文对你有帮助,那就帮我 点~点~关~注~
哈哈哈哈 ~ 开心吗 ~ 学习到小知识真的很开心呢~
加油鸭!!!!!!!!
【2023年3月3日】更新:
有人问到WebServer的库没有找到,现在附上库的链接:
arduino-esp32/libraries/WebServer at master · espressif/arduino-esp32 · GitHubArduino core for the ESP32. Contribute to espressif/arduino-esp32 development by creating an account on GitHub.https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer