OTA升级中,A区攻略,基于阿里云物联网平台实现的OTA升级,根据MQTT协议传输数据
OTA升级中A区的逻辑,基于阿里云物联网平台实现的OTA升级方案,重点在于bin文件的获取,存储bin文件的方式,以及OTA升级中的各种注意事项
OTA的A区攻略
前序准备
OTA的bootloader区在这一篇已经讲过了:OTA升级中Bootloader的写法,stm32f405实现,B区跳转到A区,B区实现A区的代码更新_单片机ota升级boot代码-CSDN博客,主要是用来判断是否跳转到A区,是否读取已经获取的Bin文件写入到Flash区中,这里要注意OTA_flag的标志位什么时间点清零或者写入1.
这里,OTA的A区主要是实现Bin文件的接受和存储
我的OTA实现是基于阿里云物联网平台,用MQTT协议传输Bin文件,这里MQTT协议要根据阿里云物联网平台提供的格式来发送和接受。具体流程如下:
阿里云物联网平台的公共实例是免费的,大家可以在这里面定义

在阿里云物联网平台打开,创建自己的链接产品,连接设备并激活,这里其他文章都有教程,大家跟做一下就可以,我这里不赘述了。设备创建后自己的板子连接到阿里云服务器后,实现通过MQTT协议的方式,连接、订阅、上报信息、接受订阅主题信息等功能即可。
下图是我自己的设备,创建一个设备之后,会显示未激活状态,用三元组连接成功后,会显示在线,设备断电后,会显示离线状态。

我假设你们已经对MQTT协议有所了解,对设备接入阿里云物联网平台的流程比较熟练的前提下,开始我们的OTA升级方案的实现:
阿里云物联网平台的OTA升级
在这个网页端可以打开阿里云提供的OTA升级流程方案,其实我们只要跟着他的文档做出我们设备端的代码就可以了:MQTT协议接入的物联网设备OTA升级流程_物联网平台(IoT)-阿里云帮助中心
在这个界面,大家可以先浏览一下,左侧是我们要的OTA升级的流程,右侧导读信息下面有消息格式的描述:

跟据阿里云的推荐流程,我们设备上电后,要通过MQTT上报自己设备的版本号,阿里云也就是根据版本号来管理我们的设备,所以这里,设备端:我用SD卡存储我的版本号信息,保证掉电不丢失
上报版本号
上传版本号根据阿里云提供的协议:

在代码端,我们上电后读取SD卡的OTA版本号:
typedef struct{
uint8_t OTA_flag;
uint16_t OTA_len;
char OTA_Ver[40];
uint8_t OTA_Ready_Flag;
}OTA_InfoCB;
OTA_InfoCB OTA_Info;
void Get_OTA_Ver()
{
char OTA_Ver[]="VER.txt";
memset(OTA_Info.OTA_Ver,0,40);
retSD = f_open(&file, OTA_Ver, FA_READ);
retSD = f_read(&file, &OTA_Info.OTA_Ver, f_size(&file), &bytesRead);
retSD = f_close(&file);
}
下面就是按照阿里云提供的消息格式以MQTT格式发送版本号到云端
这里注意上报的主题:/ota/device/inform/ Y o u r P r o d u c t K e y / {YourProductKey}/ YourProductKey/{YourDeviceName}
这是阿里云提供的主题,不要上报错了,把自己的ProductKey和DeviceName换到上面的主题中就可以:
至于代码怎么写上报的消息,这要看你是怎么实现发送的,现在国产的很多4G模块提供的AT指令也可以完成MQTT的发送,这里要看自己用的什么方式,我是使用的透传方式,自己构建publish报文发送信息到云端,(说白了:只要知道上报主题,和发送的信息,剩下的怎么发送就很简单了)

这里我的代码可能比较冗长,大家自己根据自己的实际情况来写自己的MQTT上报版本号的代码:
uint8_t Send_OTA_VER() //0为成功
{
uint16_t i = 0;
uint16_t lenTop = 0;
uint16_t len1 = 0;
uint16_t len2 = 0;
uint16_t lenMsg = 0;
uint16_t DelayCnt = 0;
uint8_t Num = 0x10;
uint8_t Uart4_TranFlag;
char New_Bin[]="OTA.bin";
char temp[100];
memset(temp,0,100);
sprintf(temp,"{\"id\": \"123\",\"params\": {\"version\": \"%s\"}}",OTA_Info.OTA_Ver);
memset(TxBuff_MQTT,0,TxLen_MQTT);
//固定包头
TxBuff_MQTT[0] = GetDataFixedHead(MQTT_TypePUBLISH,0,1,0);
//可变包头(主题名+报文标识符)
lenTop = strlen(OTA_PubTopic);
lenMsg = strlen(temp);
len1 = (2+lenTop+2+lenMsg)/128;
len2 = (2+lenTop+2+lenMsg)%128+128;
if (len1>0)
{
TxBuff_MQTT[1] = len2;
TxBuff_MQTT[2] = len1;
TxBuff_MQTT[3] = lenTop>>8;
TxBuff_MQTT[4] = lenTop;
for(i = 0;i<lenTop;i++)
{
TxBuff_MQTT[5+i] = OTA_PubTopic[i];
}
TxBuff_MQTT[5+lenTop] = Num>>8;
TxBuff_MQTT[5+lenTop+1] = Num;
for(i = 0;i<lenMsg;i++) //UTF-8编码消息内容
{
TxBuff_MQTT[7+i+lenTop] = temp[i];
}
Uart4_TranFlag = HAL_UART_Transmit(&huart4,TxBuff_MQTT,lenTop+lenMsg+7,200);
// while(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_TC)==RESET)
while (Uart4_TranFlag != 0 && DelayCnt<3)
{
DelayCnt++;
Uart4_TranFlag = HAL_UART_Transmit(&huart4,TxBuff_MQTT,lenTop+lenMsg+7,100);
}
// free(TxBuff_MQTT);
if (DelayCnt >= 3)
{
return 1;
}
else
{
return 0;
}
}
else
{
TxBuff_MQTT[2] = lenTop>>8;
TxBuff_MQTT[3] = lenTop;
for(i = 0;i<lenTop;i++)
{
TxBuff_MQTT[4+i] = OTA_PubTopic[i];
}
//报文标识符(Qos等级为1或者2时有)
TxBuff_MQTT[4+lenTop] = Num>>8;
TxBuff_MQTT[4+lenTop+1] = Num;
for(i = 0;i<lenMsg;i++)
{
TxBuff_MQTT[6+i+lenTop] = temp[i];
}
TxBuff_MQTT[1] = lenTop+lenMsg + 4;
Uart4_TranFlag = HAL_UART_Transmit(&huart4,TxBuff_MQTT,lenTop+lenMsg+6,200);
while (Uart4_TranFlag != 0 && DelayCnt<3)
{
DelayCnt++;
Uart4_TranFlag = HAL_UART_Transmit(&huart4,TxBuff_MQTT,lenTop+lenMsg+6,100);
}
// free(TxBuff_MQTT);
if (DelayCnt >= 3)
{
return 1;
}
else
{
return 0;
}
}
}
我的代码不是唯一解,一定要自己理解MQTT报文格式,报文构建,报文发送,返回值判断
发送OTA版本号到阿里云物联网平台后,平台会直接看到我们上报的版本号:

