前言

  这一节和上一节是搭配的

  给大家鱼,也必须给鱼竿!

  我期望自己封装的代码,无论过了多少年都有应用的价值!

  这节说明一下制作APP用户程序的过程

  咱是用MQTT通信控制模块实现升级,所以首先自己的程序先实现MQTT哈.

协议

  

注:所有的实现MQTT的软件,统称为MQTT上位机

一,MQTT上位机通过MQTT发送获取设备信息指令(用户在APP上点击检查更新时发送此命令)
{"data":"updata","cmd":"DeviceInfo"} //设备接收到回复
{"data":"updata","model":"STM32_MQTT_AT8266_SUM","version":"1.0.2"}//假设现在的型号是 STM32_MQTT_AT8266_SUM,当前设备硬件版本是1.0.2 二,MQTT上位机根据型号使用http访问云端存放的记录更新信息的文件
"型号"
列如:上位机使用http访问 http://47.92.31.46/hardware/STM32_MQTT_AT8266_SUM/updatainfo.txt 假设updatainfo.txt文件信息是:
{"version":"1.0.45611","SumBin1":,"SumBin2":,"details":"1,优化了部分BUG;2,测试升级;3,支持升级STM32程序;4,修改XXXBUG"} 注:版本号最大设置为20字节
APP检测版本不一致时

把后面的 "details":"1,优化了部分BUG;2,测试升级;3,支持升级STM32程序;4,修改XXXBUG" 提示给用户 
用户点击更新的时候接着往下看
三,发送以下指令
{"data":"updata","cmd":"start"} 注:测试时可直接发送此指令 //设备接收到回复 {"data":"updata","status":"start"}
然后进入BootLoader程序执行升级去了 为了让APP知道升级的状态
四,设备在执行用户程序连接上MQTT发送的第一条消息为
"{\"data\":\"status\",\"status\":\"online\",\"UpdataStatus\":\"UpdataSuccess\",\"version\":\"1.0.45611\"}" UpdateStatus_None //没有更新
UpdateStatus_DataAddressError //Flash的高位地址不是0x08 或者 RAM的高位地址不是0x20
UpdateStatus_DataOverflow //数据接收溢出
UpdateStatus_DownloadTimeout //程序下载超时
UpdateStatus_MainTimeout //整个程序运行的时间
UpdateStatus_FlashWriteErr //Flash 写错误
UpdateStatus_VersionLenErr //版本号长度错误
UpdateStatus_VersionAlike //版本号和服务器上面的一致
UpdateStatus_FlashEraseErr //Flash 擦除失败
UpdateStatus_MissingData //数据接收不完整
UpdateStatus_SumBinRangeErr //校验和范围错误(获取的云端的校验和,不在0-255之间)
UpdateStatus_SumCheckErr //校验和不一致
UpdateStatus_RunAppError //上次更新的程序没有运行起来 ----------------------------------------------------------------
控制指令,查询继电器状态
{"data":"switch","bit":"","status":"-1"} 设备回复 {"data":"switch","bit":"","status":""} 或者 {"data":"switch","bit":"","status":""} 六,控制指令,控制继电器吸合
{"data":"switch","bit":"","status":""} 设备回复 {"data":"switch","bit":"","status":""} 七,控制指令,控制继电器断开
{"data":"switch","bit":"","status":""} 设备回复 {"data":"switch","bit":"","status":""}

准备一个工程

把基础篇的已经实现MQTT通信的工程拷贝过来

把以下文件放到自己的工程

  stmflash文件直接拷贝的上一节的

  IAP和上一节的不一样,做了很多裁剪.

  

注:受内存影响,去掉了OLED部分

主函数配置

  1.包含下头文件

    

  2.调用一个函数  IAPGetUpdateInfo();//获取更新的信息

    

处理更新

  先说一下哈,处理更新是这个函数

  IAPUpdateDispose();

  这个函数主要就是清零更新状态,然后如果判断运行的是新程序,则切换程序版本.

  

  然后说一下上面函数的妙处

  如果在BootLoader里面程序文件下载成功

    

  BootLoader下载好程序以后呢,写入状态为:0x01 然后重启了

  重启以后当然还是先运行 BootLoader

  然后 BootLoader 判断是0x01以后 写入 0xFF

  然后运行新的用户程序

  假设用户程序有问题 没有执行函数  IAPUpdateDispose();

  那么就没有把升级状态清零

  那么单片机重启以后又运行 BootLoader,此时BootLoader里面一判断还是0xFF

  便会认为没有正确执行用户程序,就会切换上一份用户程序执行

  

  然后总的来说就一句话:

  你认为APP用户程序运行没有问题了以后再调用 IAPUpdateDispose();

 

