赞
踩
前文中已经详细地介绍了用LittleFS保存设置和从LittleFS读取设置所用到的函数和方法:
https://blog.csdn.net/m0_50114967/article/details/126976629
因为这个WEB服务器功能越来越多,所有代码都在同一个文件,可读性也会变得越来越差,这里先介绍一下arduino IDE的多文件管理功能。
arduino IDE保留了和C语言一样的引入.h头文件的功能,但也有自已独特的多文件管理功能。
引入头文件的方法
我们先新建一个用于测试的.h头文件,test.h
文件的内容为
- void hardware_begin(){
- Serial.begin(9600);
- }
里面包含一个hardware_begin函数,下面在主文件中引用
- #include "test.h"
- void setup() {
- // put your setup code here, to run once:
- hardware_begin();
- Serial.print("abcd");
- }
-
- void loop() {
- // put your main code here, to run repeatedly:
-
- }
无需引入头文件的方法
这是arduino IDE特有的多文件管理,用相同的方法,新建一个文件,无需输入扩展名或输入.ino扩展名。
或
内容和之前的test.h文件一样:
- void hardware_begin(){
- Serial.begin(9600);
- }
在引用时,无需引入该头件就可以直接调用test.ino文件里的函数
- //#include "test.h" 无需引入头文件
- void setup() {
- // put your setup code here, to run once:
- hardware_begin();
- Serial.print("abcd");
- }
-
- void loop() {
- // put your main code here, to run repeatedly:
-
- }
其原理就是在编译时会把项目文夹下的所有ino文件合并编译,基本上不用担心文件名。
在测试中,把setup和loop分开放在不同的文件中也是可以的。对比引入头文件,显然后面的方法比较方便。
现在我们可以把之前所实现的功能做一些分类整理,把各种类型的函数分别放到不同的文件中。
第一个文件用来保存配网所需要的函数:
- /*WIFI连接*/
- #include <WiFi.h>
- #include <DNSServer.h>
-
-
- DNSServer dnsserver;
-
-
- /***********************************************************************************
- * 函数:连接WIFI
- * ssid: WIFI名称
- * password: WIFI密码
- * return: 连接成功返回true
- ***********************************************************************************/
- void connect_WIFI(String ssid, String password){
- WiFi.begin(ssid.c_str(), password.c_str()); //连接WIFI
- Serial.print("连接WIFI");
- //循环,10秒后连接不上跳出循环
- int i = 0;
- while(WiFi.status() != WL_CONNECTED){
- Serial.print(".");
- delay(500);
- i++;
- if(i>20){
- Serial.println();
- Serial.println("WIFI连接失败");
- return;
- }
- }
- Serial.println();
- IPAddress local_IP = WiFi.localIP();
- Serial.print("WIFI连接成功,本地IP地址:"); //连接成功提示
- Serial.println(local_IP);
- }
-
-
- /***********************************************************************************
- * 设置AP和STA共存模式,设置DNS服务器
- ***********************************************************************************/
- void connect_NET(){
- const byte DNS_PORT = 53; //DNS端口
- const String url = "ESPAP.com"; //域名
- IPAddress APIp(10,0,10,1); //AP IP
- IPAddress APGateway(10,0,10,1); //AP网关
- IPAddress APSubnetMask(255,255,255,0); //AP子网掩码
- const char* APSsid = "esp32_AP"; //AP SSID
- const char* APPassword = "12345678"; //AP wifi密码
- wifi_connect(); //连接WIFI
- WiFi.mode(WIFI_AP_STA); //打开AP和STA共存模式
- WiFi.softAPConfig(APIp, APGateway, APSubnetMask); //设置AP的IP地址,网关和子网掩码
- WiFi.softAP(APSsid, APPassword, 6); //设置AP模式的登陆名和密码
- dnsserver.start(DNS_PORT, url, APIp); //设置DNS的端口、网址、和IP
- Serial.print("AP模式IP地址为:");
- Serial.println(WiFi.softAPIP());
- }
-
-
- /***********************************************************************************
- * DNS处理请求的循环
- ***********************************************************************************/
- void DNS_request_loop(){
- dnsserver.processNextRequest();
- }
第二个文件用来保存WEB所需要的函数,包含了读写文件函数,JSON格式解析或创建函数
- #include "ESPAsyncWebServer.h"
- #include <ArduinoJson.h>
- #include <LittleFS.h>
-
- //AsyncWebServer server(80); //创建一个服务器对象,WEB服务器端口:80
-
-
- /**************************************************************************************
- * 函数:字符串写入文件,文件如果存在,将被清零并新建,文件不存在,将新建该文件
- * path: 文件的绝对路径
- * str: 要写入的字符串
- *************************************************************************************/
- void str_write(String path, String str){
- Serial.println("写入文件");
- File wf = LittleFS.open(path,"w"); //以写入模式打开文件
- if(!wf){ //如果无法打开文件
- Serial.println("打开文件写入时错误"); //显示错误信息
- return; //无法打开文件直接返回
- }
- wf.print(str); //字符串写入文件
- wf.close(); //关闭文件
- File rf = LittleFS.open(path,"r"); //以读取模式打开文件
- Serial.print("FILE:");Serial.println(rf.readString()); //读取文件
- rf.close(); //关闭文件
- }
-
-
- /**********************************************************************************
- * 函数:响应网站/setwifi目录的POST请求,收到请求后,运行get_WIFI_set_CALLback回调函数
- * 获取并格式化收到的POST数据
- *********************************************************************************/
- void get_WIFI_set_CALLback(AsyncWebServerRequest *request){
- Serial.println("收到设置WIFI按钮");
- if(request->hasParam("wifiname",true)){
- AsyncWebParameter* wifiname = request->getParam("wifiname",true); //获取POST数据
- AsyncWebParameter* wifipassword = request->getParam("wifipassword",true); //获取POST数据
- String wn = wifiname->name().c_str();
- String wnv = wifiname->value().c_str();
- String wp = wifipassword->name().c_str();
- String wpv = wifipassword->value().c_str();
- //把SSID和password写成一个JSON格式
- StaticJsonDocument<200> wifi_json; //创建一个JSON对象,wifi_json
- wifi_json[wn] = wnv; //写入一个建和值
- wifi_json[wp] = wpv; //写入一个键和值
- String wifi_json_str; //定义一个字符串变量
- serializeJson(wifi_json, wifi_json_str); //生成JOSN的字符串
- str_write("/WIFIConfig.conf",wifi_json_str); //字符串写入
- }
- }
-
-
- /**********************************************************************************
- * 函数:从文件path中读取字符串
- * path: 文件的绝对路径
- * return: 返回读取的字符串
- *********************************************************************************/
- String str_read(String path){
- Serial.println("读取文件");
- File rf = LittleFS.open(path,"r"); //以读取模式打开文件
- if(!rf){ //如果无法打开文件
- Serial.println("打开文件读取时错误"); //显示错误信息
- return ""; //无法打开文件直接返回
- }
- String str = rf.readString(); //读取字符串
- rf.close(); //关闭文件
- return str;
- }
-
-
- /***************************************************************************************
- * 函数:解析JSON字符串,从JSON字符串名称得到该值
- * str: JSON字符串
- * Name: JSON集合的名称
- * return: 返回值的字符串
- ***************************************************************************************/
- String analysis_json(String str, String Name){
- DynamicJsonDocument doc(str.length()*2); //定义一个JSON对象
- deserializeJson(doc, str); //反序列数据
- String value = doc[Name].as<String>(); //从Name中读取对应的值
- return value;
- }
-
-
- /***********************************************************************************
- * 函数:/WIFIConfig.conf文件中读取设置数据并连接WIFI
- ***********************************************************************************/
- void wifi_connect(){
- Serial.println("在conf文件中读取数据并连接WIFI");
- String str = str_read("/WIFIConfig.conf"); //读取文件内容
- String wifiname = analysis_json(str, "wifiname"); //解析WIFI名称
- String wifipassword = analysis_json(str, "wifipassword"); //解析WIFI密码
- connect_WIFI(wifiname, wifipassword); //连接WIFI
- }
-
-
- /***********************************************************************************
- * web服务器初始化
- ***********************************************************************************/
- void web_server(){
- Serial.println("初始化WEB服务器");
- server.serveStatic("/", LittleFS, "/").setDefaultFile("index.html"); //响应网站根目录的GET请求,返回文件index.html
- server.on("/setwifi" ,HTTP_POST , get_WIFI_set_CALLback); //响应设置WIFI按钮的请求
- server.begin(); //初始化
- }
-
-
- /********************************************************************************
- * LittleFS文件系统初始化
- *********************************************************************************/
- void LittleFS_begin(){
- Serial.println();
- Serial.println("初始化文件系统");
- if(!LittleFS.begin(true)){
- Serial.println("An Error has occurred while mounting LittleFS");
- return;
- }
- }
第三个文件就是主文件,包括了ESPAsyncWebServer库的全局服务器变量和setup和loop两个接口
- #include "ESPAsyncWebServer.h"
- AsyncWebServer server(80); //创建一个服务器对象,WEB服务器端口:80
- void setup() {
- Serial.begin(9600); //串口波特率初始化
- LittleFS_begin(); //LittleFS文件系统初始化
- connect_NET(); //网络初始化
- web_server(); //WEB服务器初始化
- }
-
- void loop() {
- DNS_request_loop(); //DNS服务请求处理
- }
最后是网页的html代码:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <link rel="stylesheet" type="text/css" href="mystyle.css">
- <title>EPS32教程</title>
- </head>
- <body>
- <div id="pal">
- <form name="wifiset" onsubmit="return validateForm()" action="\setwifi" method="post" target="myframe">
- <label for="wifiname">WIFI SSID</label>
- <input name="wifiname" type="text" value="ESP32">
- <label for="wifipassward">WIFI PASSWARD</label>
- <input name="wifipassword" type="text" value="ESP32">
- <input type='submit' value='设置WIFI'>
- </form>
- <iframe src="" width="200" height="200" frameborder="0" name="myframe" style="display:NONE" ></iframe>
- </div>
- </body>
-
- <script>
- /******************************
- 表单验证,WIFI名称输入框为空时提示
- ******************************/
- function validateForm(){
- var wifiname=document.forms["wifiset"]["wifiname"].value; //得到name输入框的文字
- if (wifiname==null || wifiname==""){ //如果输入框为空
- alert("WIFI SSID必需输入"); //显示提示
- return false;
- }
- }
- </script>
- </html>
运行流程:
1、初始化LittleFS文件系统
2、连接WIFI,如果超时将跳过
3、设置AP模式和STA模式(如果WIFI已连接)
4、初始化服务器
5、如果未能连接WIFI,只能用手机或电脑通过AP模式WIFI直接连接ESP32
可以通过IP地址:10.0.10.1或域名espap.com用浏览器进入ESP32的WEB页面
设置WIFI名称和WIFI密码,点击设置,如果设置正确,下次启动就可以直接连接WIFI了
至此,一个可以通过WEB页面配置WIFI的WEB服务器就完成了,在下一章中,将会介绍ESP32的远程互动,介绍通过WEB页面控制ESP32和通过MQTT协议控制ESP32。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。