至此上报版本号的工作结束。
从阿里云物联网平台下发Bin升级包
这里在阿里云物联网平台上传自己的Bin文件,就按照下图我给的方式上传

点击确认后会出现自己的升级包

点击验证按钮,可以选择自己要升级的设备,升级哪个版本


选择MQTT方式传输数据包

点击确定。这里做完之后,剩下的就是你的数据包下发接受的逻辑了
我简单讲一下现在到了什么阶段:
目前你的设备上电后,正常会上报版本号,阿里云物联网平台会收到你的版本之后。开始下发OTA升级的请求,这里通过MQTT协议,设备端请求一次数据,阿里云发送一次数据,直到Bin文件 被分包发送结束,OTA的Bin文件传输结束。
下一步设备重新上电或者是软复位后,进入B区,检测到OTA事件的发生,写入Bin文件到FLASH区后,进入A区,上报的新版本号到阿里云,阿里云检测到新版本号之后,完成OTA升级
阿里云下发Bin升级包的第一包报文
上面的流程正常进行之后,设备联网后发送完版本号之后,阿里云会主动推送一条信息
该消息主题:/ota/device/upgrade/ Y o u r P r o d u c t K e y / {YourProductKey}/ YourProductKey/{YourDeviceName}
作为测试,你们可以自己在设备端的debug界面中看一下收来的内容是什么,这样方便解析,我这里直接把解析的数据贴出来了
/ota/device/upgrade/a1IbyN243BX/Device_003{“code”: “1000”,“data”: {“size”: %d,“streamId”: %d,“sign”:“%*32s”,“dProtocol”: “mqtt”,“version”:“%22s”,“signMethod”: “Md5”,“streamFileId”: %d,“md5”: “%*32s”},“id”: %*d,“message”: “success”}",&Update_Info.Update_Size,&Update_Info.UpdateID,&Update_Info.OTA_NewVersion,&Update_Info.streamFileId
具体自己的数据是什么样的一定要自己看一下,我这里直接把数据解析到我的结构体中了
这里注意size的大小,就是我Bin文件的大小

主动拉取升级包
设备端要主动拉取升级包,也就是发送响应的数据到阿里云,


上面这个图就是发送的Topic 和返回的Topic主题,按照这个方式来发送自己的请求的报文大小就可以,
这里要注意,size是你要请求的数据包大小,offset是你数据的偏移,
比如你要256-512这一片的数据,那你的size = 256(因为512-256 = 256)offset= 256( 因为是从256开始请求的)
这里注意,一定要提前订阅这个topic,因为他是响应的topic
响应Topic:/sys/${productKey}/${deviceName}/thing/file/download_reply


按照这个响应的消息格式来解析你自己的数据就可以了,至于怎么解析,就是你的代码实现了。
升级包存储到SD卡
你要把升级包存储到SD卡或者是其他的存储硬件
因此在每一包升级包下发到设备端后,要根据你自己的实际情况,存储到掉电不丢失的存储器中。
注意:写入到存储器之后要再次发送请求数据的报文,此时要注意更改你的Offset
我这里不贴我的代码了,没什么参考价值,因为每个人实现的方式都不一样。有需要的可以私信我
最后升级包全部接受完毕之后,要记得把OTA_flag的标志位变成1,版本号写入SD卡。
这样在重新上电之后,B区识别到flag标志,开始读取你的SD卡中接收到的Bin文件到FLASH区域中,并且能上报正常的版本号到阿里云物联网平台中。
至此,OTA升级的流程就结束了。有问题大家可以多多交流,
丢失的存储器中。
注意:写入到存储器之后要再次发送请求数据的报文,此时要注意更改你的Offset
我这里不贴我的代码了,没什么参考价值,因为每个人实现的方式都不一样。有需要的可以私信我
最后升级包全部接受完毕之后,要记得把OTA_flag的标志位变成1,版本号写入SD卡。
这样在重新上电之后,B区识别到flag标志,开始读取你的SD卡中接收到的Bin文件到FLASH区域中,并且能上报正常的版本号到阿里云物联网平台中。
至此,OTA升级的流程就结束了。有问题大家可以多多交流,
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)