華爲IoT平臺NB編解碼插件開發詳細教程【上篇】

目錄

0、前言

一、環境搭建

1.1 安裝JDK

1.2 安裝eclipse

1.3 安裝Maven

二、Profile說明

三、插件編寫

3.1 源文件說明

3.2 修改文件路徑(包含)

3.3 修改pom.xml

3.4 導入工程

3.5 代碼實現

3.6 生成jar包


0、前言

本教程分爲上、下篇,原作者是我的同事llb90,徵得其同意後在這裏再次發佈,希望能幫到有需求的人,demo可在Github下載

本文通過一個比較簡單又不失全面的例子,說明一下華爲IoT平臺編解碼插件線下開發的整個開發流程。對於環境的搭建儘量一筆帶過,對核心編碼部分做比較詳細的講解。第二章Profile部分會先出給一個小例子作爲demo,編解碼的編寫按照該pfofile中定義的字段來解析,以方便大家理解編解碼插件中的代碼。本文編寫過程中主要參考了“華爲IoT平臺NB-IoT設備集成開發指南.pdf”。

一、環境搭建

開發編解碼插件使用的IDE是eclipse,語言是Java。本文儘量以簡單的方式告訴你如何將華爲提供的編解碼樣例修改爲適合自己的編解碼插件。即使你沒有什麼Java基礎,只要懂得編程邏輯就好。跟着一起來吧!

1.1 安裝JDK

JDK版本1.8以上。參考網絡教程:https://blog.csdn.net/u010058695/article/details/100983213

1.2 安裝eclipse

下載並安裝eclipse。eclipse下載後解壓縮到本地即可運行。

1.3 安裝Maven

下載地址是: http://maven.apache.org/download.cgi  下載後的文件解壓縮即可,然後添加環境變量。

在eclipse中配置maven插件。打開eclipse,點擊window->Preferences,彈出如下窗口:

在彈出的窗口左側欄中,依次找到並點擊Maven->Installations,在右側點擊Add按鈕,彈出如下圖所示窗口:

點擊Directory,選擇Maven的路徑,然後Finish。到此,Maven配置完成。

二、Profile說明

Profile實際上是一系列關於設備模型的描述文件,每個文件都使用JSON格式(鍵值對)。

Profile中首先需要說明設備的基本信息,包括廠商ID,廠商名稱,設備類型,接入協議,以及設備可以提供的哪些服務等;其次,profile中要針對每一項服務,用一個獨立的文件進行詳細描述。服務,可以理解爲是對設備消息(上下行)功能的一個分類,一個服務就代表一類功能;每個服務下包含若干屬性和命令,每個屬性對應上報消息中的某一個數據,每個命令字段則對應下行消息中的某些字段。比如,一個電錶設備,會上報電池電量、功率、電能、電壓等,可以將電池電量放在Battery服務中,屬性值爲batteryLevel,將功率、電能、電壓都放在Transmission服務中,分別對應該服務下的Power、Energy、Voltage屬性。可以在一條消息中上報所有服務的所有屬性,也可以分開上報。

本例中提供的profile信息,基本信息如下:

設備類型: MyType
設備型號: MyModel
廠商ID  : ThirdParty
廠商名稱: ThirdParty
協議:     Coap

數據服務有兩項:Battery,包含一個屬性BatteryLevel,兩個字節;Transmission,包含一個屬性upData,不定長數組(profile中表示不定長數組,需將屬性類型定義爲string,長度設爲一個比較大的數);包含一條下行命令CLOUDREQ,有兩個命令字段;cmdType,一個字節;downData,不定長數組。

profile採用在線開發的方式,如下圖所示:

本例中,採用一條消息上報所有服務屬性的方式。上報數據格式爲:前兩個字節表示batteryLevel屬性,大端方式;第三個字節表示後續數據長度;第四個字節至最後,表示upData屬性。下行命令數據格式爲:第一個字節表示cmdType;第二個字節至最後,表示downData。(請仔細理解該數據格式,插件的編寫就是按照數據格式解析出對應的屬性值)。

