1.6.2 Alink 通信协议
更新时间:2018-09-18 15:30:51
网络通道能力介绍
传输数据形式
透传
概念介绍
设备端直接通过上发自定义二进制数据, 云端对上传上来的二进制数据直接进行解析(通过云端转换脚本, 需自行开发), 并转换为标准Alink协议数据的格式。而在下行时, 云端同样会通过经过解析, 把标准的Alink协议数据转换成二进制数据, 并发送到设备端。
透传相关的Topic定义如下,传输数据为二进制数据。
下行 Topic
设备端订阅Topic:/sys/{productKey}/{deviceName}/thing/model/down_raw
设备端回复Topic:/sys/{productKey}/{deviceName}/thing/model/down_raw_reply
上行 Topic
设备端发布Topic:/sys/{productKey}/{deviceName}/thing/model/up_raw
服务端回复Topic(需设备端订阅):/sys/{productKey}/{deviceName}/thing/model/up_raw_reply
非透传(Alink格式)
设备直接构造对应Topic以及对应的json格式数据, 云端直接进行解析。
服务调用方式
云端下发的服务请求支持同步和异步方式。
同步调用
如果服务为同步调用,云端会等待设备回复,否则会调用超时。
同步Topic格式约定
设备端订阅Topic: /sys/{productKey}/{deviceName}/rrpc/request/{messageId}
设备端回复Topic:/sys/{productKey}/{deviceName}/rrpc/response/{messageId}
productKey, deviceName为设备唯一信息, 可以从云平台上获取。
messageId为IoT套件生成的消息ID,设备端回复响应时,Topic里的这个值要与请求一致;设备端订阅时可以使用/sys/{productKey}/{deviceName}/rrpc/request/+, 将最末的采用同配符订阅,回复时不可以使用同配符。
异步调用
如果服务为异步调用,云端执行调用后直接返回,不会关心设备的回复消息。
注意: 下行请求目前默认是采取异步方式调用方式。
Alink基础格式介绍
参数解析
根据物模型定义 TSL,组装以下请求和响应payload,request为请求payload,response为响应payload。
method对应tsl中method;
Alink协议请求中params对应tsl中的inputData;
Alink协议回复中data对应tsl中的outputData。
Alink协议请求格式:
{
"id" : "123", //表示消息id, 为String类型, 取值范围0~(2^31-1)
"version":"1.0", //消息的版本默认为1.0,作为保留字段
"params" : { //请求入参,类型为JSONObject, 参数的取值和具体的method对应参考tsl.method描述
"RGB" : {
"R":110,
"G":2,
"B":50
},
"swtich" : 1,
"usedTime": 50.5
},
"method":"/sys/adsgag/test_device/thing/service/property/set" //请求对应的方法, 如""对应{tsl.method}
}
Alink协议应答格式:
{
"id":"123", // 表示消息id, 为String类型, 取值范围0~(2^31-1)
"code":200, //返回结果的code, 具体参考下表
"message":"success", // 返回结果的描述, 非必填, 具体参考下表
"localizedMsg":"", //设备返回的错误信息
"data":{} //返回的结果,类型为JSONObject
}
格式说明
物的描述-TSL中一共使用了以下这些数据类型, 而在Alink协议数据中, 应按照以下规范处理, 否则数据可能被平台过滤:
类型 | 格式说明 | 样例 |
---|---|---|
整数型(int) | 32位有符号整形 | "int":123 |
浮点型(float) | 单精度浮点数 | "float":3.33 |
双精度型(double) | 双精度浮点数 | "double":6.66 |
枚举型(enum) | 0 ~ 99 范围内整形 | "enum":2 |
布尔型(bool) | 0 或者 1 | "bool":0 |
字符串(text) | 最长支持255字符长度字符串数据 | "text":"hello world" |
时间型(date) | 1970年毫秒时间戳, 需转换为字符串格式 | "date":"1513653388000" |
json对象(struct) | 复合结构类型, 成员格式参考以上基础类型。 | "struct":{"int":333, "text":"hello world"} |
alink传输数据示例:
我们定义一款智能调节RGB颜色的灯, 如下描述:
1. RGB为json对象, 其中包含R,G,B三个属性, 均为整形
2. bright为整数型, 描述亮度
3. switch为布尔型, 描述开关
4. usedTime为浮点型, 描述设备使用时间
那么, 我们上报属性的时候可以使用如下数据格式进行上报
{
"id" : "7481264598",
"version":"1.0",
"params" : {
"RGB" : {
"R":110,
"G":2,
"B":50
},
"swtich" : 1,
"usedTime": 50.5
},
"method":"thing.event.property.post"
}
通用Code以及错误码解析
云端返回结果code和message描述如下:
code | message | 含义 |
---|---|---|
200 | success | 表示请求成功 |
400 | request error. | 请求失败 |
401 | request auth error. | 请求授权错误, 比如设备上报的签名鉴权失败 |
403 | request forbidden. | 禁止请求 |
404 | service not found. | 服务找不到 |
429 | too many requests. | 请求太多, 过于频繁 |
460 | request parameter error. | 请求参数错误 |
500 | server error. | 服务内部出错 |
503 | server not available. | 服务不可用 |
6203 | topic not exist | topic不存在 |
业务Code解析
云端返回结果code和message描述如下:
code | message | 含义 |
---|---|---|
6200 | script relation not exist | 对于产品是透传类型,需要通过脚本进行数据转换。 脚本不存在时会报这个错误。 |
6201 | script convert data is null | 对于产品是透传类型,需要通过脚本进行数据转换。 脚本主要进行数据转换,肯定是有返回结果的。 脚本转换的数据返回为空时会报这个错。 |
26001 | Script content is empty! | 对于产品是透传类型,需要通过脚本进行数据转换。如果进行脚本转换时如果云端拿到的脚本为空,就会报这个错误 |
26002 | Script execution exception, view more message! | 对于产品是透传类型,需要通过脚本进行数据转换。脚本执行过程脚本本身报错,会报这个错误。 可以通过数据控制台数据解析进行模拟脚本运行进行排查。 |
26003 | Script execution timeout! | 对于产品是透传类型,需要通过脚本进行数据转换。脚本执行超时 |
26006 | Method is not found in script! | 对于产品是透传类型,需要通过脚本进行数据转换。 按照标准定义了protocalToRawData和rawDataToProtocal,当调用这两个函数时如果函数不存在,会报这个错误 |
26007 | The format of result is error! | 对于产品是透传类型,需要通过脚本进行数据转换。按照标准定义protocalToRawData返回byte[]数组,rawDataToProtocal返回JSONObject,如果返回的结果不满足要求,会报这个错误 |
26008 | This type of script is not support! | 对于产品是透传类型,需要通过脚本进行数据转换。目前脚本类型只支持JavaScript, 当数据转换时脚本类型不是JavaScript就会报这个错 |
26009 | Script execution is error! | 对于产品是透传类型,需要通过脚本进行数据转换。 脚本执行过程中如果发生云端无法识别的错误,会报这个错误。 可以通过数据控制台数据解析进行模拟脚本运行进行排查。 |
6321 | tsl: device not exist in product | 上下行的数据都需要满足Alink协议的要求,云端会对数据进行校验。这个错误码表示:云端检查数据格式时,如果设备不属于这个产品会报这个错误 |
6313 | tsl service not available | 上下行的数据都需要满足Alink协议的要求,云端会对数据进行校验。 这个错误码表示:云端检查数据格式的任务不可用。 |
6106 | map size must less than 200 | 上下行的数据都需要满足Alink协议的要求,云端会对数据进行校验。这个错误码表示:上报的数据数量超过200个 |
6256 | device synchronization failed | 子设备注册时,子设备信息数据同步错误 |
6401 | topo relation not exist | 对于网关类型设备挂载的子设备, 当该子设备和网关不存在拓扑关系,注销子设备时会报错。 |
6402 | topo relation cannot add by self | 添加拓扑关系时,设备不能够把自己添加为自己的子设备 |
使用MQTT连接阿里云IoT
您可以使用我们的IoT SDK进行快速移植,如果不用我们提供的SDK,完全使用开源MQTT包自主接入(若使用第三方代码, 阿里云不提供技术支持),可以参考以下流程:
注意, 在进行MQTT CONNECT协议设置的时候
- Connect指令中的KeepAlive有效范围[60秒,300秒],否则会拒绝连接。
- 如果同一个设备多个连接可能会导致客户端互相上下线,MQTT默认开源SDK会自动重连,您可以通过日志服务看到设备行为。
如果使用TLS,需要 下载根证书
使用MQTT客户端连接服务器,如果您自主接入可以使用开源MQTT客户端参考,如果您对MQTT不了解,可以参考 http://mqtt.org 相关文档。(若使用第三方代码, 阿里云不提供技术支持)
MQTT 连接域名:
使用域名:${productKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com:1883
${productKey}请替换为您的产品key,mqtt的Connect报文参数如下:
mqtt的Connect报文参数如下:
mqttClientId: clientId+"|securemode=3,signmethod=hmacsha1,timestamp=132323232|"
mqttUsername: deviceName+"&"+productKey
mqttPassword: sign_hmac(deviceSecret,content)sign签名需要把以下参数按字典序排序后,再根据signmethod加签。
content=提交给服务器的参数(productKey,deviceName,timestamp,clientId), 按照字母顺序排序, 然后将参数值依次拼接
其中clientId是客户端自表示id,建议mac或sn,64字符内;
timestamp当前时间毫秒值,仅做混淆,可以不传递;
mqttClientId格式中||内为扩展参数;
signmethod代表签名算法类型,可支持hmacSha1,hmacSha256,hmacMd5;
securemode代表目前安全模式,可选值有2 (TLS直连模式)、3(TCP直连模式;
示例:
如果clientId = 12345,deviceName = device, productKey = pk, timestamp = 789,signmethod=hmacsha1,deviceSecret=secret,那么使用tcp方式提交给mqtt参数分别如下:
mqttclientId=12345|securemode=3,signmethod=hmacsha1,timestamp=789|
username=device&pk
password=hmacsha1("secret","clientId12345deviceNamedeviceproductKeypktimestamp789").toHexString(); //最后是二进制转16制字符串,大小写不敏感。 这个例子结果为 FAFD82A3D602B37FB0FA8B7892F24A477F851A14
注意上面3个参数分别是mqtt Connect登录报文的mqttClientId,mqttUsername,mqttPasswrod
网关和子设备场景
子设备场景介绍
如果硬件场景是子设备通过网关, 再连接到阿里云IoT平台上的情况,子设备相关的Topic均由网关代理使用, 并需要严格按照以下的Topic流程进行:
a. 添加子设备拓扑关系
b. 子设备上线
c. 自由使用 属性/事件/服务 等等相关的Topic
注:
1. 上述流程中的 a 和 b 步骤请在收到服务端回复成功之后再依次进行下一步, 以防调用过快导致拓扑关系或者设备上线功能调用失败
2. 属性/事件/服务, 以及相关的设备禁用,删除等功能, 均适用于子设备以及单设备场景。
3. 目前子设备场景不支持多个网关嵌套(例子:设备A是网关GW的子设备, 而设备A又是设备B的网关, 这种功能不支持), 只能存在一层。
网关添加/删除/获取子设备的拓扑关系
添加子设备拓扑关系
透传 | 非透传 | |
---|---|---|
上行 | 不支持 | 支持 |
设备端发布Topic: /sys/{gw_productKey}/{gw_deviceName}/thing/topo/add
payload:
{
"id" : "123",
"version":"1.0",
"params" : [{
"productKey":"xxxxx",//子设备productKey
"deviceName":"xxxx",//子设备deviceName
"sign":"",
"signmethod":"hmacSha1" //可支持hmacSha1,hmacSha256,hmacMd5
"timestamp":"123456789",
"clientId":"test&1234556554", //本地标记,可以和productKey&deviceName保持一致
}],
"method":"thing.topo.add"
}
注: sign与signmethod可参考【使用MQTT连接阿里云IoT】中介绍
服务端回复Topic(需设备端订阅): /sys/{gw_productKey}/{gw_deviceName}/thing/topo/add_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
说明:对于三元组设备 子设备签名规则同网关相同
sign = hmac_sha1(deviceSecret, clientId1234556554&testdeviceNametestproductKey1234556554timestamp123456789)
删除拓扑关系
透传 | 非透传 | |
---|---|---|
上行 | 不支持 | 支持 |
设备端发布Topic: /sys/{gw_productKey}/{gw_deviceName}/thing/topo/delete
payload:
{
"id" : "123",
"version":"1.0",
"params" : [{
"productKey":"xxxxx",//子设备productKey
"deviceName":"xxxx",//子设备deviceName
}],
"method":"thing.topo.delete"
}
服务端回复Topic(需设备端订阅): /sys/{gw_productKey}/{gw_deviceName}/thing/topo/delete_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
获取拓扑关系
透传 | 非透传 | |
---|---|---|
上行 | 支持 | 支持 |
设备端发布Topic: /sys/{gw_productKey}/{gw_deviceName}/thing/topo/get
payload:
{
"id" : "123",
"version":"1.0",
"params" : {},
"method":"thing.topo.get"
}
服务端回复Topic(需设备端订阅): /sys/{gw_productKey}/{gw_deviceName}/thing/topo/get_reply
payload:
{
"id":"123",
"code":200,
"data": [{
"productKey":"xxxxx",//子设备productKey
"deviceName":"xxxx",//子设备deviceName
}]
}
网关向服务器报告子设备上线/下线信息
子设备上线
透传 | 非透传 | |
---|---|---|
上行 | 不支持 | 支持 |
设备端发布Topic: /ext/session/{gw_productKey}/{gw_deviceName}/combine/login
payload:
{
"id":"123",
"params":{
"productKey":"xxxxx",//子设备productKey
"deviceName":"xxxx",//子设备deviceName
"clientId":"xxxx",
"timestamp":"xxxx",
"signmethod":"hmacmd5 or hmacsha1 or hmacsha256",
"sign":"xxxxx", //子设备签名
"cleanSession":"true or false" // 如果是true,那么清理所有子设备离线消息,即QoS1或者2的所有未接收内容
}
}
注1:该Topic只支持qos=0的设置。
注2: sign与signmethod可参考【使用MQTT连接阿里云IoT】中介绍。
服务端回复Topic(需设备端订阅): /ext/session/{gw_productKey}/{gw_deviceName}/combine/login_reply
payload:
{
"id":"123",
"code":200,
"message":"success"
}
子设备下线
透传 | 非透传 | 同步调用 | 异步调用 | |
---|---|---|---|---|
上行 | 不支持 | 支持 | 不支持 | 支持 |
设备端发布Topic: /ext/session/{gw_productKey}/{gw_deviceName}/combine/logout
payload:
{
"id":"123",
"params":{
"productKey":"xxxxx",//子设备productKey
"deviceName":"xxxxx",//子设备deviceName
}
}
服务端回复Topic(需设备端订阅):/ext/session/{gw_productKey}/{gw_deviceName}/combine/logout_reply
payload:
{
"id":"123",
"code":200,
"message":"success"
}
单个设备场景
上行数据
设备属性上报
注:参数按照tsl中出入参定义;
透传 | 非透传 | |
---|---|---|
上行 | 支持 | 支持 |
注: 子设备也使用该Topic进行属性上报。
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/event/property/post
payload:
{
"id" : "123",
"version":"1.0",
"params" : {
"Power" : "on",
"WF" : "2"
},
"method":"thing.event.property.post"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/event/property/post_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
设备事件上报
注:method为tsl中method,参数按照tsl中出入参定义;
透传 | 非透传 | |
---|---|---|
上行 | 支持 | 支持 |
注: 子设备也使用该Topic进行事件上报。
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/event/{tsl.event.identifer}/post
payload:
{
"id" : "123",
"version":"1.0",
"params" : {
"Power" : "on",
"WF" : "2"
},
"method":"thing.event.{tsl.event.identifier}.post"
}
服务端回复Topic(需设备端订阅):/sys/{productKey}/{deviceName}/thing/event/{tsl.event.identifer}/post_reply
payload:
{
"id" : "123",
"code":200,
"data" : {}
}
下行数据
服务器获取设备属性
注:参数按照tsl中出入参定义;
物的属性获取, 目前统一从云端缓存(设备影子)中直接获取物的属性。没有get请求直接下发到设备。
透传 | 非透传 | 同步调用 | 异步调用 | |
---|---|---|---|---|
下行 | 支持 | 支持 | 不支持 | 支持 |
设备端订阅Topic: /sys/{productKey}/{deviceName}/thing/service/property/get
注: params中为Json数据, 参数为开发者设置的属性名字, 详情参考TSL描述。
payload:
{
"id" : "123",
"version":"1.0",
"params" : [
"power" , "temp"
],
"method":"thing.service.property.get"
}
注:服务端不会对get_reply数据做处理,目前获取到的属性值要求设备通过post方式上报。
设备端回复Topic:/sys/{productKey}/{deviceName}/thing/event/property/post
payload:
{
"id":"123",
"code":200,
"data":{
"power":"on",
"temp":"23"
}
}
服务器设置设备属性
注:参数按照tsl中出入参定义;
透传 | 非透传 | 同步调用 | 异步调用 | |
---|---|---|---|---|
下行 | 支持 | 支持 | 不支持 | 支持 |
设备端订阅Topic: /sys/{productKey}/{deviceName}/thing/service/property/set
payload:
{
"id" : "123",
"version":"1.0",
"params" : {
"Power" : "on",
"WF" : "2"
},
"method":"thing.service.property.set"
}
设备端回复Topic: /sys/{productKey}/{deviceName}/thing/service/property/set_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
服务器触发指定服务
注:method为tsl中method,参数按照tsl中出入参定义;
透传 | 非透传 | 同步调用 | 异步调用 | |
---|---|---|---|---|
下行 | 支持 | 支持 | 支持 | 支持 |
异步模式下:
设备端订阅Topic: /sys/{productKey}/{deviceName}/thing/service/{tsl.service.identifer}
payload:
{
"id" : "123",
"version":"1.0",
"params" : {
"Power" : "on",
"WF" : "2"
},
"method":"thing.service.{tsl.service.identifer}"
}
设备端回复Topic:/sys/{productKey}/{deviceName}/thing/service/{tsl.service.identifer}_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
同步模式下:
注: messageId请参考【同步调用】中具体描述
设备端订阅Topic: /sys/{productKey}/{deviceName}/rrpc/request/+
payload:
{
"id" : "123",
"version":"1.0",
"params" : {
"Power" : "on",
"WF" : "2"
},
"method":"thing.service.{tsl.service.identifer}"
}
设备端回复Topic:/sys/{productKey}/{deviceName}/rrpc/response/{messageId}
payload:
{
"id":"123",
"code":200,
"data":{}
}
设备禁用
透传 | 非透传 | 同步调用 | 异步调用 | |
---|---|---|---|---|
上行 | 不支持 | 支持 | 不支持 | 支持 |
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/topo/disable
payload:
{
"id" : "123",
"version":"1.0",
"params" :{},
"method":"thing.disable"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/topo/disable_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
设备禁用恢复
透传 | 非透传 | 同步调用 | 异步调用 | |
---|---|---|---|---|
上行 | 不支持 | 支持 | 不支持 | 支持 |
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/enable
payload:
{
"id" : "123",
"version":"1.0",
"params" : {},
"method":"thing.enalbe"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/topo/enable_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
设备删除
透传 | 非透传 | 同步调用 | 异步调用 | |
---|---|---|---|---|
上行 | 不支持 | 支持 | 不支持 | 支持 |
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/delete
payload:
{
"id" : "123",
"version":"1.0",
"params" : {},
"method":"thing.delete"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/topo/delete_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
其他扩展功能
设备扩展信息
设备扩展信息设置
透传 | 非透传 | |
---|---|---|
上行 | 不支持 | 支持 |
参数说明:
params元素个数不超过200个
attrKey要求长度不超过100字节,仅允许字符集为[a-z, A-Z, 0-9]和下划线,且首字符必须是字母或者下划线
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/deviceinfo/update
payload:
{
"id" : "123",
"version":"1.0",
"params" : [{
"attrKey" : "Temperature",
"attrValue" : "36.8"
}],
"method" : "thing.deviceinfo.update"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/deviceinfo/update_reply
payload:
{
"id" : "123",
"code":200,
"data" : {}
}
设备扩展信息删除
透传 | 非透传 | |
---|---|---|
上行 | 不支持 | 支持 |
参数说明:
params元素个数不超过200个
attrKey要求长度不超过100字节,仅允许字符集为[a-z, A-Z, 0-9]和下划线,且首字符必须是字母或者下划线
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/deviceinfo/delete
payload:
{
"id" : "123",
"version":"1.0",
"params" : [{
"attrKey" : "Temperature"
}],
"method" : "thing.deviceinfo.delete"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/deviceinfo/delete_reply
payload:
{
"id" : "123",
"code":200,
"data" : {}
}
TSL
获取对应产品的TSL信息
透传 | 非透传 | |
---|---|---|
上行 | 不支持 | 支持 |
获取TSL模板,协议详见 TSL描述
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/tsltemplate/get
payload:
{
"id" : "123",
"version":"1.0",
"params" : {
},
"method" : "thing.tsltemplate.get"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/tsltemplate/get_reply
payload:
{
"id" : "123",
"code" : 200,
"data" :tsl JsonObject(参照tsl模板样例)
}
设备秘钥签名(目前仅蓝牙)
设备密钥签名
透传 | 非透传 | |
---|---|---|
上行 | 不支持 | 支持 |
- cipherType 加密方式,目前支持蓝牙一型一密(cipherType: 6)和蓝牙一机一密(cipherType: 7)
设备端发布Topic: /sys/{productKey}/{deviceName}/thing/cipher/get
payload:
{
"id" : "123",
"version":"1.0",
"params" :{
"deviceName": "TestDeviceName"
"productKey": "TestProductKey",
"productId" : "TestId", //shortModel
"cipherType": 6,
"mac": "6f9e2fa9f2e9",
"random": "462d53c9846fb"
},
"method":"thing.cipher.get"
}
服务端回复Topic(需设备端订阅): /sys/{productKey}/{deviceName}/thing/cipher/get_reply
payload:
{
"id":"123",
"code":200,
"data":{}
}
###加密算法
cipherType=6 BLE一型一密:密钥算法sha256(contentByteArray)。
contentByteArray=productSecret.getByte()+0x2c+hexToByte(mac)+0x2c+hexToByte(random)
注: productId为产品的主键ID,productSecret根据productId查询得到。
cipherType=7 BLE一机一密:密钥算法sha256(contentByteArray)
contentByteArray=deviceSecret.getByte()+0x2c+hexToByte(mac)+0x2c+hexToByte(random)
其中0x2c是英文逗号 ,
的字节表示,返回签名取sha256结果的前32位。