华为IoT平台NB编解码插件开发详细教程【上篇】
目錄
0、前言
一、環(huán)境搭建
1.1 安裝JDK
1.2 安裝eclipse
1.3 安裝Maven
二、Profile說明
三、插件編寫
3.1 源文件說明
3.2 修改文件路徑(包含)
3.3 修改pom.xml
3.4 導(dǎo)入工程
3.5 代碼實(shí)現(xiàn)
3.6 生成jar包
0、前言
本教程分為上、下篇,原作者是我的同事llb90,征得其同意后在這里再次發(fā)布,希望能幫到有需求的人,demo可在Github下載。
本文通過一個(gè)比較簡單又不失全面的例子,說明一下華為IoT平臺編解碼插件線下開發(fā)的整個(gè)開發(fā)流程。對于環(huán)境的搭建盡量一筆帶過,對核心編碼部分做比較詳細(xì)的講解。第二章Profile部分會(huì)先出給一個(gè)小例子作為demo,編解碼的編寫按照該pfofile中定義的字段來解析,以方便大家理解編解碼插件中的代碼。本文編寫過程中主要參考了“華為IoT平臺NB-IoT設(shè)備集成開發(fā)指南.pdf”。
一、環(huán)境搭建
開發(fā)編解碼插件使用的IDE是eclipse,語言是Java。本文盡量以簡單的方式告訴你如何將華為提供的編解碼樣例修改為適合自己的編解碼插件。即使你沒有什么Java基礎(chǔ),只要懂得編程邏輯就好。跟著一起來吧!
1.1 安裝JDK
JDK版本1.8以上。參考網(wǎng)絡(luò)教程:https://blog.csdn.net/u010058695/article/details/100983213
1.2 安裝eclipse
下載并安裝eclipse。eclipse下載后解壓縮到本地即可運(yùn)行。
1.3 安裝Maven
下載地址是: http://maven.apache.org/download.cgi? 下載后的文件解壓縮即可,然后添加環(huán)境變量。
在eclipse中配置maven插件。打開eclipse,點(diǎn)擊window->Preferences,彈出如下窗口:
在彈出的窗口左側(cè)欄中,依次找到并點(diǎn)擊Maven->Installations,在右側(cè)點(diǎn)擊Add按鈕,彈出如下圖所示窗口:
點(diǎn)擊Directory,選擇Maven的路徑,然后Finish。到此,Maven配置完成。
二、Profile說明
Profile實(shí)際上是一系列關(guān)于設(shè)備模型的描述文件,每個(gè)文件都使用JSON格式(鍵值對)。
Profile中首先需要說明設(shè)備的基本信息,包括廠商ID,廠商名稱,設(shè)備類型,接入?yún)f(xié)議,以及設(shè)備可以提供的哪些服務(wù)等;其次,profile中要針對每一項(xiàng)服務(wù),用一個(gè)獨(dú)立的文件進(jìn)行詳細(xì)描述。服務(wù),可以理解為是對設(shè)備消息(上下行)功能的一個(gè)分類,一個(gè)服務(wù)就代表一類功能;每個(gè)服務(wù)下包含若干屬性和命令,每個(gè)屬性對應(yīng)上報(bào)消息中的某一個(gè)數(shù)據(jù),每個(gè)命令字段則對應(yīng)下行消息中的某些字段。比如,一個(gè)電表設(shè)備,會(huì)上報(bào)電池電量、功率、電能、電壓等,可以將電池電量放在Battery服務(wù)中,屬性值為batteryLevel,將功率、電能、電壓都放在Transmission服務(wù)中,分別對應(yīng)該服務(wù)下的Power、Energy、Voltage屬性??梢栽谝粭l消息中上報(bào)所有服務(wù)的所有屬性,也可以分開上報(bào)。
本例中提供的profile信息,基本信息如下:
設(shè)備類型: MyType 設(shè)備型號: MyModel 廠商ID : ThirdParty 廠商名稱: ThirdParty 協(xié)議: Coap數(shù)據(jù)服務(wù)有兩項(xiàng):Battery,包含一個(gè)屬性BatteryLevel,兩個(gè)字節(jié);Transmission,包含一個(gè)屬性upData,不定長數(shù)組(profile中表示不定長數(shù)組,需將屬性類型定義為string,長度設(shè)為一個(gè)比較大的數(shù));包含一條下行命令CLOUDREQ,有兩個(gè)命令字段;cmdType,一個(gè)字節(jié);downData,不定長數(shù)組。
profile采用在線開發(fā)的方式,如下圖所示:
本例中,采用一條消息上報(bào)所有服務(wù)屬性的方式。上報(bào)數(shù)據(jù)格式為:前兩個(gè)字節(jié)表示batteryLevel屬性,大端方式;第三個(gè)字節(jié)表示后續(xù)數(shù)據(jù)長度;第四個(gè)字節(jié)至最后,表示upData屬性。下行命令數(shù)據(jù)格式為:第一個(gè)字節(jié)表示cmdType;第二個(gè)字節(jié)至最后,表示downData。(請仔細(xì)理解該數(shù)據(jù)格式,插件的編寫就是按照數(shù)據(jù)格式解析出對應(yīng)的屬性值)。
三、插件編寫
3.1 源文件說明
從華為資源中心下載編解碼插件Demo,并解壓到本地。文件結(jié)構(gòu)如下圖所示:
源代碼在src文件夾下;編譯生成的插件包在target文件夾下。src 文件夾包含 main 、test 兩個(gè)子文件夾,main下存放源碼,test下是單元測試代碼。官網(wǎng)下載的Demo中,源碼的路徑是:src\main\java\com\Huawei\NBIoTDevice\WaterMeter,單元測試代碼的路徑是:src\test\java\com\Huawei\NBIoTDevice\WaterMeter。
插件源碼文件有5個(gè):
(a)ProtocolAdapterImpl.java 可以理解為是插件的入口文件,對外提供調(diào)用接口。該文件只需要修改兩個(gè)字符串的定義即可:
// 廠商名稱 private static final String MANU_FACTURERID = "Huawei"; // 設(shè)備型號 private static final String MODEL = "NBIoTDevice";? 修改為profile當(dāng)中定義的廠商ID和設(shè)備型號。
(b)CmdProcess.java 實(shí)現(xiàn)下行命令的編碼工作,將從收到的服務(wù)器報(bào)文中提取出命令字段對應(yīng)的內(nèi)容,并將其轉(zhuǎn)換成字節(jié)流。需要實(shí)現(xiàn)的函數(shù)是:
public byte[] toByte()(c)ReportProcess.java 實(shí)現(xiàn)將收到的二進(jìn)制碼流按照格式解碼出對應(yīng)profile中的屬性值,并生成JSON格式。需要實(shí)現(xiàn)的函數(shù)是:
//根據(jù)二進(jìn)制碼流的格式,從中取出對應(yīng)字節(jié),轉(zhuǎn)換成profile中對應(yīng)屬性的值 public ReportProcess(byte[] binaryData) //將解碼出來的屬性值封裝成JSON格式 public ObjectNode toJsonNode()(d)ByteBufUtils.java 和 Utilty.java文件封裝了一些公共方法,不用做修改。也不會(huì)使用到。
3.2 修改文件路徑(包含)
插件包名的要求是:com.廠商名稱.設(shè)備型號.設(shè)備類型。因此下載下來的代碼,要根據(jù)自己的設(shè)備修改下文件路徑。即將Huawei文件夾重命名為profile中定義的廠商名稱,NBIoTDevice文件夾重命名為profile中定義的設(shè)備型號,WaterMeter文件夾重命名為profile中定義的設(shè)備類型。注意:src\main 和src\test 下都要修改。在本例中,需要修改為:
src\main\java\com\ThirdParty\MyModel\MyTyp, src\test\java\com\ThirdParty\MyModel\MyType3.3 修改pom.xml
打開pom.xml文件,修改第7行“artifactId”和第88行“Bundle-SymbolicName”的值為:設(shè)備類型-廠商ID-設(shè)備型號。在本例中,需要修改為:MyType-ThirdParty-MyModel。
3.4 導(dǎo)入工程
打開eclipse,點(diǎn)擊file->import,在彈出窗口中選擇maven工程,如下圖所示:
之后在彈出的窗口中,點(diǎn)擊Browse,選擇工程路徑(pom.xml文件所在路徑)。工程導(dǎo)入后如下圖所示:
從圖8可以看到首次導(dǎo)入工程后是有錯(cuò)誤的。這是因?yàn)槲覀冊诘?節(jié)中將文件路徑修改了,與代碼里面的包路徑不一致引起的。解決方法為:依次打開源文件,將第一行的
package com.Huawei.NBIoTDevice.WaterMeter;
修改為
package com.ThirdParty.MyModel.MyType;
打開OSGI_INF目錄下的CodeProvideHandler.xml 文件:
打開后,文件內(nèi)容如下圖所示:
將Name 、 Class* 內(nèi)的路徑也修改為對應(yīng)的包路徑:
3.5 代碼實(shí)現(xiàn)
前面說明了各個(gè)源文件要修改的地方,本節(jié)中具體講解實(shí)現(xiàn)的方法。
(a)修改ProtocolAdatpterImpl.java文件
在文件中找到如下兩行:
// 廠商名稱 private static final String MANU_FACTURERID = "Huawei"; // 設(shè)備型號 private static final String MODEL = "NBIoTDevice";將MANU_FACTURERID?和 MODEL定義修改為profile中定義的廠商ID和設(shè)備型號,本例中需要修改為:
// 廠商名稱 private static final String MANU_FACTURERID = "ThirdParty"; // 設(shè)備型號 private static final String MODEL = "MyModel";(b)解碼實(shí)現(xiàn)
解碼,是將NB模組上報(bào)的二進(jìn)制碼流按格式解析出對應(yīng)字段的過程。解碼的代碼在ReportProcess.java 文件中。
第一個(gè)函數(shù):public ReportProcess(byte[] binaryData) 入?yún)?byte[] binaryData就是NB模組上報(bào)的二進(jìn)制碼流。解碼得到數(shù)據(jù)存儲(chǔ)在成員變量當(dāng)中。本例中的代碼實(shí)現(xiàn)如下:
NB上報(bào)二進(jìn)制數(shù)據(jù)的格式為:前兩個(gè)字節(jié)表示batteryLevel,大端,整型;第三個(gè)字節(jié)表示后邊還有多少字節(jié);第四個(gè)字節(jié)往后表示不定長字段upData。因此,解碼的思路便是:
System.arraycopy 是JDK提供的數(shù)組拷貝函數(shù):第一個(gè)參數(shù)是源數(shù)組,第二個(gè)參數(shù)是偏移,表示從源數(shù)組的第幾個(gè)字節(jié)開始拷貝,第三個(gè)參數(shù)是目的數(shù)組,第四個(gè)參數(shù)是目的數(shù)組的偏移,第5個(gè)參數(shù)表示拷貝的長度。
第二個(gè)函數(shù):public ObjectNode toJsonNode() 返回一個(gè)ObjectNode對象(JSON)。該函數(shù)的功能,是將解碼后得到的數(shù)據(jù),按照規(guī)定格式填入一個(gè)JSON對象中。本例中,生成的JSON對象的內(nèi)容格式如下圖所示:
JSON對象的內(nèi)容格式要求是:"msgType":? "deviceReq",? 表示設(shè)備上報(bào)數(shù)據(jù),固定不動(dòng);“data”:數(shù)組對象,數(shù)組中的每個(gè)元素分別對應(yīng)profile中的一個(gè)服務(wù);“serviceID”的值是profile中定義的服務(wù)名稱;“serviceData”的值是該服務(wù)下所有的屬性值。(本例中,profile定義了兩個(gè)服務(wù),Battery服務(wù)中有一個(gè)BatteryLevel屬性;Transmission服務(wù)中有一個(gè)upData屬性)。由圖13的“upData”的值可以看出,數(shù)組類型的值,需要將二進(jìn)制流轉(zhuǎn)成base64編碼的格式。
該函數(shù)的代碼實(shí)現(xiàn)如下圖所示:
該函數(shù)代碼比較簡單,主要是用到了 ObjectMapper 這個(gè)類,該類提供了JAVA中操作JSON數(shù)據(jù)的方法,可對照圖13上報(bào)數(shù)據(jù)格式,仔細(xì)理解該部分代碼。
(c)編碼實(shí)現(xiàn)
編碼,是將IoT平臺收到的服務(wù)器下行數(shù)據(jù)(服務(wù)器下行數(shù)據(jù)是http或者h(yuǎn)ttps協(xié)議),從中提取出下行字段,并將其拼成二進(jìn)制碼流。編碼部分的代碼在 CmdProcess.java 文件中。需要實(shí)現(xiàn)的函數(shù)是:public byte[] toByte()
本例中,該函數(shù)的實(shí)現(xiàn)代碼如下圖所示:
服務(wù)器下行命令的JSON數(shù)據(jù)格式是:
"msgType": "cloudReq", 固定值,表示服務(wù)器下行命令;
"serviceId",profile中對應(yīng)的服務(wù),本例中是"Transmission",
"cmd",profile中定義的下行命令,本例中是"CLOUDREQ",
"paras",profile中定義的下行命令的各個(gè)字段,本例中是cmdType和downData兩個(gè)字段;圖16中,cmdType的值是2,downData是一個(gè)不定長數(shù)組,base64編碼格式。
因此,編碼的思路是:
3.6 生成jar包
經(jīng)過前面的工作后,代碼就已經(jīng)準(zhǔn)備好了,接下來是生成JAR包。在DOS窗口中進(jìn)入pom.xml文件所在路徑,執(zhí)行 mvn package 命令,最后彈出如下圖所示的結(jié)果,則表明生成Jar包成功。如果有錯(cuò)誤,則根據(jù)提示再去修改代碼,然后重新執(zhí)行 mvn package。
在工程目錄的target文件夾下,存放生成的JAR包“MyType-ThirdParty-MyModel-1.0.0.jar”。JAR包的命名規(guī)則是:
設(shè)備類型-廠商ID-設(shè)備型號-版本號.jar
好,至此插件編寫任務(wù)完成。插件打包、插件質(zhì)檢、插件簽名等內(nèi)容見下篇教程。
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的华为IoT平台NB编解码插件开发详细教程【上篇】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机网络技术课程代码02141模拟试题
- 下一篇: .net 2005大写html标签 xh