三、插件編寫

3.1 源文件說明

從華爲資源中心下載編解碼插件Demo,並解壓到本地。文件結構如下圖所示:

源代碼在src文件夾下;編譯生成的插件包在target文件夾下。src 文件夾包含 main 、test 兩個子文件夾,main下存放源碼,test下是單元測試代碼。官網下載的Demo中,源碼的路徑是:src\main\java\com\Huawei\NBIoTDevice\WaterMeter,單元測試代碼的路徑是:src\test\java\com\Huawei\NBIoTDevice\WaterMeter。

插件源碼文件有5個:

(a)ProtocolAdapterImpl.java 可以理解爲是插件的入口文件,對外提供調用接口。該文件只需要修改兩個字符串的定義即可:

// 廠商名稱
private static final String MANU_FACTURERID = "Huawei";
// 設備型號
private static final String MODEL = "NBIoTDevice";

  修改爲profile當中定義的廠商ID和設備型號。

(b)CmdProcess.java 實現下行命令的編碼工作,將從收到的服務器報文中提取出命令字段對應的內容,並將其轉換成字節流。需要實現的函數是:

public byte[] toByte()

(c)ReportProcess.java 實現將收到的二進制碼流按照格式解碼出對應profile中的屬性值,並生成JSON格式。需要實現的函數是:

//根據二進制碼流的格式,從中取出對應字節,轉換成profile中對應屬性的值
public ReportProcess(byte[] binaryData)
//將解碼出來的屬性值封裝成JSON格式
public ObjectNode toJsonNode()

(d)ByteBufUtils.java 和 Utilty.java文件封裝了一些公共方法,不用做修改。也不會使用到。

3.2 修改文件路徑(包含)

插件包名的要求是:com.廠商名稱.設備型號.設備類型。因此下載下來的代碼,要根據自己的設備修改下文件路徑。即將Huawei文件夾重命名爲profile中定義的廠商名稱,NBIoTDevice文件夾重命名爲profile中定義的設備型號,WaterMeter文件夾重命名爲profile中定義的設備類型。注意:src\main 和src\test 下都要修改。在本例中,需要修改爲:

src\main\java\com\ThirdParty\MyModel\MyTyp,
src\test\java\com\ThirdParty\MyModel\MyType

3.3 修改pom.xml

打開pom.xml文件,修改第7行“artifactId”和第88行“Bundle-SymbolicName”的值爲:設備類型-廠商ID-設備型號。在本例中,需要修改爲:MyType-ThirdParty-MyModel。

3.4 導入工程

打開eclipse,點擊file->import,在彈出窗口中選擇maven工程,如下圖所示:

之後在彈出的窗口中,點擊Browse,選擇工程路徑(pom.xml文件所在路徑)。工程導入後如下圖所示:

從圖8可以看到首次導入工程後是有錯誤的。這是因爲我們在第2節中將文件路徑修改了,與代碼裏面的包路徑不一致引起的。解決方法爲:依次打開源文件,將第一行的

package com.Huawei.NBIoTDevice.WaterMeter;

修改爲

package com.ThirdParty.MyModel.MyType;

打開OSGI_INF目錄下的CodeProvideHandler.xml 文件:

打開後,文件內容如下圖所示:

將Name 、 Class* 內的路徑也修改爲對應的包路徑:

3.5 代碼實現

前面說明了各個源文件要修改的地方,本節中具體講解實現的方法。

(a)修改ProtocolAdatpterImpl.java文件

在文件中找到如下兩行:

// 廠商名稱
private static final String MANU_FACTURERID = "Huawei";
// 設備型號
private static final String MODEL = "NBIoTDevice";

MANU_FACTURERID MODEL定義修改爲profile中定義的廠商ID和設備型號,本例中需要修改爲:

// 廠商名稱
private static final String MANU_FACTURERID = "ThirdParty";
// 設備型號
private static final String MODEL = "MyModel";

(b)解碼實現

解碼,是將NB模組上報的二進制碼流按格式解析出對應字段的過程。解碼的代碼在ReportProcess.java 文件中。

