ESP32cam系列教程003:ESP32cam实现远程 HTTP_OTA 自动升级

chatgpt/2023/9/27 5:24:31

文章目录

  • 1.什么是 OTA
  • 2. ESP32cam HTTP_OTA 本地准备
    • 2.1 HTTP OTA 升级原理
    • 2.2 开发板本地基准程序(程序版本:1_0_0)
    • 2.3 开发板升级程序(程序版本:1_0_1)
    • 2.4 本地 HTTP_OTA 升级测试
      • 2.4.1 本地运行一个 HTTP 服务
      • 2.4.2 替换远程链接并将要升级的程序打包成 `.bin` 文件
      • 2.4.3 替换远程链接并烧录基准程序(版本为:1_0_0 的程序)测试升级是否成功
  • 3. HTTP_OTA 升级展望
    • 3.1 后期版本更新可通过 HTTP_OTA 实现
    • 3.2 借助网络云平台实现远程 HTTP_OTA 升级

本教程是 ESP32cam 的系列教程之三,使用 Arduino IDE 对 ESP32cam 开发板进行开发。
本教程代码同样使用与其他 ESP32 开发板。

1.什么是 OTA

OTA 即空中下载技术(Over-the-Air Technology),其可以安全方便地升级设备的固件或软件。远程升级还可以大大降低成本,节省资源,它已成为物联网设备和产品制造商的关键技术之一。

ESP32 开发板支持 3 种 OTA 方式:

  1. Arduino IDE :主要用于软件开发阶段,实现不接线固件烧录
  2. Web_OTA:通过 Web 浏览器手动提供应用程序更新模块
  3. HTTP_OTA:固件存放到 http 服务器端,设备自动判断是否需要联网下载固件升级

本文主要介绍:HTTP_OTA 的原理与实现。

2. ESP32cam HTTP_OTA 本地准备

2.1 HTTP OTA 升级原理

  1. 本地程序在开机连接 WIFI 后发送 http 请求获取远程服务器中的升级 json 文件。
  2. 通过对比 json 中的远程版本信息与本地的版本信息判断是否一致。
  3. 若远程版本信息与本地版本不一致,则本地需要更新程序。
  4. 通过 json 中的版本信息在远程服务器中拉取需要更新的程序的 .bin 文件。
  5. 依据下载下来的 .bin 自动完成版本的升级,然后自动重启开发板。
  6. 重复第一步获取远程 json 文件判断是否需要更新。

2.2 开发板本地基准程序(程序版本:1_0_0)

本地 1_0_0 版本程序主要内容如下:

  1. 当前版本(非常重要,升级依据)
  2. 远程升级的 json 链接与远程固件的文件夹链接
  3. 获取并解析 json 的函数 httpGETRequest
  4. 依据 json 判断是否需要更新的函数 isOrNotNeedUpdate
  5. 以及其他基础信息组成
#include <WiFi.h>#include <HTTPClient.h>
#include <ESP32httpUpdate.h>
#include <Arduino_JSON.h>/**********根据实际修改**********/
const char* wifi_ssid = "TP-LINK_1760";   // WIFI名称,区分大小写,不要写错
const char* wifi_password = "987654321";  // WIFI密码// 特别重要,升级依据!!!
// 设置当前代码版本 格式 1_0_0
char* version = "1_0_0";//远程固件链接,只支持http
const char* baseUpdateUrl = "http://example.cn/esp32/";
const char* updateJson = "http://example.cn/esp32/esp32_update.json";// esp32_update.json
// {
//     "version":"1_0_1"
// }/**********根据实际修改**********/int need_ota_update = 0;
int i = 0;
String jsonBuffer;// 获取远程 json 升级文件
String httpGETRequest(const char* serverName) {WiFiClient client;HTTPClient http;String payload = "";//连接目标网址http.begin(client, serverName);//发送HTTP站点请求int httpCode = http.GET();if (httpCode > 0) {Serial.printf("[HTTP] GET... code: %d\n", httpCode);payload = http.getString();} else {Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());}http.end();  //关闭连接//返回获得的数据用于Json处理return payload;
}// 依据json文件中版本号与本地版本号,判断是否需要进行更新
void isOrNotNeedUpdate(){// 获取远程的升级 json ,判断内部版本与本地是否相同,判断是否需要升级jsonBuffer = httpGETRequest(updateJson);Serial.println(jsonBuffer);//将解析的Json对象值储存在Jsonu缓冲区中JSONVar myObject = JSON.parse(jsonBuffer);Serial.println(myObject);// Serial.println(myObject["version"]);const char* ota_version = myObject["version"];// Serial.println(ota_version);Serial.println("---");Serial.print("远程版本: ");Serial.println(ota_version);Serial.print("本地版本: ");Serial.println(version);// char * 与 const char * 比较// 判断远程版本与本地版本是否相同if (String(version) == String(ota_version)) {need_ota_update = 0;Serial.println("无需升级。。。");} else {need_ota_update = 1;Serial.println("需要升级。。。");Serial.print("OTA 升级地址为:");// 升级的完整链接, 例如:http://example.cn/esp32/esp32_1_0_1.binString fullUpdateUrl = String(baseUpdateUrl) + "esp32_" + ota_version + ".bin";Serial.println(String(fullUpdateUrl));// 获取远程 bin 文件进行升级t_httpUpdate_return ret = ESPhttpUpdate.update(fullUpdateUrl);Serial.println(ret);switch (ret) {case HTTP_UPDATE_FAILED:Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());break;case HTTP_UPDATE_NO_UPDATES:Serial.println("HTTP_UPDATE_NO_UPDATES");break;case HTTP_UPDATE_OK:Serial.println("HTTP_UPDATE_OK");break;default:Serial.println(ret);}// version=(char *)ota_version;}need_ota_update = 0;
}void setup() {Serial.begin(115200);  //波特率115200Serial.print("Connection WIFI");WiFi.begin(wifi_ssid, wifi_password);    //连接wifiwhile (WiFi.status() != WL_CONNECTED) {  //等待连接wifidelay(500);Serial.print(".");}Serial.println("");// 调用判断是否需要升级函数isOrNotNeedUpdate();
}void loop() {
// 主程序Serial.println(i);i++;delay(2000);
}

2.3 开发板升级程序(程序版本:1_0_1)

本测试升级程序如下,仅仅在程序版本与主程序中做了调整,以便更清楚的看出是否OTA升级成功。

#include <WiFi.h>#include <HTTPClient.h>
#include <ESP32httpUpdate.h>
#include <Arduino_JSON.h>/**********根据实际修改**********/
const char* wifi_ssid = "TP-LINK_1760";   // WIFI名称,区分大小写,不要写错
const char* wifi_password = "987654321";  // WIFI密码// 特别重要,升级依据!!!
// 设置当前代码版本 格式 1_0_0
char* version = "1_0_1";//远程固件链接,只支持http
const char* baseUpdateUrl = "http://example.cn/esp32/";
const char* updateJson = "http://example.cn/esp32/esp32_update.json";// esp32_update.json
// {
//     "version":"1_0_1"
// }/**********根据实际修改**********/int need_ota_update = 0;
int i = 0;
String jsonBuffer;// 获取远程 json 升级文件
String httpGETRequest(const char* serverName) {WiFiClient client;HTTPClient http;String payload = "";//连接目标网址http.begin(client, serverName);//发送HTTP站点请求int httpCode = http.GET();if (httpCode > 0) {Serial.printf("[HTTP] GET... code: %d\n", httpCode);payload = http.getString();} else {Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());}http.end();  //关闭连接//返回获得的数据用于Json处理return payload;
}// 依据json文件中版本号与本地版本号,判断是否需要进行更新
void isOrNotNeedUpdate(){// 获取远程的升级 json ,判断内部版本与本地是否相同,判断是否需要升级jsonBuffer = httpGETRequest(updateJson);Serial.println(jsonBuffer);//将解析的Json对象值储存在Jsonu缓冲区中JSONVar myObject = JSON.parse(jsonBuffer);Serial.println(myObject);// Serial.println(myObject["version"]);const char* ota_version = myObject["version"];// Serial.println(ota_version);Serial.println("---");Serial.print("远程版本: ");Serial.println(ota_version);Serial.print("本地版本: ");Serial.println(version);// char * 与 const char * 比较// 判断远程版本与本地版本是否相同if (String(version) == String(ota_version)) {need_ota_update = 0;Serial.println("无需升级。。。");} else {need_ota_update = 1;Serial.println("需要升级。。。");Serial.print("OTA 升级地址为:");// 升级的完整链接, 例如:http://example.cn/esp32/esp32_1_0_1.binString fullUpdateUrl = String(baseUpdateUrl) + "esp32_" + ota_version + ".bin";Serial.println(String(fullUpdateUrl));// 获取远程 bin 文件进行升级t_httpUpdate_return ret = ESPhttpUpdate.update(fullUpdateUrl);Serial.println(ret);switch (ret) {case HTTP_UPDATE_FAILED:Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());break;case HTTP_UPDATE_NO_UPDATES:Serial.println("HTTP_UPDATE_NO_UPDATES");break;case HTTP_UPDATE_OK:Serial.println("HTTP_UPDATE_OK");break;default:Serial.println(ret);}// version=(char *)ota_version;}need_ota_update = 0;
}void setup() {Serial.begin(115200);  //波特率115200Serial.print("Connection WIFI");WiFi.begin(wifi_ssid, wifi_password);    //连接wifiwhile (WiFi.status() != WL_CONNECTED) {  //等待连接wifidelay(500);Serial.print(".");}Serial.println("");// 调用判断是否需要升级函数isOrNotNeedUpdate();
}void loop() {
// 主程序Serial.println(i);Serial.println("OTA 升级成功");i++;delay(2000);
}

2.4 本地 HTTP_OTA 升级测试

2.4.1 本地运行一个 HTTP 服务

这里使用 vscode 进行:

  1. 用 vscode 打开一个空白文件夹
  2. 在文件夹中新建目录 esp32,文件 index.html ,目录下新建文件 esp32_update.json
  3. esp32_update.json 中内容是 {"version":"1_0_1"} ,表明当前远程的版本为 1_0_1
  4. index.html 中为标准html结构文件
  5. index.html 界面中右键>Open with Live Server 打开

  1. 替换 127.0.0.1 为本地 192.168.1.XXX 并拼接 /esp32/esp32_update.json ,如下图所示

2.4.2 替换远程链接并将要升级的程序打包成 .bin 文件

  1. 将 arduino IDE 中的程序的远程链接替换成本地 HTTP 服务器链接

  2. 工具中 开发板和 Partition Scheme 选择如下图:

  3. 项目中选择导出已编译的二进制文件,导出的二进制文件在同级目录下。

  4. 将导出的 .bin 文件重命名为 esp32_1_0_x.bin 样式,并复制到 2.4.1 节中的 esp32目录中,保证使用 http://192.168.1.x/esp32/esp32_1_0_x.bin 能够下载到该文件。

2.4.3 替换远程链接并烧录基准程序(版本为:1_0_0 的程序)测试升级是否成功

  1. 将 arduino IDE 中的程序的远程链接替换成本地 HTTP 服务器链接
  2. 将 2.4.1 节中的 esp32_update.json 内部版本改为 1_0_0 ,保证一开始不升级。
  3. 将程序烧录进 esp32 开发板中。然后打开串口监视器
  4. 串口调试器中显示不需要升级
  5. 将 2.4.1 节中的 esp32_update.json 内部版本改为 1_0_1 ,然后重启开发板。
  6. 由上图可知,开发板自动判断是否需要升级并自动OTA升级成功。

3. HTTP_OTA 升级展望

3.1 后期版本更新可通过 HTTP_OTA 实现

通过第二节可知,可以通过 HTTP_OTA 实现 esp32 开发板的隔空升级,这样可以在一台设备上测试好了程序后,上传 .bin 文件到第 2.4.1 节中的 HTTP 服务器文件夹中,实现其他开发板批量升级。

3.2 借助网络云平台实现远程 HTTP_OTA 升级

第 2.4 节是使用本地 HTTP 服务器进行升级的,我们也可以使用云服务厂商的对象云存储服务,将需要升级的 .bin 文件与 esp32_update.json 放到云服务厂商的对象云存储服务中,使用提供的公网域名替换程序代码中的远程固件连接,真正实现远程 OTA 快速自动升级服务。

注意:

  1. 本地 HTTP_OTA 升级时,本机电脑需要和 esp32 开发板连在同一个网络下,否则 esp32 开发板无法访问固件地址。
  2. 使用云服务厂商的对象云存储服务,对象云存储需要设置禁止缓存,否则可能会获取之前缓存的版本而不是最新版,导致不必要的错误。

本文首发于本人博客:https://blog.gitnote.cn/post/esp32cam_http_ota/
版权信息: CC BY-NC-SA 4.0 (自由转载-非商用-相同方式共享-保持署名)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-5314848.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

基本不等式@平均值不等式@双勾函数不等式

文章目录 基本不等式基本齐次不等式一次形式&#x1f47a;基本不等式拓展拓展1拓展2 算数平均数和几何平均数不等式应用恒等变形 双勾函数不等式导数函数单调性&#x1f388;求解过程 极值点和极值函数单调性的简单证明&#x1f388; 基本不等式 基本齐次不等式 设 a , b ∈ …

Rule110

Rule 110 is a one-dimensional cellular automaton with interesting properties (such as being Turing-complete). There is a one-dimensional array of cells (on or off). At each time step, the state of each cell changes. In Rule 110, the next state of each ce

webstorm配置less转译

Program中路径如果识别不到 项目文件\node_modules.bin\lessc

图片识别文字在线转换,这几个方法很好用

随着科技的不断发展&#xff0c;图片文字在线转换已经成为了一个非常方便的工具。通过这个工具&#xff0c;我们可以将图片中的文字转换成电子文本&#xff0c;方便我们进行编辑、存储和分享。本文将介绍一些好用的方法和注意事项&#xff0c;帮助大家更好地使用图片文字在线转…

用python编写一个小程序,如何用python编写软件

大家好&#xff0c;给大家分享一下用python编写一个小程序&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 1、python可以写手机应用程序吗&#xff1f; 我想有人曲解意思了&#xff0c;人家说用python开发渣蔽一个手机app&#xff0c;不是…

互联网医院系统开发:打造便捷高效的医疗服务平台

随着互联网技术的飞速发展&#xff0c;互联网医院系统的出现为医疗行业带来了许多新的机遇和优势。互联网医院系统是一种基于互联网技术的医疗服务平台&#xff0c;旨在提供便捷、高效、个性化的医疗服务。下面将介绍互联网医院系统开发的优势。   提供便捷的医疗服务&#x…

SQL-进阶

mysql --local-infile -u root -pset global local_infile 1;load data local infile 目录 into able 表名 fields terminated by , lines terminated by \n;

Footprint Analytics 宣布 20+ 链 API 免费增速,助力熊市 buidler

7 月 31 日&#xff0c;web3 数据供应商 Footprint Analytics 宣布其 API 产品的重大更新。 此次升级不仅大幅提升了 API 产品调用速度限制&#xff0c;还开放了包括 Ethereum, BNB, Polygon, zkSync 等在内的 20 公链的免费数据调用。 此外&#xff0c;Footprint 还更新了新…
推荐文章