设备 HTTP 接入协议
设备 HTTP 接入协议
注意:通过 HTTP API 只能实现部分简单的功能,更多功能请参考 MQTT 或 CoAP API
HTTP 接入协议主要适合只包含数据上传类设备
概述
请求地址
host
云服务器域名port
云服务器端口, 一般为默认 80 端口path
云服务器访问路径
示例 (下面是 {domain-name} 服务器的设备接入地址):
请求消息体格式
请求消息体格式必须为 application/json
设备 ID (DID)
设备通过 DID 来唯一标识一个设备,可预先烧录在设备中。
设备 ID 没有固定格式,目前支持 MAC 地址或设备序列号做为设备 DID 使用。
设备密钥
设备通过设备密钥来认证身份,设备密钥由平台生成,可在设备出厂时烧录到设备中
设备密钥和设备 ID 是一一对应的
消息签名
<data>:<method>
method
表示签名算法名称, 如md5
data
表示签名内容, HEX 字符串格式,大小写不敏感
签名算法:
- 有时间戳的模式:
data = md5(did + ":" + deviceSecret + ":" + timestamp).toHexString()
- 没有时间戳的模式:
data = md5(did + ":" + deviceSecret).toHexString()
设备注册
设备通过向云服务器发送注册请求来认证身份,激活设备以及获取访问令牌.
注意事项:
目前没有对设备注册严格认证, 只依赖于 MAC 地址. 首先必须保证 MAC 地址的唯一性, 其次 MAC 地址有被冒充的可能性. 所以这个接口只适合在受保护的网内使用.
注册成功后, 会设置一个注册有效时间, 当在注册有效时间期满之前必须发送更新注册请求来延长注册有效时间, 否则会被服务器注销处理.
注册请求
请求地址:
消息内容:
{
"did": String,
"sign": String,
"timestamp": Number,
"type": "register",
"data": {
"expires": Number,
"nodes": [String]
"version": {
"firmware": String
},
"supported": []
}
}
请求参数:
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
did | true | String | - | 设备唯一 ID |
sign | - | String | - | 消息签名,当服务端启用了设备认证时必须提供 |
timestamp | - | Number | - | 可选,设备发送消息时的时间戳 |
type | true | String | register | 消息类型,必须是 register |
data | - | Object | - | 可选,设备描述信息 |
- expires | - | Number | 3600 | 可选,设备端期望的注册期满时间, 单位为秒 |
- nodes | - | Array | - | 可选,绑定到当前节点的边缘节点列表,常用于网关 |
- gateway | - | String | - | 可选,网关的 DID, 常用于边缘节点通过网关注册时 |
- version | - | Object | - | 可选,设备版本信息 |
- supported | - | Array | - | 可选,设备支持的特性列表 |
应答结果:
{
"did": String,
"type": "register",
"result": {
"id": String,
"token": String,
"mqtt": String,
"coap": String,
"expires": Number
}
}
应答参数:
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
did | true | String | - | 注册的设备的唯一 ID |
type | true | String | register | 消息类型,必须是 register |
result | - | Object | - | 可选,注册结果数据 |
- token | true | Number | - | 令牌,用于后续消息加密和认证 |
- expires | - | Number | 3600 | 云端期望的注册期满时间, 单位为秒 |
- id | - | String | - | 设备在云端的 ID |
- mqtt | - | String | - | 云端 MQTT 服务器 URL |
- coap | - | String | - | 云端 CoAP 服务器 URL |
错误应答:
CODE | TYPE | NOTE |
---|---|---|
100401 | Unauthorized | 设备没有通过身份认证 |
100403 | Permission denied | 该设备需要取得授权 |
104001 | Miss required parameter | 缺失必要的参数,请参考 API 文档 |
200202 | Device does not exists | 设备不存在 |
更新注册
在注册有效期之前设备必须发送更新注册请求来更新注册状态。
更新注册请求不需要包含 data
(事物描述)
请求内容:
{
"did": String,
"type": "register",
"sign": String,
"timestamp": Number
}
请求参数:
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
did | true | String | - | 设备唯一 ID |
sign | - | String | - | 消息签名 |
timestamp | - | Number | - | 时间戳 |
type | true | String | register | 消息类型,必须是 register |
应答结果:
{
"did": String,
"type": "register",
"result": {
"id": String,
"token": String,
"expires": Number
}
}
应答参数:
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
did | true | String | - | 注册的设备的唯一 ID |
type | true | String | register | 消息类型,必须是 register |
token | true | Number | - | 令牌,用于后续消息加密和认证 |
result | - | Object | - | 可选,注册结果数据 |
- expires | - | Number | 3600 | 云端期望的注册期满时间, 单位为秒 |
删除注册
设备可发送删除注册请求删除注册状态。
删除注册请求需要包含值为 -1
的 expires 参数, 表示注册马上过期
云端处理完删除注册请求后,应马上删除设备的 token
请求内容:
{
"did": String,
"sign": String,
"timestamp": Number,
"type": "register",
"data": {
"expires": -1,
}
}
请求参数:
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
did | true | String | - | 设备唯一 ID |
sign | - | String | - | 消息签名 |
timestamp | - | Number | - | 时间戳 |
type | true | String | register | 消息类型,必须是 register |
data | - | Object | - | 可选,设备描述信息 |
- expires | true | Number | -1 | 必须是 -1, 表示马上期满 |
响应结果
{
"did": String,
"type": "register",
"result": {
"id": String,
"token": String,
"expires": Number
}
}
应答参数:
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
did | true | String | - | 注册的设备的唯一 ID |
type | true | String | register | 消息类型,必须是 register |
result | - | Object | - | 可选,注册结果数据 |
- expires | true | Number | -1 | 总是为 -1, 表示注册已经过期 |
设备属性
上报数据流
前端设备可以通过 stream 消息主动上报数据。
注意:上报数据流的同时也会更新设备影子状态
数据流的信息会同时保存到云端历史数据库中
请求地址:
请求内容:
{
"did": String,
"token": String,
"type": "stream",
"data": {
"<name>": <value>
}
}
did
表示前端设备的 IDtoken
访问令牌,在注册时取得data
数据流数据,可同时发布多个不同名称的数据流
响应结果
{
"did": String,
"token": String,
"type": "stream",
"data": {
"code": 0,
"count": 1
}
}
code
如何成功总是为 0count
如果为 0, 表示没有有效的数据 (可能消息内容为空)
设备事件
发布事件
前端设备发生事件时,将通过 event
消息上报给云端
请求地址:
事件记录会保存到云端数据库中,应用程序可以在云端查询事件记录
请求内容:
{
"did": String,
"token": String,
"type": "event",
"data": {
"<event>": <data>
}
}
did
表示前端设备的 IDtoken
访问令牌,在注册时取得data
事件数据,可同时发布多个不同名称的事件
响应结果
{
"type": "event",
"did": String,
"token": String,
"data": {
"code": 0
}
}
code
如何成功总是为 0
设备操作
应用程序可以通过这个接口远程调用前端设备的操作接口,如"开灯/关灯"等,具体流程如下:
注意:这个接口仅用于应用程序和云端进行交互,不适用于前端设备
前端设备需使用 MQTT 或 CoAP 协议才能实现远程操作调用功能。
应用程序->设备管理服务器: POST /actions
设备管理服务器->MQ: PUBLISH /actions/:did
MQ->前端设备: action 请求
前端设备->前端设备: 执行操作
前端设备->MQ: PUBLISH /messages/:did
MQ->设备管理服务器: action 结果
设备管理服务器->应用程序: HTTP Response
发送调用请求
请求地址:
由应用程序发送给云端,表示要调用指定 ID 的设备指定名称的操作。
请求参数:
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
timeout | - | Number | 0 | 等待应答超时时间,单位为毫秒 |
注意:
- 如果没有设置 timeout 参数,服务端会立即返回应答,不会等待目标设备执行结果
- 如果设置了 timeout 参数,则会等待并返回目标设备执行结果
- 如果超过了 timeout 时间也没有等到执行结果,则会返回超时错误应答
请求内容:
{
"type": "action",
"did": String,
"mid":String
"data": {
"<name>": <input>
}
}
mid
可选,表示消息的 IDdid
必需,表示前端设备的 IDtype
总是为action
data
操作数据name
必需,操作名称input
可选,输入参数
返回成功结果
消息格式:
{
"type": "action",
"did": String,
"mid": String,
"result": {
"<name>": <output>
}
}
mid
表示消息的 IDdid
表示前端设备的 IDresult
表示调用成功的方法以及其输出参数
返回失败结果
服务端错误消息格式:
{
"type": "action",
"mid": String,
"did": String,
"result": {
"code": Number,
"error": "<error>"
}
}
mid
表示消息的 IDdid
表示前端设备的 IDresult
操作结果code
操作结果代码error
错误信息
设备端错误消息格式 (设置了等待超时时间):
{
"type": "action",
"mid": String,
"did": String,
"result": {
"<name>": {
"code": Number,
"error": "<error>"
}
}
}
mid
表示消息的 IDdid
表示前端设备的 IDresult
操作结果name
操作名称code
操作结果error
表示调用失败的方法以及其错误信息
设备影子
查询设备影子
设备可以通过这个接口查询设备影子的最新状态
请求地址:
请求内容:
{
"did": String,
"token": String,
"type": "action",
"data": {
"shadow": {
"read": {}
}
}
}
响应结果
{
"did": String,
"type": "action",
"result": {
"shadow": {
"read": {
"version": String,
"updated": Number,
"config": {
"version": String,
"updated": Number,
"<name>": <value>
},
"reported": {
"<name>": <value>
},
"desired": {
"<name>": <value>
},
"metadata": {
"reported": {
"updated": Number,
"<name>": {
"updated": Number
}
},
"desired": {
"updated": Number,
"<name>": {
"updated": Number
}
},
}
}
}
}
}
应答参数:
NAME | REQUIRED | TYPE | DESCRIPTION |
---|---|---|---|
did | true | String | 设备的 ID |
version | true | String | 设备影子的版本 |
updated | true | Number | 设备影子的最后更新时间 |
config | - | Object | 设备配置参数 |
reported | - | Object | 设备最后上报的属性或状态 |
desired | - | Object | 设备期望被配置的属性 |
metadata | - | Object | 设备影子元数据 |
更新设备影子
应用程序可以通过这个接口修改期望的属性,设备端可以通过这个接口上报实际的属性
请求地址:
请求内容:
{
"did": String,
"token": String,
"type": "action",
"data": {
"shadow": {
"write": {
"reported": {
"<name>": <value>
},
"desired": {
"<name>": <value>
}
}
}
}
}
NAME | REQUIRED | TYPE | DEFAULT | DESCRIPTION |
---|---|---|---|---|
did | true | String | - | 设备 ID |
reported | - | Object | - | 上报设备当前属性或状态 |
desired | - | Object | - | 设置期望的设备属性 |
响应结果
{
"did": String,
"type": "action",
"result": {
"shadow": {
"write": {
"code": 0
}
}
}
}