第一個函數:public ReportProcess(byte[] binaryData) 入參 byte[] binaryData就是NB模組上報的二進制碼流。解碼得到數據存儲在成員變量當中。本例中的代碼實現如下:

NB上報二進制數據的格式爲:前兩個字節表示batteryLevel,大端,整型;第三個字節表示後邊還有多少字節;第四個字節往後表示不定長字段upData。因此,解碼的思路便是:

  1. 首先判斷數據長度是否合法,至少應爲3個字節,對應第37行代碼;數據長度應不小於第3個字節的值加上3,對應第42行代碼。該部分代碼屬於保護性代碼。
  2. 將前兩個字節拼成一個16位的整型數據,表示batteryLevel,對應第47行代碼。
  3. 根據第三個字節的值,創建一個Byte數組,將第四個字節往後的內容拷貝至該數組內,得到upData。對應第50~53行代碼。

System.arraycopy 是JDK提供的數組拷貝函數:第一個參數是源數組,第二個參數是偏移,表示從源數組的第幾個字節開始拷貝,第三個參數是目的數組,第四個參數是目的數組的偏移,第5個參數表示拷貝的長度。

第二個函數:public ObjectNode toJsonNode() 返回一個ObjectNode對象(JSON)該函數的功能,是將解碼後得到的數據,按照規定格式填入一個JSON對象中。本例中,生成的JSON對象的內容格式如下圖所示:

JSON對象的內容格式要求是:"msgType":  "deviceReq",  表示設備上報數據,固定不動;“data”:數組對象,數組中的每個元素分別對應profile中的一個服務;“serviceID”的值是profile中定義的服務名稱;“serviceData”的值是該服務下所有的屬性值。(本例中,profile定義了兩個服務,Battery服務中有一個BatteryLevel屬性;Transmission服務中有一個upData屬性)。由圖13的“upData”的值可以看出,數組類型的值,需要將二進制流轉成base64編碼的格式。

該函數的代碼實現如下圖所示:

該函數代碼比較簡單,主要是用到了 ObjectMapper 這個類,該類提供了JAVA中操作JSON數據的方法,可對照圖13上報數據格式,仔細理解該部分代碼。

(c)編碼實現

編碼,是將IoT平臺收到的服務器下行數據(服務器下行數據是http或者https協議),從中提取出下行字段,並將其拼成二進制碼流。編碼部分的代碼在 CmdProcess.java 文件中。需要實現的函數是:public byte[] toByte()

本例中,該函數的實現代碼如下圖所示:

服務器下行命令的JSON數據格式是:

"msgType": "cloudReq", 固定值,表示服務器下行命令;

"serviceId",profile中對應的服務,本例中是"Transmission",

"cmd",profile中定義的下行命令,本例中是"CLOUDREQ",

"paras",profile中定義的下行命令的各個字段,本例中是cmdType和downData兩個字段;圖16中,cmdType的值是2,downData是一個不定長數組,base64編碼格式。

因此,編碼的思路是:

  1. 判斷下行命令是否是profile中定義的。對應第77行代碼。
  2. 獲取cmdType字段的值,該值佔一個字節。對應第78行代碼。
  3. 獲取downData的值,該值是base64編碼形式,需轉成二進制碼流,對應第79行代碼。
  4. 將兩個字段的值拼接成一個二進制數組,並返回。對應第81~84行代碼。

3.6 生成jar包

經過前面的工作後,代碼就已經準備好了,接下來是生成JAR包。在DOS窗口中進入pom.xml文件所在路徑,執行 mvn package 命令,最後彈出如下圖所示的結果,則表明生成Jar包成功。如果有錯誤,則根據提示再去修改代碼,然後重新執行 mvn package。

在工程目錄的target文件夾下,存放生成的JAR包“MyType-ThirdParty-MyModel-1.0.0.jar”。JAR包的命名規則是:

設備類型-廠商ID-設備型號-版本號.jar

好,至此插件編寫任務完成。插件打包、插件質檢、插件簽名等內容見下篇教程。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章