2338浏览
查看: 2338|回复: 5

[ESP8266/ESP32] 超便利!教你用ESP32开发板DIY掌上网页服务器!

[复制链接]
本帖最后由 铁熊 于 2022-1-23 10:21 编辑

qw1.jpg


本文作者:默。默是铁熊的创客好友,经常与铁熊分享创意项目。


qw2.jpg

前段时间有个老师对我说:每到开学季,学校就要印刷学生的录取名单并进行张贴,为此学校每年都要耗费大量的人力物力。学校里面教学活动很多,传统的通知都是通过张贴海报之类的方式进行公布,但是在信息化高速发展的今天,许多消息的发布已经不需要传统的纸质媒介了,我们可以通过网站在线查询。然而一个网站的开发是十分复杂的,涉及到的知识很多,大部分人不可能有这么多的时间和精力去学习网站开发。

考虑到这些难点,结合我与那位老师交流以及解决该问题的过程,本教程将教你利用 ESP32 开发板搭建一个实用的网络服务器。该方案利用 ESP32 开发板托管网页,通过数据库查询信息,然后通过网页进行显示。同时也可以对网页进行可视化编辑,让没有任何基础的人都能够轻松地设计一个实用网页 ,而你需要做的仅仅是提供你要呈现的数据 。

下面让我们先来看看这个项目的演示视频,该演示项目中我们托管了4个不同服务的网页:


# M5 Server X名称的由来


M5 是指基于 ESP32 的 M5 Core2 开发板,Server 代表它是一个网络服务器,而 X 代表了无限可能,故名 M5 Server X,运用 M5 Server X 我们能够将任何数据或者服务通过网页的形式呈现,而无需任何前端或者后端开发的知识。

# 预期目标及功能


  • 通过访问 ESP32 的 IP 地址查看网页;
  • 设置自定义域名访问;
  • 服务后台管理功能;
  • 可视化网页修改;
  • 数据库数据处理;
  • SD 卡配置文件加载。

# 所用硬件

  • M5 Core2

qw3.jpg

# M5 Core2 特点
  • 基于 ESP32 开发,支持 WiFi、蓝牙;
  • 16M 闪存,8M PSRAM;
  • 内置扬声器,电源指示灯,震动马达,RTC,I2S 功放,电容式触摸屏,电源键,复位键;
  • TF 卡插槽(支持最大 16GB);
  • 内置锂电池,配备电源管理芯片;
  • 独立小板内置 6 轴 IMU,PDM 麦克风;
  • M-Bus 总线插座。

# 程序设计

下面开始详细讲解程序设计过程。

## 开发环境


我们使用 Arduino IDE 软件来编写本项目的程序,开发板选择 M5Stack-Core2。至于如何在 Arduino 中配置 ESP32 的开发环境,不在本文的介绍范围,请自行查阅相关资料。

## 程序思路


为了达到我们的预期目标,我们先绘制功能的思维导图,再根据思维导图逐步实现 M5 Server X 的程序设计。

qw4.jpg

下面我们来具体讨论 M5 Server X 各个子功能是如何实现的。

## 如何显示网页


我们想要访问一个网页必须要知道网络的路径,那么 M5 Server X 如何获取我们访问的路径参数,以及发送对应的网页呈现给我们呢,下面是一个简单的例子,我们上传该程序 。

  1. #include <WiFi.h>
  2. #include <WebServer.h> //引入相应库
  3. const char *ssid = "********";
  4. const char *password = "********";
  5. WebServer server(80); //声明WebServer对象
  6. void handleArg1() //回调函数
  7. {
  8.   String arg = server.pathArg(0);
  9.   server.send(200, "text/plain", "This is the link/{},The parameters are:" + arg);
  10. }
  11. void handleArg2() //回调函数
  12. {
  13.   String arg0 = server.pathArg(0);
  14.   String arg1 = server.pathArg(1);
  15.   server.send(200, "text/plain", "This is the link/{}/{},The parameters are:" + arg0 + " & " + arg1);
  16. }
  17. void setup() {
  18.   Serial.begin(115200);
  19.   Serial.println();
  20.   WiFi.mode(WIFI_STA);
  21.   WiFi.setSleep(false);
  22.   WiFi.begin(ssid, password);
  23.   while (WiFi.status() != WL_CONNECTED)
  24.   {
  25.     delay(500);
  26.     Serial.print(".");
  27.   }
  28.   Serial.println("Connected");
  29.   Serial.print("IP Address:");
  30.   Serial.println(WiFi.localIP());
  31.   server.on("/{}", handleArg1);        //注册链接与回调函数
  32.   server.on("/{}/{}", handleArg2); //注册链接与回调函数
  33.   server.begin(); //启动服务器
  34.   Serial.println("Web server started");
  35. }
  36. void loop() {
  37.   server.handleClient(); //处理来自客户端的请求
  38. }
