haas506开发教程-高级组件库-ota
1.ota升级
- main.py
# -*- coding: UTF-8 -*-
import network
import ujson
import utime as time
import modem
from linksdk import Device
import ota
from driver import KV
# ota 消息推送的接受函数
def on_trigger(data):
global info
# 保存服务端推送的ota信息
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']
# 开始ota 包下载
dl_data = {}
dl_data['url'] = info['url']
dl_data['store_path'] = info['store_path']
ota.download(dl_data)
# ota 升级包下载结果回调函数
def on_download(data):
global info
if data >= 0:
print('Ota download succeed')
# 开始ota包校验
param = {}
param['length'] = info['length']
param['store_path'] = info['store_path']
param['hash_type'] = info['hash_type']
param['hash'] = info['hash']
ota.verify(param)
# ota 升级包校验结果回调函数
def on_verify(data):
global info
print(data)
if data >= 0 :
print('Ota verify succeed')
print('Start Upgrade')
# 开始ota升级
param = {}
param['length'] = info['length']
param['store_path'] = info['store_path']
param['install_path'] = info['install_path']
ota.upgrade(param)
# ota 升级包结果回调函数
def on_upgrade(data):
if data >= 0 :
print('Ota succeed')
#ota升完级后 重启设备
reboot()
#当iot设备连接到物联网平台的时候触发'connect' 事件
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'] = data['handle']
# 初始化ota服务
ota.init(data_handle)
# ota 回调函数注册
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'] ,
"product_key": productKey ,
"device_name": deviceName ,
"module_name": module_name ,
"version": default_ver
}
# 上报本机ota相关信息,上报版本信息返回以后程序返回,知道后台推送ota升级包,才会调用on_trigger函数
ota.report(report_info)
#当连接断开时,触发'disconnect'事件
def on_disconnect():
print('linkkit is disconnected')
#当iot云端下发属性设置时,触发'props'事件
def on_props(request):
print('clound req data is {}'.format(request))
#当iot云端调用设备service时,触发'service'事件
def on_service(id,request):
print('clound req id is {} , req is {}'.format(id,request))
#当设备跟iot平台通信过程中遇到错误时,触发'error'事件
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
#NetWorkClient该类是一个单例类,实现网络管理相关的功能,包括初始化,联网,状态信息等.
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:
#注册网络连接的回调函数on(self,id,func); 1代表连接,func 回调函数 ;return 0 成功
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
kv = KV()
key = '_amp_customer_devicesecret'
deviceSecretdict = kv.getStorageSync(key)
if deviceSecretdict is not None:
deviceSecret = deviceSecretdict[key]
if deviceSecretdict is None or deviceSecret is None:
key_info = {
'productKey': productKey ,
'productSecret': productSecret ,
'deviceName': deviceName
}
# 动态注册一个设备,获取设备的deviceSecret
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 = "ggezd26tOuS"
productSecret = "PGTEUoksF4GUX0Ta"
device_dyn_resigter_succed = False
# 定义需要升级的模块和版本号
module_name = 'default'
default_ver = '2.0.1'
# 定义升级包的下载和安装路径,其中url,hash_type和hash 会通过服务端推送被保存下来
info = {
'url': '',
'store_path': '/data/pyamp/app.zip',
'install_path': '/data/pyamp/',
'length': 0,
'hash_type': '',
'hash': ''
}
# 连接网络
connect_network()
# 获取设备的IMEI 作为deviceName 进行动态注册
deviceName = modem.getDevImei()
#获取设备的ICCID
ICCID=modem.sim.getIccid()
#初始化物联网平台Device类,获取device实例
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_CONNECT 是事件,on_connect是事件处理函数/回调函数
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={
'param':FwVersionStr
}
time.sleep_ms(1000)
device.postProps(data0)
print("FwVersionStr:",FwVersionStr)
#将ICCID,IMEI数据放入字典
imei_iccid={}
imei_iccid["IMEI"]=deviceName
imei_iccid["ICCID"]=ICCID
#将字典转换为字符串
imei_iccid_str=ujson.dumps(imei_iccid)
data1={
'param':imei_iccid_str
}
#10S上报一次
time.sleep_ms(1000)
device.postProps(data1)
while True:
print('当前App版本号:' + default_ver)
print('等待Ota升级包.....')
print('--------------------------------------------------------------------')
time.sleep(1)
- board.json
{
"name": "haas506",
"version": "1.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"
}
- 实现步骤
(1)在阿里云物联网平台创建一个设备、打开动态注册
(2)在设备的功能定义中设置自定义功能,如IMEI、ICCID和FwVersion,然后发布上线
(3)在产品下创建一个设备,建议使用设备的IMEI号作为deviceName
(4)复制产品的productKey和productSecret,粘贴到程序的相应位置
(5)烧录程序,查看日志获取到当前版本为2.0.1
(6)当修改代码后,将代码中的default_ver改为2.0.6,保存
(7)将当前项目的x.py和board.json一起打包成xx.zip
(8)打开ota升级面板
(9)添加升级包,填写升级包名称、所属产品、升级包模块、升级包版本号、签名算法、上传升级包
(10)点击验证
(11)输入待升级版本号、待验证的设备
(12)验证中
(13)点击查看
(14)等待升级成功
(15)查看日志/设备详情,查看设备是否升级成功
2.class-ota
-
ota
- ota.init(param)
- 作用: 初始化ota服务
- 参数: param是一个字典,其中一个键’device_handle’ 很重要,它的值是连接物联网平台返回的device_handle
- 返回: 0成功
- ota.on(id, func)
- 作用: 注册ota升级相关的回调函数
- 参数: 回调函数的id和id所对应的回调函数
- 返回: 0成功
- 例如:ota.on(1,on_trigger),回调函数的id是1,回调函数是on_trigger()
- ota.report(param)
- 作用: 上报ota升级版本号,模块名等信息
- 参数: param是一个字典,包含上报的信息,如device_handle,product_key,device_name,module_name,version
- 返回: 0成功
属性 类型 说明 device_handle 指针 通过这个指针,获取mqtt连 接相关信息 product_key 字符串 物联网平台的产品key device_name 字符串 物联网平台的设备名称 module_name 字符串 需要升级的模块名称, app升级是’default’ version 字符串 python轻应用的版本号 - ota.download(param)
- 作用: 下载ota升级包
- 参数: param是一个字典,包含url,store_path
- 返回: 0成功
属性 类型 说明 url 字符串 ota包的下载链接 store_path 字符串 ota包的保存路径 - ota.verify(param)
- 作用: 升级包校验
- 参数: param是一个字典,包含length,store_path,hash,hash_type
- 返回: 0成功
属性 类型 说明 length 字符串 ota的升级包大小 store_path 字符串 ota包的保存路径 hash 字符串 目标ota的hash值 hash_type 字符串 ota包的hash签名类型 - ota.upgrade(param)
- 作用: 执行ota升级操作
- 参数: param是一个字典,包含length,store_path,install_path
- 返回: 0成功
属性 类型 说明 length 字符串 ota的升级包大小 store_path 字符串 ota包的保存路径 install_path 字符串 ota包的安装路径 - ota.init(param)
3.总结
本节介绍了如何使用haas506高级组件库中的ota模块,实现了ota升级功能。