haas506 2.0开发教程-高级组件库-ota
最新案例教程点击下方链接跳转,CSDN已停止更新
点
击
跳
转
点击跳转HaaS506官方最新案例
ota升级
1、案例说明
-
OTA升级是通过无线网络在线升级,简单来说就是在连接无线网络的情况下,通过系统自带的更新设置来进行设备系统升级。比如手机系统更新。
-
Haas506开发板完成动态注册连接云端后可以完成OTA升级(远程更新)。
(1) 系统文件升级需要注册3个函数,在云端触发文件升级后,会触发on_trigger函数,并将文件的一系列信息通过on_trigger参数传入,我们可以将这些参数保存到全局变量中;
(2)在on_trigger触发后,我们在on_trigger回调函数中调用ota.download函数来下载文件,ota.download函数下载完成后,会产生on_download回调,我们根据on_download的传入参数判断下载文件是否成功,如果成功, 我们在on_download回调函数中调用ota.verify来做文件校验;
(3)ota.verify函数校验完成后,会产生on_verify回调,我们根据on_verify的传入参数来判断校验文件是否成功。
2、代码
- 需要将产品的productKey和productSecret,粘贴到代码的指定位置
- 2.2版本获取IMEI号接口有更新,需要更改以下内容(Ctrl+F 查找modem)
deviceName = modem.info.getDevImei()
...
from driver import GPIO
import network
import ujson
import utime as time
import modem
from aliyunIoT import Device
import ota
import kv
def on_trigger(data):
global info
info['url'] = data['url']
info['length'] = data['length']
info['module_name'] = data['module_name']
info['version'] = data['version']
info['hash'] = data['hash']
info['hash_type'] = data['hash_type']
dl_data = {}
dl_data['url'] = info['url']
dl_data['store_path'] = info['store_path']
ota.download(dl_data)
def on_download(data):
global info
if data >= 0:
print('Ota download succeed')
param = {}
param['length'] = info['length']
param['store_path'] = info['store_path']
param['hash_type'] = info['hash_type']
param['hash'] = info['hash']
ota.verify(param)
def on_verify(data):
global info
print(data)
if data >= 0 :
print('Ota verify succeed')
print('Start Upgrade')
param = {}
param['length'] = info['length']
param['store_path'] = info['store_path']
param['install_path'] = info['install_path']
ota.upgrade(param)
def on_upgrade(data):
if data >= 0 :
print('Ota succeed')
reboot()
def on_connect(data):
global module_name,default_ver,productKey,deviceName,deviceSecret,on_trigger,on_download,on_verify,on_upgrade
print('***** connect lp succeed****')
data_handle = {}
data_handle['device_handle'] = device.getDeviceHandle()
ota.init(data_handle)
ota.on(1,on_trigger)
ota.on(2,on_download)
ota.on(3,on_verify)
ota.on(4,on_upgrade)
report_info = {
"device_handle": data_handle['device_handle'],
"product_key": productKey ,
"device_name": deviceName ,
"module_name": module_name ,
"version": default_ver
}
ota.report(report_info)
def on_disconnect():
print('linkkit is disconnected')
def on_props(request):
print('clound req data is {}'.format(request))
def on_service(id,request):
print('clound req id is {} , req is {}'.format(id,request))
def on_error(err):
print('err msg is {} '.format(err))
def on_4g_cb(args):
global g_connect_status
pdp = args[0]
netwk_sta = args[1]
if netwk_sta == 1:
g_connect_status = True
else:
g_connect_status = False
def connect_network():
global net,on_4g_cb,g_connect_status
net = network.NetWorkClient()
g_register_network = False
if net._stagecode is not None and net._stagecode == 3 and net._subcode == 1:
g_register_network = True
else:
g_register_network = False
if g_register_network:
net.on(1,on_4g_cb)
net.connect(None)
else:
print('网络注册失败')
while True:
if g_connect_status:
print('网络连接成功')
break
time.sleep_ms(20)
def on_dynreg_cb(data):
global deviceSecret,device_dyn_resigter_succed
deviceSecret = data
device_dyn_resigter_succed = True
def dyn_register_device(productKey,productSecret,deviceName):
global on_dynreg_cb,device,deviceSecret,device_dyn_resigter_succed
key = '_amp_customer_devicesecret'
deviceSecretdict = kv.get(key)
print("deviceSecretdict:",deviceSecretdict)
if isinstance(deviceSecretdict,str):
deviceSecret = deviceSecretdict
if deviceSecretdict is None or deviceSecret is None:
key_info = {
'productKey': productKey ,
'productSecret': productSecret ,
'deviceName': deviceName
}
if not device_dyn_resigter_succed:
device.register(key_info,on_dynreg_cb)
if __name__ == '__main__':
ICCID=None
g_connect_status = False
net = None
device = None
deviceSecret = None
deviceName = None
productKey = "a1aNr1wef2c"
productSecret = "Jppqfgx4tHeZh1Zi"
device_dyn_resigter_succed = False
module_name = 'default'
default_ver = '2.0.1'
info = {
'url': '',
'store_path': '/data/pyamp/app.zip',
'install_path': '/data/pyamp/',
'length': 0,
'hash_type': '',
'hash': ''
}
connect_network()
deviceName = modem.getDevImei()
ICCID=modem.sim.getIccid()
device = Device()
if deviceName is not None and len(deviceName) > 0 :
dyn_register_device(productKey,productSecret,deviceName)
else:
print("获取设备IMEI失败,无法进行动态注册")
while deviceSecret is None:
time.sleep(0.2)
print('动态注册成功:' + deviceSecret)
key_info = {
'region' : 'cn-shanghai' ,
'productKey': productKey ,
'deviceName': deviceName ,
'deviceSecret': deviceSecret ,
'keepaliveSec': 60,
}
print(key_info)
device.on(device.ON_CONNECT,on_connect)
device.on(device.ON_DISCONNECT,on_disconnect)
device.on(device.ON_PROPS,on_props)
device.on(device.ON_SERVICE,on_service)
device.on(device.ON_ERROR,on_error)
device.connect(key_info)
FwVersion={}
FwVersion["FwVersion"]="amp-v1.16 build on 2021-11-17, 15:18:23"
FwVersionStr=ujson.dumps(FwVersion)
data0={
'params':FwVersionStr
}
time.sleep_ms(1000)
device.postProps(data0)
print("FwVersionStr:",FwVersionStr)
imei_iccid={}
imei_iccid["IMEI"]=deviceName
imei_iccid["ICCID"]=ICCID
imei_iccid_str=ujson.dumps(imei_iccid)
data1={
'params':imei_iccid_str
}
time.sleep_ms(1000)
device.postProps(data1)
while True:
print('当前App版本号:' + default_ver)
print('等待Ota升级包.....')
print('--------------------------------------------------------------------')
time.sleep(1)
{
"name": "haas506",
"version": "2.0.0",
"io": {
"cloud_led":{
"type":"GPIO",
"port": 9,
"dir": "output",
"pull":"pulldown"
},
"serial1":{
"type":"UART",
"port":0,
"dataWidth":8,
"baudRate":115200,
"stopBits":1,
"flowControl":"disable",
"parity":"none"
},
"serial2":{
"type":"UART",
"port":1,
"dataWidth":8,
"baudRate":115200,
"stopBits":1,
"flowControl":"disable",
"parity":"none"
},
"serial3":{
"type":"UART",
"port":2,
"dataWidth":8,
"baudRate":115200,
"stopBits":1,
"flowControl":"disable",
"parity":"none"
}
},
"debugLevel": "ERROR"
}
3、上传升级包
(1)在阿里云物联网平台创建一个设备、打开动态注册
(2)在设备的功能定义中设置自定义功能,如IMEI、ICCID和FwVersion,然后发布上线
(3)在产品下创建一个设备,建议使用设备的IMEI号作为deviceName
(4)复制产品的productKey和productSecret,粘贴到程序的相应位置
(5)烧录程序,查看日志获取到当前版本为2.0.1
![在这里插入图片描述](https://img-blog.csdnimg.cn/b2c03d6b6f99482ab25983341eff1727.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
(6)当修改代码后,将代码中的default_ver改为2.0.6,保存
(7)将当前项目的x.py和board.json一起打包成xx.zip
(8)打开ota升级面板
![在这里插入图片描述](https://img-blog.csdnimg.cn/1e3c7ce9037842f6a464fc48649226a6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
(9)添加升级包,填写升级包名称、所属产品、升级包模块、升级包版本号、签名算法、上传升级包
注意:升级包版本号必须与程序中更改的版本号一致 。
例如,上传的压缩包版本号为2.0.6 ,这里必须填写2.0.6 。否则云端会显示更新失败,但程序能正常下载至开发板。
![在这里插入图片描述](https://img-blog.csdnimg.cn/016f9d4454384d0b800f116307290469.png)
(10)点击验证
![在这里插入图片描述](https://img-blog.csdnimg.cn/96b5cd8156e14780888638399def28da.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
(11)输入待升级版本号、待验证的设备
![在这里插入图片描述](https://img-blog.csdnimg.cn/c57baaa285734a55b6803bf7fc286fd4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述](https://img-blog.csdnimg.cn/e90c949c64d64d8ba00f5a5bd41458e8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
(12)验证中
![在这里插入图片描述](https://img-blog.csdnimg.cn/f6263ed7f0e445f9a7addf90ee836d68.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
(13)点击查看
![在这里插入图片描述](https://img-blog.csdnimg.cn/d03abec1fdeb49b185b1b3e555070719.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
(14)等待升级成功
![在这里插入图片描述](https://img-blog.csdnimg.cn/3a6a9d21506141e89e78af25acef319e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
(15)查看日志/设备详情,查看设备是否升级成功
![在这里插入图片描述](https://img-blog.csdnimg.cn/f1899a62b223441ca9430cc2d253fab0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pm65LqR5pyN,size_20,color_FFFFFF,t_70,g_se,x_16)
init | on | report | download | verify | upgrade |
---|
初始化ota服务 | 注册ota升级相关的回调函数 | 上报ota升级版本号,模块名等信息 | 下载ota升级包 | 升级包校验 | 执行ota升级操作 |
ota.init(data_handle) - 初始化
函数功能:ota 初始化,建立ota后台服务线程
注意事项:确保wifi连接成功 确保aliyunIoT连接成功
参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
data_handle | dictionary | 是 | ota初始化需要参数 |
data_handle参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
device_handle | int | 是 | aliyunIoT句柄 |
返回值说明:成功返回0, 其他表示失败
ota.report(report_info) - 上报当前模块版本
函数功能:上报模块版本号信息
注意事项:确保wifi连接成功
确保aliyunIoT连接成功
参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
report_info | dictionary | 是 | 上报模块版本号需要的信息 |
report_info参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
device_handle | int | 是 | aliyunIoT句柄 |
product_key | string | 是 | 上云三元组信息product_key |
device_name | string | 是 | 上云三元组信息device_name |
module_name | string | 是 | 待上报模块的名字 |
module_name | string | 是 | 待上报模块的版本号 |
返回值说明:成功返回0, 其他表示失败。
ota.on(1, on_trigger) - 回调注册 - 1
函数功能:注册OTA的on_trigger回调函数,在升级开始时触发
注意事项:确保wifi连接成功。
确保aliyunIoT连接成功。
确保ota.init执行完成。
参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
on_trigger | funcCallback | 是 | 文件升级触发时的回调函数 |
on_trigger函数原型:def on_trigger(data)
Copy to clipboardErrorCopied
on_trigger函数参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
data | dictionary | 是 | on_trigger函数触发时传入on_trigger的参数 |
on_trigger函数data参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
url | string | 是 | 待升级文件所在url |
length | int | 是 | 待升级文件文件长度,单位是字节 |
module_name | string | 是 | 待升级文件的模块名称 |
version | string | 是 | 待升级文件的版本号 |
hash | string | 是 | 待升级文件的哈希值 |
hash_type | string | 是 | 待升级文件的哈希类型 |
返回值说明:成功返回0, 其他表示失败。
ota.on(2, on_download) - 回调注册 - 2
函数功能:注册OTA的on_download回调函数,在download完成时触发
注意事项:确保wifi连接成功
确保aliyunIoT连接成功
确保ota.init执行完成
参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
on_download | funcCallback | 是 | 文件下载完成时的回调函数 |
on_download函数原型:def on_download(data)
on_download函数参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
data | int | 是 | on_download函数触发时传入on_download的参数 ,大于等于0说明download成功,否则失败 |
返回值说明:成功返回0, 其他表示失败。
ota.on(3, on_verify) - 回调注册 - 3
函数功能:注册OTA的on_verify回调函数,在verify完成时触发
注意事项:确保wifi连接成功
确保aliyunIoT连接成功
确保ota.init执行完成
参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
on_verify | funcCallback | 是 | 文件校验完成时的回调函数 |
on_verify函数原型:def on_verify(data)
on_verify函数参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
data | int | 是 | on_verify函数触发时传入on_download的参数 ,大于等于0说明verify成功,否则失败 |
返回值说明:成功返回0, 其他表示失败。
ota.download(data) - 文件下载
函数功能:发起文件下载流程。
注意事项:确保wifi连接成功
确保aliyunIoT连接成功
确保ota.init执行完成
参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
data | dictionary | 是 | 发起文件下载流程所需要的信息 |
data参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
url | string | 是 | 文件所在的url信息 |
store_path | string | 是 | 文件要下载到的文件系统路径 |
返回值说明:成功返回0, 其他表示失败。
ota.verify(data) - 文件校验
函数功能:发起文件校验流程
注意事项:确保wifi连接成功
确保aliyunIoT连接成功
确保ota.init执行完成
参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
data | dictionary | 是 | 发起文件校验流程所需要的信息 |
data参数说明:
参数 | 类型 | 必选参数? | 说明 |
---|
length | int | 是 | 文件长度,单位是字节 |
store_path | string | 是 | 文件所在的文件系统路径 |
hash_type | string | 是 | 文件的哈希类型 |
hash | string | 是 | 文件的哈希值 |
返回值说明:成功返回0, 其他表示失败。
ota.upgrade(param)
+ 作用: 执行ota升级操作
+ 参数: param是一个字典,包含length,store_path,install_path
+ 返回: 0成功
属性 | 类型 | 说明 |
---|
length | 字符串 | ota的升级包大小 |
store_path | 字符串 | ota包的保存路径 |
install_path | 字符串 | ota包的安装路径 |
3.总结
本节介绍了如何使用haas506高级组件库中的ota模块,实现了ota升级功能。