复制代码


上传完程序,打开串口监视器。如下图所示,我们观察到路由器给 M5 Core2 分配的 IP 地址是 192.168.1.28,记住该地址。

qw5.jpg

我们通过浏览器访问:192.168.1.28/arduino/png,发现浏览器返回数据如下:

qw6.jpg

‍‍‍‍‍‍在这里我们有两个路径参数,分别是 arduino 与 png,你也可以试一下只有一个路径参数的情况 。在这个例子当中,我们路径参数以文本的形式给我们呈现,那么如何访问某一个特定的路径发送一个HTML文件呢,在这里只需要判断的路径参数是否是我们定义的路径就行了,例子如下:‍‍‍‍‍‍

  1. const char HTML1[] PROGMEM = R"rawliteral(
  2. //HTML源代码
  3. )rawliteral";
  4. const char HTML2[] PROGMEM = R"rawliteral(
  5. //HTML源代码
  6. )rawliteral";
  7. const char HTML3[] PROGMEM = R"rawliteral(
  8. //HTML源代码
  9. )rawliteral";
  10. void handleArg1() //回调函数
  11. {
  12.   String arg = server.pathArg(0);
  13.   if (String(arg).equals(String(""))) {
  14.     // 访问路径为空(根目录)
  15.     server.send(200, "text/html", HTML1);
  16.   } else if (String(arg).equals(String("m5"))) {
  17.     // 自定义路径"m5"
  18.     server.send(200, "text/html", HTML2);
  19.   } else {
  20.     // 无效路径(未定义)
  21.     server.send(200, "text/html", HTML3);
  22.   }
  23. }
复制代码


在这个例子中,我们考虑了3种路径情况,分别是访问路径为空(根目录),自定义路径(m5)与无效路径(未定义)。当我们访问对应的路径时,M5 Server X 能够给浏览器返回的不同的 html 文本,浏览器将自动渲染该页面。

我们将网页内容定义在 HTML 字符串中。如何设计网页内容呢?我们可以在浏览器中访问一个喜欢的网页,然后点击鼠标右键选择“查看页面源代码”就能看到该网页的源代码,将页面源代码复制并替换到程序中注释的地方,同时将原 HTML 文件的资源引用的相对路径改为绝对路径,这样我们便能够得到由 M5 Server X 托管的网页。对于二级路径的情况也和一级路径类似,我们通过不同的层级路径就可以使用一个 M5 Core2 托管许多不同类型的网页。

这里推荐几个实用的网页模板网站:

其中 17 素材网拥有大量的 html 网页特效、网站模板、素材等。提供在线预览功能,我们可以很方便的找到心仪的网页模板;highcharts 图表网拥有丰富的交互式图表,例如带交互特效的折线图、面积图、柱形图、散点图等,能够让我们以动态的方式直观地观察数据变换情况,是数据分析的不二选择。

## 如何可视化修改网页
通过查看网页源代码的方式,我们已经获取到了网页的模板,但是我们并没有 Web 开发的任何基础,似乎无从下手呀?有没有一种可视化、所见即所得的方式让我们修改网页呢?答案是肯定的,这里我介绍3个可视化网页修改的编辑器。

其中菜鸟教程在线 HTML 编辑器与 W3School 网页编辑器均可以实时修改网页源代码并预览其各种网页特效,HTML 编辑器能够像 Word 一样编辑 HTML,十分便利,唯一的缺点就是不能渲染动态的 js 特效,适合静态网页的可视化修改。下面以 W3School 网页编辑器为例,简述如何获得网页模板并进行可视化编辑。

qw7.jpg

