阿里云物联网边缘计算加载MQTT驱动
寫在前面
本文在LinkEdge快速入門樣例驅(qū)動(dòng)的基礎(chǔ)上,加載了MQTT訂閱的客戶端,使得邊緣端容器可以通過MQTT獲得外部數(shù)據(jù)。
1.?????????系統(tǒng)需求
物聯(lián)網(wǎng)邊緣計(jì)算平臺(tái),又名Link IoT Edge[1]。在物聯(lián)網(wǎng)邊緣計(jì)算幫助文檔中的?“快速入門”描述了這樣一種應(yīng)用場景,“光照傳感器檢測(cè)室內(nèi)光照強(qiáng)度是否大于500 Lux,若光照強(qiáng)度大于500 Lux,則光照傳感器認(rèn)為室內(nèi)不需要開燈,從而去關(guān)閉燈(客廳燈開關(guān)等于1),否則打開燈(客廳燈開關(guān)等于0)。”
本文在該樣例的基礎(chǔ)上,在光照傳感器的驅(qū)動(dòng)程序上加載了MQTT訂閱的客戶端,使得光照傳感器可以通過訂閱的方式獲得光照強(qiáng)度值。
2.?????????系統(tǒng)架構(gòu)
????圖?1?給出了樣例的邊緣實(shí)例架構(gòu),樣例中LightSensor值是模擬值,通過定時(shí)器每2000毫秒執(zhí)行表格?1中代碼。
圖?1?邊緣實(shí)例架構(gòu)
表格?1?模擬值生成代碼
?
| ??????????if (self.lightSensor.illuminance >= 600) { ?????????????delta = -100; ???????????} else if (self.lightSensor.illuminance <= 100) { ?????????????delta = 100; ???????????} ??????????self.lightSensor.illuminance += delta; |
?
???圖?2給出了在在光照傳感器的驅(qū)動(dòng)程序上加載了MQTT訂閱的客戶端的架構(gòu)。
圖?2?光照傳感器驅(qū)動(dòng)掛載MQTT訂閱客戶端
3.?????????安裝部署
樣例完整的安裝和配置流程詳見幫助[2]。
4.?????????改寫驅(qū)動(dòng)
4.1.????????下載驅(qū)動(dòng)
下載LightSensor驅(qū)動(dòng)源碼,下載解壓后是一個(gè)index.js文件。
圖?3?下載驅(qū)動(dòng)
4.2.????????編寫驅(qū)動(dòng)
(1)???????index.js中添加MQTT訂閱客戶端代碼
表格?2?MQTT訂閱客戶端代碼
?
| 'use strict'; ? const { ??RESULT_SUCCESS, ??RESULT_FAILURE, ??ThingAccessClient, } = require('linkedge-thing-access-sdk'); ? var mqtt = require('/usr/bin/mqtt'); var options={username:'admin',password:'password',clientId:'Nodejs-ed16ef77-5cf2-4e5c-b511-1af14451df51'}; var client = mqtt.connect('mqtt://*.*.*.*:1883',options);???//?連接到MQTT服務(wù)端 ? var num = 0; var qtt = {}; ? qtt.id = '2002'; qtt.name = 'shoen'; qtt.age= 5000; ? client.subscribe('test',{qos:1});?????????????????????//訂閱主題為test的消息? ? client.on('message',function(top,message) {? ????qtt=JSON.parse(message.toString());?? }); ? // Max retry interval in seconds for registerAndOnline. const MAX_RETRY_INTERVAL = 30; |
?
(2)???????注釋原有模擬部分代碼,添加獲得值代碼。
?
表格?3?獲得數(shù)據(jù)來源
?
| ????????setInterval(function () { ??????????// if (self.lightSensor.illuminance >= 600) { ??????????//???delta = -100; ??????????// } else if (self.lightSensor.illuminance <= 100) { ??????????//???delta = 100; ??????????// } ??????????// self.lightSensor.illuminance += delta; ? ??????????if (self.client) { ????????????try { ??????????????self.lightSensor.illuminance = qtt.age; ??????????????var properties = {'MeasuredIlluminance': self.lightSensor.illuminance}; ??????????????console.log(`Report properties: ${JSON.stringify(properties)}`); ??????????????self.client.reportProperties(properties); ????????????} catch (err) { ??????????????console.log(err); ??????????????self.client.cleanup(); ????????????} ??????????} ????????}, 2000); |
?
4.3.????????重新部署
(1)???????將index.js壓縮成index.zip文件,注意index.zip僅包含index.js文件,不含其他任何文件夾。
(2)???????新建驅(qū)動(dòng)myLightSensor,上傳index.zip文件。
圖?4新建驅(qū)動(dòng)
(3)???????部署實(shí)例
圖?5?部署實(shí)例
5.?????????腳本解析
在部署過程中,我們通過link-iot-edge.sh {productkey} {devicename} {devicesecret}下載和啟動(dòng)邊緣計(jì)算平臺(tái)。
分析link-iot-edge.sh后,發(fā)現(xiàn)邊緣端實(shí)際是就是一個(gè)docker容器。其中主要幾行腳本含義如下描述:
圖?6?link-iot-edge.h源碼(局部)
n??docker pull "$LINKEDGE_IMG"
???LINKEDGE_IMG=$IMAGE_NAME_PREFIX:$1
???registry.cn-hangzhou.aliyuncs.com/iotedge/edge_x86_centosversion
n??docker run -d --rm --privileged=true -v linkedge_vol1:/usr/.security -v linkedge_vol2:/etc/.sec/ -v linkedge_vol3:/linkedge/gateway/build/.sst -v linkedge_vol4:/tmp/var/run/ -v linkedge_vol5:/linkedge/run --name=config-params $LINKEDGE_IMG $2 $3 $4
n??docker
???run創(chuàng)建一個(gè)新的容器并運(yùn)行一個(gè)命令
???-d后臺(tái)運(yùn)行容器,并返回容器ID
???--rm?容器退出時(shí)自動(dòng)清理容器并刪除文件系統(tǒng),
???--privileged=true?以特權(quán)方式啟動(dòng)容器,允許掛載宿主機(jī)目錄
???-v?linkedge_vol1:/usr/.security
宿主機(jī)的linkedge_vol1目錄掛載到容器的/usr/.security
???-v linkedge_vol2:/etc/.sec/
???-v linkedge_vol3:/linkedge/gateway/build/.sst
???-v linkedge_vol4:/tmp/var/run/
???-v linkedge_vol5:/linkedge/run
???--name=config-params?為容器指定一個(gè)名稱config-params
???$LINKEDGE_IMG?容器名稱
???$2 $3 $4三個(gè)均作為參數(shù)
n??為了方便訪問,修改以上啟動(dòng)腳本,使得容器內(nèi)可以訪問宿主機(jī)c:/test目錄。
???${preflag} docker run --rm --privileged=true?-v c:/test:/data?-v linkedge_vol1:/usr/.security -v linkedge_vol2:/etc/.sec/ -v linkedge_vol3:/linkedge/gateway/build/.sst -v linkedge_vol4:/tmp/var/run/ -v linkedge_vol5:/linkedge/run --name=config-params $LINKEDGE_IMG $2 $3 $4
?
6.?????????Node.js實(shí)現(xiàn)MQTT
n??安裝node
n??安裝npm install mqtt
6.1.????????MQTT服務(wù)端
本文采用Apollo MQTT作為MQTT服務(wù)器,安裝部署完畢后采用默認(rèn)用戶名admin,密碼password。MQTT服務(wù)器采用默認(rèn)的1883端口。
6.2.????????MQTT客戶端發(fā)布
表格?4?MQTT客戶端發(fā)布
?
| var mqtt = require('mqtt'); ? var options={username:'admin',password: 'password',clientId:'Nodejs-ed16ef77-5cf2-4e5c-b511-1af14451df58'}; var client = mqtt.connect('mqtt://*.*.*.*:1883',options);??//連接到MQTT服務(wù)端 ? var num = 0; var qtt = {}; ? qtt.id = '1001'; qtt.name = 'shoen'; qtt.age= 2222; ? client.publish('test', JSON.stringify(qtt), { qos: 0, retain: true });???? |
7.?????????設(shè)置容器
通過link-iot-edge.sh啟動(dòng)邊緣容器后,需要進(jìn)入容器安裝mqtt庫,并設(shè)置容器內(nèi)環(huán)境參數(shù),使得node.js編寫的mqtt客戶端能夠正確引用mqtt庫,即var mqtt = require('/usr/bin/mqtt');
設(shè)置主要步驟如下所示:
(1)???????啟動(dòng)容器:link-iot-edge.sh v1.7?a1xwL19pRAZ?mygw uPcoNbWHYselHGpwG2HRtMvh********
(2)???????進(jìn)入容器:docker exec -it config-params /bin/bash
(3)???????node.js設(shè)置引用
n??安裝淘寶cnpm:npm install -g cnpm --registry=https://registry.npm.taobao.org
n??全局安裝mqtt:cnpm install –g mqtt
n??查看cnpm全局倉庫路徑:cnpm?config?get?prefix
n??修改cnpm全局倉庫路徑:cnpm config set /usr/bin
n??以上設(shè)置完畢后,才可以代碼中添加引用:var mqtt = require('/usr/bin/mqtt');
n??以上設(shè)置重啟本容器失效
8.?????????容器命令
調(diào)試過程中涉及的相關(guān)容器命令如下:
(1)???????啟動(dòng)容器時(shí)映射宿主機(jī)和容器目錄:-v c:/test:/data
(2)???????查看IP地址:ip addr
(3)???????下載ifconfig:curl ifconfig.me
(4)???????find -name "*thing*"
n??linkedge-thing-access-sdk所在位置:./linkedge/gateway/build/bin/iot-gravity/runtime/nodejs8/node_modules/linkedge-thing-access-sdk
(5)???????查看容器鏡像docker image
(6)???????停止容器?docker stop?容器ID
(7)???????刪除鏡像?docker rmi?鏡像ID
9.?????????注意事項(xiàng)
(1)???????驅(qū)動(dòng)編寫錯(cuò)誤可能包括:庫文件未引用、node.js語法錯(cuò)誤,mqtt連接錯(cuò)誤;
(2)???????邊緣實(shí)例部署過程中,如發(fā)生以上錯(cuò)誤發(fā)生,光照傳感器將始終處于“離線”狀態(tài);
(3)???????本文宿主機(jī)為Windows 10,系統(tǒng)配置如下:
圖?7?Windows系統(tǒng)配置
10.?????最終效果
在宿主機(jī)上通過MQTT客戶端發(fā)布一個(gè)qtt.age=2222數(shù)據(jù),該數(shù)據(jù)會(huì)發(fā)送至MQTT服務(wù)器,容器內(nèi)加載的MQTT訂閱客戶端將收到該數(shù)據(jù),并將該數(shù)據(jù)賦值給self.lightSensor.illuminance,獲取的值將通過self.client.reportProperties(properties);上報(bào)至IOT Hub,最終在LightSensor運(yùn)行狀態(tài)中顯示光照度檢測(cè)值為2222Lux。
圖?8?最終效果
寫在后面
今年3月底深圳云棲大會(huì)后,和阿里云Linkedge團(tuán)隊(duì)幾位同學(xué)在西溪園區(qū)做了一次簡單的技術(shù)交流。阿里的同學(xué)介紹了物模型、容器等概念,我則提了異構(gòu)工業(yè)設(shè)備連接對(duì)于設(shè)備驅(qū)動(dòng)有較為強(qiáng)烈的需求……眨眼到了年底,Linkedge從公測(cè)到發(fā)布,直到今天(12-5)正式發(fā)布了v1.8,新加的幾項(xiàng)特性都值得關(guān)注,如“本地日志可以自動(dòng)同步到云端的日志服務(wù)產(chǎn)品中,支持按照業(yè)務(wù)功能進(jìn)行查詢。”這極大方便了運(yùn)維。此外,“支持C版本設(shè)備驅(qū)動(dòng)管理”,這對(duì)于我這樣一位老程序員(年紀(jì)大,而非經(jīng)驗(yàn)豐富)的吸引力是非常大的。
自10月17日開始試用Linkedge,學(xué)習(xí)時(shí)斷時(shí)續(xù),這個(gè)過程中Linkedge的幫助文檔不斷更新,導(dǎo)致前面截圖已失效。時(shí)至今日,終于輸出此文,雖然還沒有實(shí)現(xiàn)了詳細(xì)介紹如何在邊緣計(jì)算平臺(tái)上編寫驅(qū)動(dòng)的目標(biāo),但至少走通了關(guān)于驅(qū)動(dòng)的helloworld。最后,提幾點(diǎn)意見,希望Linkedge開發(fā)團(tuán)隊(duì)能有所改進(jìn):
(1)???????驅(qū)動(dòng)調(diào)試非常麻煩,幫助中沒有涉及調(diào)試方式。--這點(diǎn)從v1.8中的特性來看應(yīng)該有很大改善。
(2)???????邊緣容器設(shè)置細(xì)節(jié)應(yīng)對(duì)開發(fā)者開放。
(3)???????希望提供一個(gè)能和容器外(宿主機(jī)或其他設(shè)備)通訊的樣例,如通過串口、以太網(wǎng),這樣的樣例對(duì)于學(xué)習(xí)更加有效。
?
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的阿里云物联网边缘计算加载MQTT驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里高级技术专家:研发效能的追求永无止境
- 下一篇: 阿里云SDK再升级,宣布支持C++语言