这节建议这样处理

  在连接上MQTT以后,咱调用下 IAPUpdateDispose();

  然后把升级状态通过MQTT发出去

  

  

/**
* @brief 连接上MQTT以后发送一条上线指令
* @param
* @param
* @retval
* @example
**/
void FunctionSendOnline(void)
{
IAPUpdateDispose(); //如果不使用自定义的配置
#ifndef UserCustomConfig //device/Wi-Fi的MAC
memset(MQTTPublishTopic,NULL,sizeof(MQTTPublishTopic));
sprintf(MQTTPublishTopic,"%s%s","device/",&MQTTid[]);//组合发布的主题
#endif
MqttPublishTopicStruct.topicName.cstring = MQTTPublishTopic;//设置发布的主题
MqttPublishTopicStruct.qos = ; //消息等级
MqttPublishTopicStruct.retained = ; //需要服务器保留消息
//连接上MQTT以后发送一条上线信息,携带着更新状态,当前设备版本
MainLen= sprintf(MainBuffer,"{\"data\":\"status\",\"status\":\"online\",\"UpdataStatus\":\"%s\",\"version\":\"%s\"}",
IAPStructValue.UpdateStatusStr,//更新的状态
IAPStructValue.VersionDevice //当前设备版本
);//组合发送的数据
MainLen = MqttPublish(MqttPublishTopicStruct,MainBuffer,MainLen);//打包MQTT数据
UsartOutStr(MqttSendData,MainLen);//发送MQTT协议数据
MqttPublishTopicStruct.retained = ; //后期的数据不需要服务器保留消息
}

加上处理更新协议

  

  如果通过MQTT接收到获取设备信息指令

  就返回设备信息(型号,和当前版本号)

  MQTT上位机根据型号,http访问对应的 updatainfo.txt

  然后对比下版本号,如果不一致,就提示给用户有新版本

  然后用户点击升级的时候 再发给模块 开始更新的指令

  模块收到以后设置更新标志

  返回给MQTT 我要升级了   "{\"data\":\"updata\",\"status\":\"start\"}"    嘻嘻嘻

  然后呢 重启就好了

  因为有了升级标志,BootLoader里面就去执行升级去了

  

先查看一下用户程序的bin文件大小

  

  咱上一节BootLoader里面设置的

  0x5C00  = 23KB   设置的可以满足

  

  

配置生成第一份程序文件

  

  

  

  

配置生成第二份程序文件

  

  

  

打开计算校验和软件

  

  

计算第一份程序文件的校验和

  

计算第二份程序文件的校验和

  

把相应的文件放到云服务器

  

  

  