qw8.jpg

  • 通过 17 素材网查询关键词寻找合适的网页素材(例如我们需要一个登陆页面);
  • 选择需要的网页素材;
  • 点击查看预览效果;
  • 右键单击,选择查看网页源代码并全选复制(所有网页均可使用此方法);
  • 粘贴网页源代码到 W3School 网页编辑器,点击运行代码(网页未正确渲染);
  • 将网页引用样式资源由相对路径修改为绝对路径(修改后网页成功渲染);
  • 观察网页显示文字,在网页源代码中查找并替换对应的字符串,修改完成后重新运行代码;
  • 增加调试代码,使用网页弹窗调试页面(目的是获取表单构造URL)。

M5 Server X 使用的要点是网页样式文件 CSS,JS 和多媒体等文件均放在云端,通过绝对路径的方式进行引用,这样做的目的是 M5 Server X 只需要少量的带宽也能流畅的使用。如何获取输入表单字符串网上有很多教程,这里不再赘述,这里介绍几个实用的网页调试函数:
  • window.location.href(获取当前URL路径)
  • window.location(跳转到指定URL)
  • alert()(网页弹窗)

## 获取数据库数据



现在我们能够可视化的修改任意网页,如果我们要获取的是一个动态网页呢?例如学生成绩单中,表格的模板是固定的,而变化的仅是姓名分数等信息。对于这种通用模板,变化的数据我们可以通过占位符来表示该数据,例如下图中的 data 占位符:

qw9.jpg

表中的 data0 ~ data9 都是数据变量 ,我们可以采取键值对的形式,将数据保存到云端或者本地的数据库当中。这里我们采取学号作为标签来保存这些数据,例如000 000,张三,男,六一班,90,80,90,90,90,100其中000作为标签,而000,张三,男,六一班,90,80,90,90,90,100作为值 data0 ~ data9,分别代表了标签值中的具体数据,将上面的表格进行文本替换后得到下面的表格:

qw10.jpg

