來源 | 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();
});