中国电信物联网开放平台V100R001C30编解码库开发与升级指南.docx
《中国电信物联网开放平台V100R001C30编解码库开发与升级指南.docx》由会员分享,可在线阅读,更多相关《中国电信物联网开放平台V100R001C30编解码库开发与升级指南.docx(32页珍藏版)》请在冰豆网上搜索。
![中国电信物联网开放平台V100R001C30编解码库开发与升级指南.docx](https://file1.bdocx.com/fileroot1/2023-1/4/89c141f0-1bd0-4881-8604-9c305ea00a63/89c141f0-1bd0-4881-8604-9c305ea00a631.gif)
中国电信物联网开放平台V100R001C30编解码库开发与升级指南
中国电信物联网开放平台V100R001C30编解码库开发与升级指南
(V1)
二〇一九年三月
编制单位:
编制单位
修订记录:
版本号
日期
描述
01
2017/11/06
中国电信物联网开放平台V100R001C30编解码库开发与升级指南
目录
1整体方案1
2消息处理流程2
3接口说明3
3.1decode接口说明4
3.2encode接口说明6
3.3getManufacturerId接口说明8
3.4getModel接口说明8
3.5接口实现注意事项8
4数据参考样例12
5实现样例讲解14
6编解码插件打包19
7实现样例附件22
8编解码升级指南23
1整体方案
NB-IoT设备和中国电信物联网开放平台之间采用CoAP协议通讯(注:
在设备侧,CoAP协议栈一般由NB-IOT芯片模组实现),CoAP消息的payload为应用层数据,应用层数据的格式由设备自行定义。
由于NB-IoT设备一般对省电要求较高,所以应用层数据一般不采用流行的json格式,而是采用二进制格式或者tlv格式。
设备厂商需要提供编解码插件,平台负责调用编解码插件,实现二进制消息转json格式的功能,以提供APPserver使用,如下图所示。
图1-1整体方案
2消息处理流程
上行消息处理
图2-1上行消息处理流程
下行消息处理
图2-1下行消息处理流程
3接口说明
厂商需要提供一个符合OSGI规范的jar包(jdk版本1.8),该jar包需要实现我们提供的com.huawei.m2m.cig.tup-1.3.1.jar中的IProtocolAdapter接口。
com.huawei.m2m.cig.tup-1.3.1.jar在本文的最后codecDemo.zip文件中的codecDemo.zip\codecDemo\lib目录下可以获取。
接口代码如下:
importcom.fasterxml.jackson.databind.node.ObjectNode;
publicinterfaceIProtocolAdapter{
StringVERSION="2";
defaultStringgetVersion(){
returnVERSION;
}
StringgetManufacturerId();
StringgetModel();
ObjectNodedecode(finalbyte[]binaryData)throwsException;
byte[]encode(finalObjectNodeinput)throwsException;
}
为方便问题定位,开发者需要在编解码插件日志中打印必要的定位信息(包括但不限于设备上报信息、命令下发信息等),并对敏感信息做脱敏处理。
3.1decode接口说明
3.2encode接口说明
3.3getManufacturerId接口说明
3.4getModel接口说明
3.5接口实现注意事项
3.1decode接口说明
decode接口的入参binaryData为设备发过来的CoAP报文的payload部分。
设备的上行报文可以分为两种情况:
设备上报数据、设备对平台命令的应答。
两种情况下解码输出的字段不同。
表3-1设备上报数据(对应图3-1解码1)
字段名
类型
参数描述
是否必填
identifier
String
设备在应用协议里的标识,平台从decode接口获取该参数,在encode接口传入此参数
否
msgType
String
固定值"deviceReq",表示设备上报数据
是
hasMore
Int
表示设备是否还有后续消息,0表示没有,1表示有,平台暂时不下发缓存命令,直到为0,下发缓存命令,不带按照0处理。
注:
后续消息是指,设备上报的某条数据可能分成多次数据上报,在本次上报数据后,以hasMore字段判定后续是否还有消息。
请谨慎处理该字段,如果是必须数据上报后才有缓存命令下发的场景,只有某次数据上报时hasMore为0,缓存命令才能下发。
否
data
ServiceData[]
一组服务的数据(具体见表3-2)
是
表3-2ServiceData定义
serviceId
String
服务的id
是
serviceData
ObjectNode
一个服务的数据,具体字段在profile里定义
是
eventTime
String
设备采集数据时间(格式:
yyyyMMddTHHmmssZ)
如:
20161219T114920Z
否
示例:
{
"identifier":
"123",
"msgType":
"deviceReq",
"hasMore":
0,
"data":
[{"serviceId":
"NBWaterMeterCommon",
"serviceData":
{
"meterId":
"xxxx",
"dailyActivityTime":
120,
"flow":
"565656",
"cellId":
"5656",
"signalStrength":
"99",
"batteryVoltage":
"3.5"
}
"eventTime":
"20160503T121540Z"},
{"serviceId":
"waterMeter",
"serviceData":
{"internalTemperature":
256},
"eventTime":
"20160503T121540Z"}
]
}
}
表3-3设备对平台命令的应答(对应图3-1解码2)
字段名
类型
参数描述
是否必填
identifier
String
设备在应用协议里的标识,平台从decode接口获取该参数,在encode接口传入此参数
否
msgType
String
固定值"deviceRsp",表示设备的应答消息
是
mid
Int
2字节无符号的命令id,根据平台下发命令时的mid返回给平台。
建议提供
否
errcode
Int
请求处理的结果码。
0表示成功,1表示失败
是
hasMore
Int
表示设备是否还有后续消息。
0表示没有;1表示有,平台暂时不下发缓存命令,直到为0,下发缓存命令。
不带按照0处理。
注:
后续消息是指,设备的某条应答可能分成多次数据上报,在某次应答上报后,以hasMore字段判定后续是否还有消息。
否
body
ObjectNode
命令的应答,具体字段由profile定义。
注:
body体不是数组。
否
示例:
{
"identifier":
"123",
"msgType":
"deviceRsp",
"mid":
2016,
"errcode":
0,
"body":
{
"result":
0
}
}
3.2encode接口说明
encode接口的入参json格式数据,是平台下发的消息或应答。
平台的下行报文可以分为两种情况:
平台消息下发、平台对设备上报数据的应答。
两种情况下编码输出的字段不同。
表3-1平台下发命令encode接口的入参结构定义(对应图3-2编码1)
字段名
类型
参数描述
是否必填
identifier
String
设备在应用协议里的标识,平台从decode接口获取该参数,在encode接口传入此参数
否
msgType
String
固定值"cloudReq",表示平台下发的请求
是
serviceId
String
服务的id
是
cmd
String
服务的命令名,参见profile的服务命令定义
是
paras
ObjectNode
命令的参数,具体字段由profile定义
是
hasMore
Int
表示平台是否还有后续消息下发。
0表示没有,1表示有。
注:
后续消息是指,平台可能还有待下发的消息,以hasMore字段告知设备不要休眠。
是
mid
Int
2字节无符号的命令id,平台内部分配(范围1-65535),设备命令响应平台时,需要返回该值
是
示例:
{
"identifier":
"123",
"msgType":
"cloudReq",
"serviceId":
"NBWaterMeterCommon",
"mid":
2016,
"cmd":
"SET_TEMPERATURE_READ_PERIOD",
"paras":
{
"value":
4
},
"hasMore":
0}
}
表3-2平台收到设备的上报数据后对设备的应答encode接口的入参结构定义(对应图3-2编码2)
字段名
类型
参数描述
是否必填
identifier
String
设备在应用协议里的标识,平台从decode接口获取该参数,在encode接口传入此参数
否
msgType
String
固定值"cloudRsp",表示平台收到设备的数据后对设备的应答。
是
request
byte[]
设备上报的数据
是
errcode
int
请求处理的结果码。
0表示成功,1表示失败
是
hasMore
int
表示平台是否还有后续消息下发,0表示没有,1表示有。
注:
后续消息是指,平台可能还有待下发的消息,以hasMore字段告知设备不要休眠。
是
说明:
接口返回null表示不回响应。
示例:
{
"identifier":
"123",
"msgType":
"cloudRsp",
"request":
[
1,
2
],
"errcode":
0,
"hasMore":
0
}
3.3getManufacturerId接口说明
返回厂商ID字符串。
示例:
@Override
publicStringgetManufacturerId(){
return"TestUtf8ManuId";
}
3.4getModel接口说明
返回设备型号字符串。
示例:
@Override
publicStringgetModel(){
return"TestUtf8Model";
}
3.5接口实现注意事项
接口需要支持线程安全
decode和encode函数需要支持线程安全,不得添加成员变量或静态变量来缓存过程数据。
错误示例:
多线程并发时A线程将status设置为Failed,B线程可能会同时设置为Success,从而导致status不正确,引起程序运行异常。
publicclassProtocolAdapter{
privateStringstatus;
@Override
publicObjectNodedecode(finalbyte[]binaryData)throwsException{
if(binaryData==null){
status="Failed";
returnnull;
}
ObjectNodenode;
...;
status="Success";
returnnode;
}
@Override
publicbyte[]encode(finalObjectNodeinput)throwsException{
if("Failed".equals(status)){
status=null;
returnnull;
}
byte[]output;
...;
status=null;
returnoutput;
}
}
正确示例:
直接使用入参编解码,编解码库不做业务处理。
publicclassProtocolAdapter{
@Override
publicObjectNodedecode(finalbyte[]binaryData)throwsException{
ObjectNodenode;
...;
returnnode;
}
@Override
publicbyte[]encode(finalObjectNodeinput)throwsException{
byte[]output;
...;
returnoutput;
}
}
mid字段的解释
平台对命令的下发是依次下发的,但平台收到的命令执行结果响应的次序未必与下发的次序相同,mid就是用来将命令的响应匹配到具体命令的。
在V100R001C30SPC200版本的平台,是否实现mid,消息流程也有所不同。
消息流程如下:
图3-1实现mid的消息流程
若实现了mid,并且命令执行结果已上报成功,则
1.命令执行结果响应中的状态(SUCCESSFUL/FAILED)会刷新到平台数据库中该命令的记录;
2.平台推送给APPserver的命令执行结果通知中携带commandId;
3.APPserver查询会得到该命令的状态为SUCCESSFUL/FAILED。
图3-2不实现mid的消息流程
若不实现mid,并且命令执行结果已上报成功,则
4.命令执行结果响应中的状态(SUCCESSFUL/FAILED)不会刷新到平台数据库中该命令的记录;
5.平台推送给APPserver的命令执行结果通知中不携带commandId;
6.APPserver查询会得到该命令的最终状态为DELIVERED。
上述两个消息流程是为解释mid字段的作用,部分消息流程在图中简化处理。
建议:
7.如果命令只关注送达设备,不关注执行结果,那么设备和插件不需要实现mid
8.如果命令关注执行结果,则需要设备和插件实现mid
9.如果厂商评估后不实现mid,则应用服务器不能在平台获取命令的执行结果,需要应用自行解决。
比如应用服务器在收到命令响应通知(不带commandId)后,可以根据如下方法来进行响应匹配:
10.根据命令下发的顺序。
此方法在丢包时可能会出错,应用最好是控制每次只下发一条命令。
11.插件可以在命令响应消息的resultDetail里加上命令相关的一些信息来帮助识别命令,比如命令码。
应用根据resultDetail里的信息来识别命令响应。
4数据参考样例
表4-1某款水表支持的服务定义
服务类型serviceType
属性名称
属性说明
属性类型(数据类型)
Battery
-
-
-
-
batteryLevel
电量(0--100)%
int
Meter
-
-
-
-
signalStrength
信号强度
int
-
currentReading
当前读数
int
-
dailyActivityTime
日激活通讯时长
string
那么数据上报时decode接口的输出:
{
"identifier":
"12345678",
"msgType":
"deviceReq",
"data":
[
{
"serviceId":
"Meter",
"serviceData":
{
"currentReading":
"46.3",
"signalStrength":
16,
"dailyActivityTime":
5706
},
"eventTime":
"20160503T121540Z"
},
{
"serviceId":
"Battery",
"serviceData":
{
"batteryLevel":
10
},
"eventTime":
"20160503T121540Z"
}
]
}
收到数据上报后,平台对设备的应答响应,调用encode接口编码,输入为
{
"identifier":
"123",
"msgType":
"cloudRsp",
"request":
[
1,
2
],
"errcode":
0,
"hasMore":
0
}
request的取值[1,2]是模拟数据,以实际情况为准。
表4-2命令定义
基本功能名称serviceType
分类
名称
命令参数
数据类型
枚举值
WaterMeter
水表
-
-
-
-
-
CMD
SET_TEMPERATURE_READ_PERIOD
-
-
-
-
-
-
value
int
-
-
RSP
SET_TEMPERATURE_READ_PERIOD_RSP
-
-
-
-
-
-
result
int
0表示成功,1表示输入非法,2表示执行失败
那么命令下发调用encode接口时,输入为
{
"identifier":
"12345678",
"msgType":
"cloudReq",
"serviceId":
"WaterMeter",
"cmd":
"SET_TEMPERATURE_READ_PERIOD",
"paras":
{
"value":
4
},
"hasMore":
0
}
收到设备的命令应答后,调用decode接口解码,解码的输出
{
"identifier":
"123",
"msgType":
"deviceRsp",
"errcode":
0,
"body":
{
"result":
0
}
}
5实现样例讲解
本文第七章节提供了一个Demo工程的附件,本节详细介绍这个Demo工程的实现,图5-1是Demo工程结构图。
重要:
下文中的pom.xml中的Bundle-SymbolicName用来设置编解码插件名称。
为避免您的编解码插件和其他厂商的冲突,请一定遵守命名规范。
命名规范:
设备类型-厂商ID-设备型号,例如:
WaterMeter-TestExampleID-TestNBIoTDevice。
图5-1Demo工程结构图
本工程是一个Maven工程,包含三个部分:
1pom.xml
//maven.apache.org/POM/4.0.0"xmlns:
xsi="http:
//www.w3.org/2001/XMLSchema-instance"
xsi:
schemaLocation="http:
//maven.apache.org/POM/4.0.0http:
//maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.thrid.party
--请修改为你的编解码插件的名字,命名规范:
设备类型-厂商ID-设备型号,例如:
WaterMeter_TestExampleID_TestNBIoTDevice-->
WaterMeter_TestExampleID_TestNBIoTDevice
1.0.0
bundle
UTF-8
4.11
2.7.4
2.5.4.fixed2
2.4
1.3.1
1.7.6
--单元测试使用-->
junit
junit
${junit.version}
--日志使用-->
org.slf4j
slf4j-api
${slf4j.api.version}
--转换JSON使用,必须-->
com.fasterxml.jackson.core
jackson-databind
${fasterxml.jackson.version}
--Huawei提供的编解码接口,必须-->
--systemPath请替换成你本地的目录\codecDemo\lib\com.huawei.m2m.cig.tup-1.3.1.jar-->
com.huawei
protocal-jar
1.3.1
system
D:
\codecDemo\lib\com.huawei.m2m.cig.tup-1.3.1.jar
--本例中数据转换使用到的jar,你用到的jar请写到这里,记得把artifactId填入后面的Embed-Dependency-->