这里推荐一个支持批量数据提交的网络数据库 tinywebdb(http://tinywebdb.appinventor.space/)。至于它是什么,这里不赘述,大家可以百度搜索,这里仅介绍如何获取该数据库的标签值。我们注册 tinywebdb 账号并登录后可以看到它提供的 API 接口文档如下:

qw11.jpg

我们先通过它的数据导入功能导入一条数据:

qw12.jpg

通过数据浏览功能查看刚导入的数据:

qw13.jpg

我们根据 tinywebdb 的 API 文档编写一个程序获取数据库的数据:

  1. #include <WiFi.h>
  2. #include <HTTPClient.h>
  3. const char *ssid = "********";
  4. const char *password = "********";
  5. String User = "share"; //数据库用户账号名
  6. String Secret = "everyone"; //数据库用户密钥
  7. String tag = "000"; //标签
  8. void setup() {
  9. Serial.begin(115200);
  10. Serial.println();
  11. WiFi.mode(WIFI_STA);
  12. WiFi.setSleep(false);
  13. WiFi.begin(ssid, password);
  14.   
  15. while (WiFi.status() != WL_CONNECTED) {
  16.    delay(500);
  17.    Serial.print(".");
  18. }
  19. Serial.println("Connected");
  20. Serial.print("IP Address:");
  21. Serial.println(WiFi.localIP());
  22.   
  23. if (WiFi.status() == WL_CONNECTED) {
  24.    HTTPClient http;
  25.    http.begin(String("http://tinywebdb.appinventor.space/api?user=" + User + "&secret=" + Secret + "&action=get&tag=") + String(tag));
  26.    int httpCode = http.GET();
  27.    if (httpCode > 0) {
  28.      String Request_result = http.getString();
  29.      Serial.println(Request_result);
  30.    } else {
  31.      Serial.println("Invalid response!");
  32.    }
  33.    http.end();
  34. }
  35. }
  36. void loop() {
  37. }
复制代码


打开串口监视器,返回数据如下,当访问有效标签时,返回我们保存的正确数据,当访问未定义的标签时返回 null,我们能都通过判断该值知道我们是否输入正确网页地址,从而返回不同的网页。

qw14.jpg

## 数据解析

通过 API 返回数据后,我们需要解析该 JSON 字符串。解析程序如下,这里我们需要引用ArduinoJson.h这个 JSON 字符串解析库。

  1.   StaticJsonDocument<64> doc;
  2.   DeserializationError error = deserializeJson(doc, Request_result);
  3.   if (error) {
  4.     Serial.print("deserializeJson() failed: ");
  5.     Serial.println(error.c_str());
  6.     return;
  7.   }
  8.   const char* root_000 = doc["000"]; // "000,张三,男,六一班,90,80,90,90,90,100"
复制代码


得到解析的数据后,再将该数据构造为 json 数组,对构造后的数据进行二次解析便能获取数组的每一项,将数组的每一项数据替换占位符 data 便能得到呈现的有效 html 文件,具体代码见附录程序。

## 域名解析
我们可以通过串口监视器获取设备的 IP 地址进行访问,但是路由器的分配的 IP 地址是变化的,这点很不方便,那么我们能不能给它设置一个好记的域名,让我们局域网内访问该设备呢?这里可以使用 ESPmDNS 域名解析达到该目的。代码如下:

  1. #include <ESPmDNS.h>
  2. void setup() {
  3.   Serial.begin(115200);
  4.   if (!MDNS.begin("M5Core2")) {//自定义域名
  5.     Serial.println("Error setting up MDNS responder!");
  6.   }
  7.   MDNS.addService("http", "tcp", 80); //启用DNS服务
  8. }
  9. void loop() {
  10. }
复制代码

通过域名解析,我们只要和设备在同一局域网内,访问 http://m5core2 就能访问 M5 Server X 获取相应的网页服务了。

## 读取 SD 卡文件
通过前面的讲解,我们已经能够实现访问一个链接并跳转到某一个网页了。那么问题来了,如何快速修改网页呢?因为 M5core2 可以使用 SD 卡,所以我们可以这样做:将网页和账号信息保存到 SD 当中,需要更改网页或者连接网络等信息时,直接修改SD卡中的文件,设备初始化的时候读取 SD 卡,那么就完成了网页的修改,这比我们直接修改程序要简单便捷多了。读取 SD 卡文件的程序如下:

  1. #include "FS.h"
  2. #include <SD.h>
  3. #include <SD_MMC.h>
  4. SPIClass sdSPI(VSPI); //定义SD卡软SPI管脚
  5. #define SD_MISO     38
  6. #define SD_MOSI     23
  7. #define SD_SCLK     18
  8. #define SD_CS       4
  9. String readFile(fs::FS &fs, const char * path) { //读取SD卡指定路径文件
  10.   File file = fs.open(path);
  11.   if (!file) {
  12.     Serial.println("Failed to open file for reading");
  13.   }
  14.   String data = "";
  15.   while (file.available()) {
  16.     data = String(data) + String(char(file.read()));
  17.   }
  18.   file.close();
  19.   return data;
  20. }
  21. void setup() {
  22.   Serial.begin(115200);
  23.   sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS); //初始化SD卡SPI
  24.   if (!SD.begin(SD_CS, sdSPI)) {
  25.     Serial.println("Card Mount Failed");
  26.     return;
  27.   }
  28.   Serial.println(readFile(SD, "/admin.txt"));
  29. }
  30. void loop() {
  31. }
复制代码


在程序中我们可以直接输入 TXT 或者 HTML 文件的路径,便可读取该文件中的内容。这里我们读取了 SD 卡根目录下的 admin.txt 文件,该文件作为配置文件用来保存网络信息、数据库信息与服务信息,该文件内容如下,不存在的服务用 null 表示:

  1. {
  2.   "ssid": "ChinaNet-5678",//连接WiFi名称
  3.   "password": "1234567890",//连接WiFi密码
  4.   "user": "peien",//数据库账号名
  5.   "secret": "52e2c018",//数据库密钥
  6.   "admin": "12345678",//管理密码
  7.   "server1": "score",//服务1
  8.   "server2": "arduino",//服务2
  9.   "server3": "Login",//服务3
  10.   "server4": "Light"//服务4
  11. }
复制代码



## M5 Server X 网页逻辑
M5 Server X 服务框架如下:

qw15.jpg

M5 Server X 通过域名或 IP 加服务名访问不同服务主页,例如 http://m5core2/score/000,其中 m5core2 为域名或者 IP,score 为服务名,000 为查询参数,数据库通过键值对存储数据,为了确保数据标签的唯一性,我们采取服务加参数的形式代表某个具体数据。如成绩查询服务当中,000 为实际的学号,那我们就将数据标签设置为 score_000,使用下划线增加标签的可读性,如果我们需要登录账号和密码那就将账号和密码构造为一个标签。例如演示视频案例四当中,我们就将账号和密码作为服务参数进行传递输入,当输入账号 peien、密码 123 时,数据标签被构造为 Login_peien_123。