测试放到下一节

ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于Wi-Fi模块AT指令TCP透传方式,MQTT通信控制升级(含有数据校验)-APP用户程序制作过程的更多相关文章

  1. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于(Wi-Fi模块AT指令TCP透传方式),MQTT通信控制升级

    实现功能概要 前面的版本都是,定时访问云端的程序版本,如果版本不一致,然后下载最新的升级文件,实现升级. 这一节,在用户程序里面加入MQTT通信,执行用户程序的时候,通过接收MQTT的升级命令实现升级 ...

  2. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于GPRS模块(Air202,SIM800)AT指令TCP透传方式,MQTT通信控制升级

    实现功能概要 这节和上一节的功能一样(只不过上节是利用Wi-Fi模块,这节是利用GPRS模块) 用户程序里面加入MQTT通信,执行用户程序的时候, 通过接收MQTT的升级命令实现升级. 凡是可以实现M ...

  3. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于Wi-Fi模块(ESP8266)AT指令TCP透传方式,MQTT通信控制升级(加入数据校验)

    前言 这节演示下,上两节写的利用MQTT来控制STM32控制的程序 测试准备工作(默认访问我的服务器,改为自己的服务器,请看后面说明) 一,下载BootLoader程序(请自行下载) 首先BootLo ...

  4. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于GPRS模块AT指令TCP透传方式,定时访问升级(含有数据校验)

    实现功能概要 单片机定时使用http访问云端的程序版本,如果版本不一致, 然后通过http下载最新的升级文件,实现远程升级STM32程序. 兼容Air202 ,SIM800 测试准备工作(默认访问我的 ...

  5. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于(GPRS模块AT指令TCP透传方式),定时访问升级(兼容Air202,SIM800)

    实现功能概要 单片机定时使用http访问云端的程序版本, 如果版本不一致,然后通过http下载最新的升级文件,实现远程升级STM32. 兼容Air202,SIM800 测试准备工作(默认访问我的服务器 ...

  6. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于WIFI模块AT指令TCP透传方式,定时访问升级(含有数据校验)

    实现功能概要 定时使用http访问云端的程序版本,如果版本不一致,然后通过http下载最新的升级文件,实现升级. 测试准备工作(默认访问我的服务器,改为自己的服务器,请看后面说明) 一,下载BootL ...

  7. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于(WIFI模块AT指令TCP透传方式),定时访问升级

    前言 学习此代码所需: 实现功能概要 定时使用http访问云端的程序版本,如果版本不一致,然后通过http下载最新的升级文件,实现升级. 测试准备工作(默认访问我的服务器,改为自己的服务器,请看后面说 ...

  8. ESA2GJK1DH1K升级篇: 移植远程更新程序到STM32F103RET6型号的单片机,基于(GPRS模块AT指令TCP透传方式)

    前言 上节实现远程更新是更新的STM32F103C8T6的单片机 GPRS网络(Air202/SIM800)升级STM32: 测试STM32远程乒乓升级,基于(GPRS模块AT指令TCP透传方式),定 ...

  9. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,升级流程源码详细说明

    前言 1.BootLoader程序,升级简要流程图 2.其实主要的就是把程序文件写入环形队列,然后环形队列取出来数据写入Flash 3.用户程序,简要流程图 下面的读一下,有个印象就可以: 说白了就是 ...

随机推荐

  1. 松软科技web课堂:JavaScript If...Else 语句

    条件语句用于基于不同条件执行不同的动作. 条件语句 在您写代码时,经常会需要基于不同判断执行不同的动作. 您可以在代码中使用条件语句来实现这一点. 在 JavaScript 中,我们可使用如下条件语句 ...

  2. enable user-defined extended attributes for ext3 file systems; 增加ext3 文件系统的扩展属性;

    To enable user-defined extended attributes for ext3 file systems (i.e. device), use: tune2fs -o user ...

  3. n个数字相加

    求s=a+aa+aaa+aaaa+aa...a的值 其中a是一个数字,多少个数字相加由键盘输入控制 a = int(input("数字:")) count = int(input( ...

  4. Flink概述| 配置

    流处理技术的演变 在开源世界里,Apache Storm项目是流处理的先锋.Storm提供了低延迟的流处理,但是它为实时性付出了一些代价:很难实现高吞吐,并且其正确性没能达到通常所需的水平,换句话说, ...

  5. 品Spring:注解终于“成功上位”

    历史还是抛弃了XML,当它逐渐尝到注解的甜头之后. 尤其是在Spring帝国,到处充满着注解的气息. 注解从一个提供附属信息的“门客”,蜕变为颇具中流砥柱的“君侯”. 注解成功登上了帝国的舞台,定会像 ...

  6. Centos6进入单用户模式的两种方法

    单用户模式的作用 在使用Linux系统中,维护人员经常会碰到一个问题,就是在拥有root账号权限和密码的用户中,总是会出现忘记root密码的情况.遇到这种情况,一般情况下,维护人员就会通过最常用的方法 ...

  7. C++入门到理解阶段二核心篇(1)——c++面向对象概述、内存分析、引用

    1.c++内存分区模型 c++程序在运行的过程中,内存会被划分为以下四个分区 代码区:程序的所有程序的二进制代码,包括注释会被放到此区 全局区:存放静态变量.全局变量.常量(字符串常量和const修饰 ...

  8. 利用Python进行数据分析-Pandas(第五部分-数据规整:聚合、合并和重塑)

    在许多应用中,数据可能分散在许多文件或数据库中,存储的形式也不利于分析.本部分关注可以聚合.合并.重塑数据的方法. 1.层次化索引 层次化索引(hierarchical indexing)是panda ...

  9. 连接远程服务器的几种方式/Vscode + Remote

    连接远程服务器的几种方式 前言 最近在尝试做网盘,使用的技术栈大概是 .net core + MVC + Mysql + Layui,主要目的是通过这个具体的项目,熟悉熟悉 .net core 开发, ...

  10. centos添加用户并赋予管理员权限

    用centos时,root用户一般都是超级管理员使用的,一般不轻易给别人,但是有时候同事安装软件时需要root账号,又不得不给,只能重新建一个用户,并赋予管理员权限.下面介绍创建用户并赋予管理员权限的 ...