来源 | HaaS技术社区
1、功能简介
OTA升级是很多嵌入式产品必备的一个功能。HaaS 轻应用提供了完备的OTA解决方案。本案例就是一个升级JavaScript脚本的端云一体化例子,用户可以通过JavaScript脚本实现应用脚本的版本上报,下载,完整性检验和脚本加载;具体流程如下图所示:
1.1、设备联网
在做脚本升级前确保设备是连网上线的,连网需要加入IOT组件,如果是wifi设备,需要加入netmgr组件进行配网,所以如上代码中,引入了iot组件和netmgr组件
import * as netmgr from 'netmgr';
import * as iot from 'iot';
还需要添加设备的三元组信息:
var productKey = ' '; /* your productKey */
var deviceName = ' '; /* your deviceName */
var deviceSecret = ' '; /* your deviceSecret */
通过调用如下代码:
var device = iot.device({
productKey: productKey,
deviceName: deviceName,
deviceSecret: deviceSecret
});
实现设备的上线;
1.2、版本上报
当设备上线后,需要将脚本的版本号报上云端,所以需要事先定义好脚本的版本,如示例代码定义的版本为:
var default_ver = '2.0.0';
由于阿里云IoT物联平台OTA是多模块升级方式,所以还需要定义一个模块名称,如果当前的脚本为设备的主业务,模块名称必须为"default",如示例代码:
var module_name = 'default';
版本号和模块名定义完成后,配合设备名和产品密钥,调用如下代码可实现版本号上报云端:
ota.report({
device_handle: iotDeviceHandle,
product_key: productKey,
device_name: deviceName,
module_name: module_name,
version: default_ver
});
ota.report接口用来将脚本版本号上报云端,入参有5个,第一个为IOT 设备handlem,设备成功连网后,会返回整个对象,第二参数为产品的密钥,第三个参数为设备名称,第四个参数为要上报版本模块的名称;
完成以上调用后,在阿里云物联网平台会看到如下信息:
上图中的default模块版本即为脚本中填入的版本号,system模块的版本为当前运行JS的OS系统版本;
1.3、脚本上传云端
首先需要做个高版本的js脚本,将步骤2中的JS版本号改成 var default_ver = '3.0.0';,然后创建一个app.json文件,文件内容如下:
{
"version": "3.0.0",
"io": {},
"debugLevel": "DEBUG"
}
此文件主要是JS配套的配置,如设备端的io配置以及JS的版本号(与JS脚本中的版本号要相同);将app.js和app.json放到一个文件夹中,用JS工具打包成app.bin;JS工具用法请参考"命令行工具的pack命令使用";
打包完成后请参考下图完成固件上传到云端:
1.4、云端触发升级
JS脚本上传完成后,云端触发升级,如下图:
1.5、获取升级文件信息
当云端触发升级后,设备端会收到云端的发送的脚本信息,具体包括:文件大小、url、模块名称、hash type(md5或sha256)、hash值;对应上面的代码为:
ota.on('new', function(res) {
console.log('length is ' + res.length);
console.log('module_name is ' + res.module_name);
console.log('version is ' + res.version);
console.log('url is ' + res.url);
console.log('hash is ' + res.hash);
console.log('hash_type is ' + res.hash_type);
1.6、下载升级文件
通过步骤5设备端已拿到云端即将下发文件的版本号、url、模块名等,用户可根据需求决定是否下载此文件,比如版本比对,发现版本号较当前版本小,可以选择不下载,还可以通过模块名称判断下载的是什么文件,如模块名称为default,则下载的是JS脚本,用户可根据自己需要自己定义; 如用设备需要下载此文件,则通过download方法可实现下载,如示例代码:
ota.download({
url: info.url,
store_path: info.store_path
}, function(res) {
下载接口,需要填入的参数有2个,第一参数为文件的URL,第二参数为文件的存储路径,包括存储的文件名称,如示例代码定义的:
var info = {
url: '',
store_path: '/data/jsamp/pack.bin',
1.7、校验升级文件
当文件下载完成后,需要验证文件下载的是否完整,需要调用verify验证,如上面示例代码:
ota.verify({
length: info.length,
hash_type: info.hashType,
hash: info.hash,
store_path: info.store_path
}, function(res) {
ota.verify入参有4个,分别为,下载文件的长度、云端下发的hash type(md5或sha256)、对应的hash值以及存储已下载文件的路径,这些参数已通过步骤5全部获取,直接填入即可;
1.8、加载升级文件
当步骤7校验成功后,即可实现脚本文件的加载,此时调用upgrade即可实现脚本的重新加载,如上面的示例代码:
ota.upgrade({
length: info.length,
store_path: info.store_path,
install_path: info.install_path
}, function(res)
ota.upgrade有3个入参,第一个为下载文件的长度,第二入参为已下载文件的路径,第三个参数为要安装的路径,如示例代码定义的安装路径:
install_path: '/data/jsamp/',
如果升级成功,脚本会重新加载,上报版本号,云端状态如下图所示:
2、OTA接口介绍
open(Object option)
属性 |
类型 |
必填 |
描述 |
iot |
Text |
是 |
传入IOT组件的device handle |
report(Object option)
属性 |
类型 |
必填 |
描述 |
device_handle |
Number |
是 |
传入IOT组件的device handle指针 |
product_key |
String |
是 |
设备的产品密钥 |
device_name |
String |
是 |
设备名称 |
module_name |
String |
是 |
模块名称 |
version |
String |
是 |
模块的版本号 |
dowload(Object option, Function callback)
属性 |
类型 |
必填 |
描述 |
url |
String |
是 |
下载文件的URL |
store_path |
String |
是 |
存储下载文件的路径包括文件名称 |
callback |
Function |
是 |
下载完后的回调函数 |
verify(Object option, Function callback)
属性 |
类型 |
必填 |
描述 |
length |
String |
是 |
下载文件的长度 |
hash_type |
String |
是 |
是md5还是sha256 |
store_path |
String |
是 |
存储下载文件的路径 |
callback |
Functiom |
是 |
校验结果的回调函数 |
upgrade(Object option, Function callback)
属性 |
类型 |
必填 |
描述 |
length |
String |
是 |
下载文件的长度 |
store_path |
String |
是 |
存储下载文件的路径 |
install_path |
String |
是 |
安装脚本的路径 |
callback |
Function |
是 |
升级成功的回调函数 |
3、参考代码
import * as netmgr from 'netmgr';
import * as iot from 'iot';
import * as appota from 'appota'
//此脚本包含了wifi连网功能,仅适合haas100、haaseduk1
var productKey = ''; /* your productKey */
var deviceName = ''; /* your deviceName */
var deviceSecret = ''; /* your deviceSecret */
var device;
var module_name = 'default';
var default_ver = '2.0.0';
var ota;
var status;
/* download info */
var info = {
url: '',
store_path: '/data/jsamp/pack.bin',
install_path: '/data/jsamp/',
length: 0,
hashType: '',
hash: ''
}
function createDevice() {
device = iot.device({
productKey: productKey,
deviceName: deviceName,
deviceSecret: deviceSecret,
region: 'cn-shanghai',
});
device.on('connect', function () {
console.log('(re)connected');
var iotDeviceHandle = device.getDeviceHandle();
console.log('get device handle module');
ota = appota.open(iotDeviceHandle);
console.log('report default module ver');
ota.report({
device_handle: iotDeviceHandle,
product_key: productKey,
device_name: deviceName,
module_name: module_name,
version: default_ver
});
ota.on('new', function(res) {
console.log('length is ' + res.length);
console.log('module_name is ' + res.module_name);
console.log('version is ' + res.version);
console.log('url is ' + res.url);
console.log('hash is ' + res.hash);
console.log('hash_type is ' + res.hash_type);
info.url = res.url;
info.length = res.length;
info.module_name = res.module_name;
info.version = res.version;
info.hash = res.hash;
info.hashType = res.hash_type;
ota.download({
url: info.url,
store_path: info.store_path
}, function(res) {
if (res >= 0) {
console.log('download success');
console.log('verify start');
console.log(info.hashType);
ota.verify({
length: info.length,
hash_type: info.hashType,
hash: info.hash,
store_path: info.store_path
}, function(res) {
if (res >= 0) {
console.log('verify success');
console.log('upgrade start');
ota.upgrade({
length: info.length,
store_path: info.store_path,
install_path: info.install_path
}, function(res) {
if (res >= 0) {
console.log('upgrade success')
} else {
console.log('upgrade failed')
}
})
} else {
console.log('verify failed');
}
})
} else {
console.log('download failed');
}
});
});
});
}
var network = netmgr.openNetMgrClient({
name: '/dev/wifi0'
});
var status;
status = network.getState();
console.log('status is ' + status);
network.connect({
ssid: '', //请替换为自己的热点ssid
password: '' //请替换为自己热点的密码
});
network.on('error', function () {
console.log('error ...');
});
network.on('connect', function () {
createDevice();
});