## 服务响应逻辑
M5 Server X 服务响应的逻辑如下,访问根目录返回 Home_page.html 页面,该页面我们默认为代码雨,实际你可以设置为所有服务的导航页面,通过标签或者按钮跳转到子服务页面。Log_in.html 为某个子服务的服务主页,当服务开启时有两种情况,当提交参数正确时,通过 replace 函数查找占位符并替换数据,返回 success.html 页面,当提交参数错误时,返回 mistake.html(404)页面,当我们禁用某项服务时,无论提交参数是否正确,都会返回 Not_open.html(服务未开放或者无此服务)页面。

qw16.jpg

## 配置文件结构

配置文件下有七个文件,其中 admin.txt、Home_page.html、Not_open.html 为公共文件,不同子服务用不同文件夹(英文文件夹名)区分。每个子服务文件夹下均有 Log_in.html、success.html、mistake.html 三个 HTML 文件。示意图如下,其中子服务文件夹非必需,是否启用该服务由 admin.txt 配置决定。对于没有的服务用 null 表示,当服务名为 null 时设备初始化将跳过该服务不加载该服务文件  。

qw17.jpg

## 后台控制面板

M5 Server X 的后台功能主要有登录、服务器管理与设备信息查询,其中如何绘制控制页面与触摸屏的使用在往期《DIY掌上POS机,或许是最小的收银POS机了!》这篇教程中有详细的描述,这里就不再赘述。

# 试玩
以上就是 M5 Server X 的项目介绍,如果你不想下载 IDE 只想体验该项目,那么你可以访问 https://docs.m5stack.com/zh_CN/download 根据你自己的系统下载 M5Burner 烧录工具进行安装,打开软件按照下面的步骤进行烧录体验,其中 SD 卡网页模板与配置文件请通过本教程附件进行下载,直接解压到的 SD 卡修改网络信息即可体验。

qw18.jpg

## 使用说明
  • 烧录固件;
  • 将附件提供的模板解压到 SD 卡;
  • 打开 admin.txt 文件修改网络信息;
  • SD 卡插入 M5Core2 并重启设备;
  • 等待 M5Core2 初始化并进入控制主页;
  • 按演示视频控制设备与查看服务器管理与账号信息显示页面;
  • 访问 http://m5core2/ 进入代码雨主页;
  • 访问 http://m5core2/score 查看学生成绩(学号为000);
  • 访问 http://m5core2/arduino 通过关键词m5core2进行搜索;
  • 访问 http://m5core2/Login 查看学生成绩(用户名peien密码123);
  • 访问 http://m5core2/Light 控制灯泡(开关分别代表了两个URL,自行修改为自己的接口);
  • 分别输入正确信息与错误信息,启用服务与禁用服务,体验 M5 Server X。

# 总结

有了上面的理论基础,我们便能完成 M5 Server X 的项目制作了,其中具体实现细节由于篇幅限制,这里就不再讨论,大家可以下载程序源代码进行查看,其中必要的程序说明已经注释,对此项目有任何建议或者疑问均可评论区留言。

使用 M5 Server X 你能够轻松打造自己的个人网站,当然你也可以使用普通 ESP32 完成此项目,但可能相对麻烦些,但这样一个 10 多块钱的个人服务器还有什么可嫌弃的呢。如果你想给别人分享你的网页服务,可以使用内网穿透服务,这个大家就自行百度了,在上面的思维导图当中我们提供了本项目用到的网页素材网、可视化编辑平台、自建数据库等链接,大家可以下载附件进行查阅学习。

我是默,我们下期见。

# 代码下载
关注公众号“铁熊玩创客”,回复“ M5 Server X ”获取完整代码。

微信二维码引导2.png







hnyzcj  版主

发表于 2022-1-23 13:09:51

点赞一个
回复

使用道具 举报

赤星三春牛!  中级技匠

发表于 2022-1-27 11:30:22

铁熊厉害,点赞!
回复

使用道具 举报

QQQQQQQ  高级技师

发表于 2022-2-14 17:17:11

厉害,点赞!
回复

使用道具 举报

QQQQQQQ  高级技师

发表于 2022-3-13 13:03:01

M5 Core2多贵?
回复

使用道具 举报

QQQQQQQ  高级技师

发表于 2022-3-13 13:43:12

666666666666666666666
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2022 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail