基于官方 SDK 的ESP8266在线更新固件 OTA
阅读原文时间:2021年04月20日阅读:1

最近在使用ESP8266自己DIY智能家居应用,作为一个智能小家电,在线更新固件是必不可少的,本文介绍一下本人的OTA方案,供大家参考。
一、方案选择 
 参考ESP8266_RTOS_SDK中给出的示例,就可以轻松搭建出本地服务器以供OTA升级,但是这个方案有一个局限性,就是ESP8266只能在内网更新,一旦离开将无法使用。所以上云使用是必须的,这样可以使用手机微信小程序远程控制,也可以搭配小米音箱或者HomeKit的生态组建智能交互环境。上云的话,乐鑫官方有提供ESPRESSIF Cloud服务,具体可以参考https://iot.espressif.cn,我这里本着折腾的原则٩(ˊᗜˋ*)و,选择用自己的腾讯云搭建一个OTA服务器,下面是我的折腾历程,帮大家排一下雷。。。
 二、OTA服务搭建 
  由于我的博客是使用hexo提供Web服务的,所以想要直接下载文件很简单,在hexo网站项目的根目录下的source文件夹中创建download文件夹,你还可以在download下创建其他子文件夹,用于分类管理,然后将bin档上传到这个文件夹中就可以了。这样,你的下载url就是https://域名/download/子文件夹/bin档文件名。  
  然后是HTTPS证书的认证问题,这里需要注意的是国内的服务器申请域名是需要备案的,由于我的域名是在腾讯云购买的,所以相应的DNS解析也是由腾讯云提供,HTTPS证书也是由腾讯云提供。在腾讯云后台找到相应的地方,下载申请好的HTTPS证书,下载下来是个zip包,解压后发现腾讯云已经提供好各种Web服务对应的证书文件了,这里我们需要的是Apache文件夹中的1_root_bundle.crt文件,注意不是所有crt证书都可以转换为ESP8266可用的pem证书的,因为有些crt证书是已经组合过的证书了。linux环境下在命令行中输入如下指令将crt转换为pem:openssl x509 -in 1_root_bundle.crt -out ca_cert.pem1  
  在ESP8266项目根目录下创建server_certs文件夹,将生成的ca_cert.pem文件复制到这个文件夹中,至此,OTA服务的搭建就已经完成了。
  三、固件编写 
  首先是menuconfig的配置,参考SDK中相关示例的README,需要修改Partition Table项,将Single factory app, no OTA修改为Factory app, two OTA definitions或者Custom partition table CSV,我这里直接修改为Factory app, two OTA definitions,因为本身代码不是特别复杂,所以直接用官方设定就可以了。如果要自定义分区表,请参考SDK中./docs/en/api-guides/partition-tables.rst的说明创建。 
  其次是修改component.mk文件,将HTTPS证书路径添加到编译过程中,在component.mk文件中添加下面这条语句:COMPONENT_EMBED_TXTFILES := ${PROJECT_PATH}/server_certs/ca_cert.pem1  然后是代码编写,参考SDK中给出的示例,只需要100行不到的代码,就可以实现HTTPS的OTA升级了,下面贴一下我基于官方SDK少量修改后的代码,给大家参考一下。官方SDK都是自解释命名方式,所以我只做少量注释。#include “freertos/FreeRTOS.h”#include “freertos/task.h”#include “freertos/event_groups.h”#include “freertos/FreeRTOS.h”#include “freertos/task.h”#include “esp_system.h”#include “esp_log.h”#include “esp_netif.h”#include “esp_event.h”#include “protocol_examples_common.h”#include “nvs.h”#include “nvs_flash.h”#include “esp_ota_ops.h”#include “esp_http_client.h”#include “esp_https_ota.h”#include “mqtt_tcp.h"static const char *TAG = “OTA”;extern const uint8_t server_cert_pem_start[] asm(”_binary_ca_cert_pem_start");extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");esp_err_t _http_event_handler(esp_http_client_event_t *evt){ switch (evt->event_id) { case HTTP_EVENT_ERROR: ESP_LOGD(TAG, “HTTP_EVENT_ERROR”); break; case HTTP_EVENT_ON_CONNECTED: ESP_LOGD(TAG, “HTTP_EVENT_ON_CONNECTED”); break; case HTTP_EVENT_HEADER_SENT: ESP_LOGD(TAG, “HTTP_EVENT_HEADER_SENT”); break; case HTTP_EVENT_ON_HEADER: ESP_LOGD(TAG, “HTTP_EVENT_ON_HEADER, key=%s, value=%s”, evt->header_key, evt->header_value); break; case HTTP_EVENT_ON_DATA: ESP_LOGD(TAG, “HTTP_EVENT_ON_DATA, len=%d”, evt->data_len); break; case HTTP_EVENT_ON_FINISH: ESP_LOGD(TAG, “HTTP_EVENT_ON_FINISH”); break; case HTTP_EVENT_DISCONNECTED: ESP_LOGD(TAG, “HTTP_EVENT_DISCONNECTED”); break; } return ESP_OK;}void ota_task(void *pvParameter){ ESP_LOGI(TAG, “ota_task start\n”); esp_http_client_config_t config = { .url = “https://godenx.club/download/update.bin”, //这里我直接修改为我自己的bin文件下载链接 .cert_pem = (char )server_cert_pem_start, .event_handler = _http_event_handler, .timeout_ms = 20000, //修改这里是因为网络不太稳定,延长超时时间提高OTA升级成功率 }; esp_err_t ret = esp_https_ota(&config); if (ret == ESP_OK) { mqtt_return_msg(success); //我的项目是使用mqtt通讯的,所以这里有一个mqtt的通讯函数,用于汇报OTA升级成功 ESP_LOGE(TAG, “Firmware Upgrades Success!”); esp_restart(); } else { mqtt_return_msg(fail); //通过mqtt汇报OTA升级失败 ESP_LOGE(TAG, “Firmware Upgrades Failed!”); } vTaskDelete(NULL);}/ OTA升级调用接口 */void ota_start(){ xTaskCreate(&ota_task, “ota_task”, 8192, NULL, 5, NULL);}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081  这段示例代码已经实现了一个简单的OTA升级了,只需要适当修改部分地方,就可以直接拿来使用。需要OTA升级时,直接调用ota_start()就可以了。当你的程序全部写好后,使用make ota指令来生成OTA的bin档,bin档名称是以你的项目名开头,ota.bin结尾的文件,可以修改bin档名称,只需要对应修改下载链接就可以了,然后将bin档上传到服务器。可以给更新固件加入一些显示版本号的函数,用于区分是否升级成功。
  四、DEBUG调试 
  我的项目使用的时mqtt通讯,所以我通过mqtt发送升级命令后,就可以在串口看到程序运行ota_task了,当时经常会遇到如下的问题,导致OTA升级失败。E (531279) esp-tls: read error :-76E (531279) TRANS_SSL: esp_tls_conn_read error, errno=No more processes12  
  经过一番搜索,发现问题原因就是网络质量差,需要增大超时时间,具体方法就是在HTTP客户端配置中添加timeout_ms这个配置,经过一番测试,20000这个数值可以保证在我这边的网络下每次升级成功。esp_http_client_config_t config = { .timeout_ms = 20000,};

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章