云端开发手册

首页

概述

AIOT是一个物联网云平台,提供用户管理、设备管理、数据采集与远程控制等服务。通过智能设备采集的数据存储在AIOT云端数据库中,比如:功率、温湿度、开关状态、门窗状态等。同时,AIOT云端可以通过下发控制命令来远程控制设备。那开发者如何获得采集数据呢?又如何远程控制自己的设备呢?

为了满足这些第三方开发者的需求,AIOT开放平台提供了云端对接方式。通过Open API和消息推送服务,开发者可以从云端采集数据和远程控制设备,从而开发丰富的物联网应用。

AIOT开放平台提供了非常完善的接口,包括:

  • 用户管理
  • 位置管理
  • 设备管理
  • 场景管理
  • 资源管理
  • 联动管理

另外,AIOT开放平台提供了消息推送服务,支持把设备上报的实时数据推送到第三方服务器,满足了开发者对数据实时性的要求。

下面,本手册将介绍下如何基于云端对接方式开发第三方应用,包括应用的创建、配置和开发等。

写在前面

一个好的软件开发流程加上一个好的软件系统架构,会给软件开发带来事半功倍的效果。因此,为了帮助开发者开发得更加顺畅,在前面交代些重要的事。如果你是一个经验丰富的开发者,可以跳过这一小节。

在应用正式开发前,开发者需要做些准备工作,可参考如下流程。

应用开发流程

一个稳定和高效的应用需要考虑API调用性能、消息处理性能、Access-Token的高可用性等方面,建议参考如下架构图。

应用参考架构图

如果开发者还不熟悉API的调用方法,推荐使用Web API测试工具Postman。Postman是一款优秀的Web API和HTTP请求调试工具,功能强大,界面清晰,操作方便快捷。Postman能够帮助开发者测试AIOT Open API,从而快速掌握API的调用方法。

注意:使用Postman时请关闭SSL验证(SSL certifacate verification)。

应用创建与配置

创建应用

登录AIOT开放平台,单击“新建应用”。创建应用时,开发者需要设置应用的相关参数,包括:

  • 应用名称
  • 行业类型
  • 简介

创建应用成功后平台自动分配AppID和AppKey,其中AppID是应用的唯一标识,而AppKey是应用的秘钥。AppID和AppKey非常重要,在应用开发过程中会被频繁使用,比如:在调用AIOT开放平台Open API时,开发者需要在请求Header中加上AppID和AppKey作为校验参数。

注意:请开发者务必妥善保管AppKey,以防泄露,同时建议定期重置AppKey。

申请资源权限

资源是一种抽象的说法,在这里指由设备产生的数据,包括设备的设置参数与实时状态。一个设备具有多个资源,不同的资源表示不同含义的数据。例如,开关状态(plug_status)是智能插座的一个资源,表示智能插座当前是否通电。通过访问该资源,开发者可以查询插座的当前状态和远程开关插座。

访问资源之前,开发者需要先按级别申请资源的权限。资源级别分为1级和2级,1级表示常用的资源,2级表示不常用的资源。获得某个类型设备的1级授权后,开发者可以在应用中访问该类型设备的所有常用资源。

默认情况下,应用会自动分配所有类型设备的1级资源权限。如果需要申请2级资源授权,请访问“应用管理”页面,然后切换到“资源授权”页,如下图所示。

  • 单击每一行右侧的“申请资源”按钮,申请对应设备类型的资源。
  • 选中左侧多个勾选框,然后单击右上角的“批量申请”按钮,可以批量申请多个设备类型的资源。

申请单提交后需等待1到3个工作日,审核结果会以短信或邮件的方式通知到开发者。

资源授权页

申请API权限

API是AIOT开放平台对外提供数据的接口,也是开发者查询与控制设备的主要方式。在开发应用前,开发者请根据自己的需求来申请API的权限。默认情况下,应用会自动分配常用API的权限。

如果开发者需要申请API,请访问“应用管理”页面,然后切换到“API访问”页,如下图所示。

  • 单击每一行右侧的“申请”按钮,申请对应API的访问权限。
  • 单击右上角的“批量申请”按钮,然后按功能批量申请多个API的访问权限。

申请单提交后需等待1到3个工作日,审核结果会以短信或邮件的方式通知到开发者。

API访问页

账号授权

在设备入网后,设备绑定到唯一的AIOT账号,也就是Aqara APP的登录账号。只有获得AIOT账号的授权许可,第三方应用才能访问与控制该账号下的设备,同时AIOT平台才会把设备消息推送到第三方服务器。

说明:在应用商店或Apple Store搜索“Aqara”,下载安装后注册Aaqra APP账号。

目前,AIOT开放平台提供两种授权方式:OAuth 2.0和签名授权方式。

OAuth2.0

OAuth2.0 是一个开放标准,允许用户让第三方应用访问该用户在某一网站(或物联网平台)上存储的私密资源(如用户信息、照片、视频、设备数据等),而无需将用户名和密码提供给第三方应用。如果您想对OAuth2.0开放标准进行扩展阅读,请参考 理解OAuth2.0 | OAuth标准(英文)

AIOT开放平台采用OAuth 2.0标准的授权码(authorization_code)模式,适用于拥有server端的应用。OAuth 2.0 授权流程简单、安全,时序图如下所示,完成授权流程后获得访问令牌(AccessToken)。此后,开发者使用访问令牌来调用接口,获取用户信息或操作用户的设备。

Oauth2.0授权码模式时序图

OAuth 2.0 详细授权流程如下:

注意:本章节URL示例以“中国大陆地区(https://aiot-oauth2.aqara.cn/)”为例进行说明,若在其他地区,请参考国家(地区码)文档更改域名。

步骤1 请求授权码

首先,第三方应用需要通过浏览器将用户重定向到AIOT OAuth 2.0服务。使用Aqara APP账号登录成功后,AIOT开放平台会返回用户的授权码(code)。授权码的有效期为10分钟,请在10分钟内完成后续流程。

  • URL: https://aiot-oauth2.aqara.cn/authorize?client_id=xxx&response_type=code&redirect_uri=xxxx&state=xxx&theme=x
  • 请求方式: HTTP GET
  • 请求参数
参数名 是否必须 描述
client_id 第三方应用ID,AppID
response_type 返回类型,按照OAuth 2.0 标准,取值为code
redirect_uri 第三方应用注册的重定向URI
state 取值为任意字符串,认证服务器将原样返回该参数
theme 页面主题,目前支持0、1、2三套主题,默认为主题0
  • 返回说明
GET  HTTP/1.1 302 Found
Location: https://redirect_uri?code=xxx&state=xxx

步骤2 获取访问令牌

获得授权码后,第三方应用访问以下URL,用授权码换取访问令牌(AccessToken)。

  • URL: https://aiot-oauth2.aqara.cn/access_token
  • 请求方式: HTTP POST (application/x-www-form-urlencoded)
  • 请求参数
参数名 是否必须 描述
client_id 第三方应用ID,AppID
client_secret 第三方应用秘钥,AppKey
grant_type 根据OAuth 2.0 标准,取值为authorization_code
code 上一步请求获得的授权码
redirect_uri 上一步请求中设置的redirect_uri参数
  • 返回示例(状态码200)
{
    "access_token": "xxxxx", 
    "expires_in": 7200, 
    "token_type": "bearer", 
    "openId": "xxx", 
    "refresh_token": "xxxxx", 
    "state": "abcde"
}
  • 返回参数
参数名 描述
access_token 访问令牌,第三方应用访问AIOT开放服务的凭证
expires_in 访问令牌的剩余有效时间,单位为秒
token_type 根据OAuth 2.0 标准,取值为bearer
openId 授权用户的唯一标识
refresh_token 刷新令牌,用于刷新访问令牌,有效期为30天
state 取值为任意字符串,认证服务器将原样返回该参数

步骤3 刷新访问令牌

由于访问令牌的有效期只有2个小时,所以开发者需要在访问令牌过期前使用刷新令牌进行刷新,建议的刷新周期为1个半小时。

  • URL: https://aiot-oauth2.aqara.cn/refresh_token
  • 请求方式: HTTP POST (application/x-www-form-urlencoded)
  • 请求参数
参数名 是否必须 描述
client_id 第三方应用ID,AppID
client_secret 第三方应用秘钥,AppKey
grant_type 根据OAuth 2.0 标准,取值为refresh_token
refresh_token 上一步请求获得的刷新令牌
  • 返回示例(状态码200)
{
    "access_token": "xxxxx", 
    "expires_in": 7200, 
    "token_type": "bearer", 
    "openId": "xxx", 
    "refresh_token": "xxxxx", 
    "state": "abcde"
}
  • 返回参数
参数名 描述
access_token 访问令牌,第三方应用访问AIOT开放服务的凭证
expires_in 访问令牌的剩余有效时间,单位为秒
token_type 根据OAuth 2.0 标准,取值为bearer
openId 授权用户的唯一标识
refresh_token 新的刷新令牌,旧的刷新令牌立即作废
state 取值为任意字符串,认证服务器将原样返回该参数

注意:如果刷新访问令牌时出现非正常返回的情况,请重试!

签名授权

大都数情况下,第三方应用会有自己的账号体系,并希望将此账号体系与AIOT账号体系进行对接,而不像Oauth2.0授权方式一样,需要用户再次注册Aqara账号。签名授权的方式,对用户而言,对Aqara账号是无感知的,只需要注册第三方应用的账号即可。

步骤1 创建超级账号

登录AIOT开放平台网站,在“应用管理”页面切换到“超级账号”页面,单击页面右上角的“创建账号”,输入用户名和密码,创建成功后,系统会自动生成“Open ID”和“Private Key”。

参数名 描述
Open ID 授权用户的唯一标识
Private Key 密钥,用于生成数字签名
用户名 设置的Aqara账号,目前不支持在Aqara APP上登录。

步骤2 生成数字签名

数字签名采用ECDSA算法,代码可下载

说明:ECDSA算法及demo.zip文件夹中,ECDSAUtil.java为ECDSA算法代码,OpenEchoTester.java为签名授权接口调用demo。

签名字符串拼接方法如下:

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(uri).append("&").append(appId).append("&").append(appKey).append("&").append(openId).append("&").append(nonce);
参数名 描述
uri 例如:查询设备接口:https://aiot-open-3rd.aqara.cn/open/device/query/v2,uri即为/open/device/query/v2。
appId 第三方应用ID
appKey 第三方应用秘钥
openId 步骤1中生成的Open ID
nonce 发送请求时的时间戳,单位ms

步骤3 请求接口

通过签名授权方式认证后,在请求接口时,需在header中携带以下参数:

参数名 类型 描述
Authorization-Version String 认证方案的版本号。值:v2
Appid String 第三方应用ID
Appkey String 第三方应用秘钥
Openid或Open-Id String 步骤1中生成的Open ID
_nonce String 发送请求时的时间戳,单位ms
_signature String 步骤2中请求的数字签名

API调用

API调用规范

  1. 为了保证数据传输的安全,AIOT开放平台对外提供的API均采用HTTPS协议,中国大陆地区域名为:https://aiot-open-3rd.aqara.cn。若在其他地区,请参考国家(地区码)文档更改域名。

  2. OpenID 作为第三方应用对用户的唯一标识,是原AIOT账号加密后的结果。每个AIOT用户对每个第三方应用有一个唯一的OpenID。

  3. 接口的请求body和返回结果都采用JSON格式,如果开发者采用其他格式,会提示“请求参数错误”。

  4. 通过接口查询设备状态或控制设备时需要设置参数“资源别名”,不同资源的取值类型也不一样。所有资源的信息(别名、取值类型、含义等)请访问AIOT开放平台的“应用管理->资源授权”页面。

  5. 所有功能的详细API定义请访问AIOT开放平台的“应用管理->API访问”页面。

调用示例

OAuth 2.0

例如,通过调用接口查询一个设备的详细信息,调用方法如下:

  • 请求URL:https://aiot-open-3rd.aqara.cn/open/device/query

  • 请求方式: HTTP POST (application/json)

  • 请求header示例

Key Value 描述(可不填)
Appid 54a230100006040223478911 应用的唯一标识
Appkey oT7kp77v123456siiXISamsPpvaTaWeZ 应用的秘钥
Openid Yb2bR2btJC6L8EmU5Z3jzh4oQsttie 通过OAuth授权获得的用户ID
Access-Token 12db5a10c49fd289963dbc67a0d13ab5 通过OAuth授权获得的访问令牌
Content-Type application/json 返回结果采用JSON格式

注意:在请求header时填写的Key和Value值,需注意字母大小写。

  • 请求body示例
  {
  "openId": "Yb2bR2btJC6L8Em123456h4oQsttie",
  "did": "lumi.158d0001234654"
  }

说明:参数did表示设备ID,是设备的唯一标识。开发者可以通过调用接口,根据OpenID获得用户下所有设备的did。

  • 返回结果示例
  {
    "result": {
        "bindDate": "2017-11-13",
        "chipVersion": "",
        "bindTime": "22:35:18",
        "name": "卧室红外光照传感器",
        "model": "lumi.sensor_motion.es2",
        "isOnline": 1,
        "firmwareVersion": "1",
        "did": "lumi.158d0001123454",
        "parentId": "lumi.158d00011234a9"
    },
    "code": 0,
    "isBytesData": 0,
    "requestId": "oHjXRtRdnm"
  }

签名授权

例如,通过调用接口查询一个设备的详细信息,调用方法如下:

  • 请求URL:https://aiot-open-3rd.aqara.cn/open/device/query/v2
  • 请求方式: HTTP POST (application/json)
  • 请求header示例
Key Value 描述(可不填)
Authorization-Version v2 认证方案的版本号
Appid 54a230100006040223478911 应用的唯一标识
Appkey oT7kp77v123456siiXISamsPpvaTaWeZ 应用的秘钥
Openid或Open-Id 225997134641850051123456247729 通过OAuth授权获得的用户ID
_nonce 1532571136000 发送请求时的时间戳,单位ms
_signature MEUCICSJ9WBOXWoNElGFVLR3IyTYso 请求的数字签名

消息推送

如果第三方应用需要接收设备消息,开发者需要按照如下步骤启用消息推送功能:

  1. 填写服务器配置;
  2. 验证服务器地址;
  3. 按类型订阅消息;
  4. 根据消息格式实现业务逻辑。

特别注意,第三方应用在正常接收消息后必须按照规定的格式返回JSON报文,格式如下:

{
    "code": 0|ErrorCode,
    "result": "自定义内容"
}

服务器配置

访问“应用管理->消息推送”页面,单击右上角的“编辑”按钮,填写配置信息:

  1. URL:服务器地址,第三方服务器用来接收消息的接口URL;
  2. Token:由开发者任意填写,用于生成签名;
  3. EncodingAESKey:随机生成或由开发者手动填写,将用来对消息体进行加解密;
  4. 消息加解密方式:分为明文模式、兼容模式和安全模式,更改消息加解密方式后会立即生效,请开发者谨慎修改。

详细说明下消息加解密方式的区别:

  • 明文模式:不对消息体进行加密,安全系数低;
  • 兼容模式:消息体同时包含明文和密文,方便开发者调试和维护;
  • 安全模式:消息体为纯密文,需要开发者加密和解密,安全系数高。

注意:目前仅支持“明文模式”,请开发者使用明文模式。

消息服务器配置

验证服务器

明文模式

在明文模式下,服务器验证的方法很简单。开发者保存服务器配置后,AIOT服务器会发送一个POST请求到开发者设置的服务器地址(URL),请求将携带一个参数echostr(JSON格式),它是一个随机的字符串。如果第三方服务器收到该请求,请原样返回echostr参数内容,则验证服务器成功,否则验证失败。

发送报文格式:

{
    "echostr": "jdlfialjf8i"
}

返回报文格式如下:

{
    "code": 0,
    "result": "jdlfialjf8i"
}

安全模式

在安全模式下,服务器验证的方法变得复杂,和微信公众号平台类似。 开发者保存服务器配置后后,AIOT服务器将发送GET请求到填写的服务器地址(URL),请求携带如下参数:

  • signature:加密签名,signature结合了开发者填写的Token参数和请求中的timestamp参数、nonce参数;
  • timestamp:时间戳;
  • nonce:随机数;
  • echostr:随机字符串。

若确认此次GET请求来自绿米服务器,请原样返回echostr参数内容,则验证服务器成功,否则验证失败。其中,加密/校验流程如下:

  1. 将Token、timestamp、nonce三个参数进行字典序排序;
  2. 将三个参数字符串拼接成一个字符串进行sha1加密;
  3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于AIOT服务器。

消息格式

目前,AIOT开放平台支持以下两类消息: - 资源消息:资源的变化消息,比如温度变化、功率变化等; - 设备消息:设备的事件消息,比如设备在线离线、绑定解绑等。

资源消息

{
    "msgType": "resource", 
    "data": [
        {
            "time": "1503556533", 
            "attr": "load_power", 
            "value": "3.93", 
            "did": "lumi.158d00011234ee"
        }
    ]
}
参数 说明
msgType 消息类型,取值为resource
time 时间戳,单位:秒
attr 资源别名,资源别名的含义请参考“应用管理->资源授权”页面
value 资源的最新值
did 设备ID

设备消息

{
    "msgType": "device", 
    "data": {
        "openId": "GoeFrrL7mN9SsGRi1234564YnQpXTS", 
        "name": "空调伴侣", 
        "model": "lumi.acpartner.aq1", 
        "time": 1503560767, 
        "event": "DEV_INFO_CHANGED", 
        "did": "lumi.158d00010b1230", 
        "parentId": "", 
        "extra": "{"clientId":"xxxx"}"
    }
}
参数 说明
msgType 消息类型,取值为device
openId 用户ID
name 设备名称
model 设备类型
time 时间戳,单位:秒
event 事件类型,详细参数说明见下表
did 设备ID
parentId 父设备(网关)ID,如果是网关,该字段为空
extra 附加消息
事件类型 描述
GW_BIND 网关入网
GW_UN_BIND 网关解绑
GW_ONLINE 网关在线
GW_OFFLINE 网关离线
SUB_DEV_BIND 子设备入网
SUB_DEV_UN_BIND 子设备解绑
SUB_DEV_ONLINE 子设备在线
SUB_DEV_OFFLINE 子设备离线
DEV_INFO_CHANGED 设备信息改变

返回码说明

第三方应用每次调用接口时,可能获得正确或错误的返回码,开发者可以根据返回码信息调试接口以及排查错误。

类别 返回码 表示 说明
SUCCESS 0 SUCCESS 成功
ERROR_PACKAGE 100 ERROR_TIMEOUT Timeout, 超时
ERROR_PACKAGE 101 ERROR_PACKAGE_ILLEGAL 数据包非法
ERROR_PACKAGE 102 ERROR_PACKAGE_DAMAGE 数据包损坏
ERROR_REQUEST 301 ERROR_REQUEST_PATH 请求路径错误
ERROR_REQUEST 302 ERROR_REQUEST_PARAMS 请求参数错误
ERROR_USER 401 ERROR_USER_NO_REG 用户未注册
ERROR_USER 402 ERROR_USER_NO_LOGIN 用户未登录
ERROR_USER 403 ERROR_USER_PERMISSION_DENIED 拒绝用户访问,没有权限
ERROR_USER 411 ERROR_PASSWORD_NOT_CORRECT 密码错误
ERROR_USER 412 ERROR_TOKEN_FAILED Token失效
ERROR_SERVER 500 ERROR_INTERNAL_SERVER Server Error 服务器出错,服务器处理中出错
ERROR_DEVICE 601 ERROR_DEVICE_NO_REG 设备未注册
ERROR_DEVICE 602 ERROR_DEVICE_OFFLINE 设备离线
ERROR_DEVICE 603 ERROR_DEVICE_PERMISSION_DENIED 拒绝设备访问,没有权限
ERROR_DEVICE 604 ERROR_DEVICE_BIND 设备绑定错误,未绑定,或绑定的用户名有误
ERROR_THIRD 801 ERROR_APP3RD_APPID_OR_APPKEY_ILLEGAL AppID或AppKey有误
ERROR_THIRD 802 ERROR_THIRD_APP_ID_HAS_NO_PERMISSION AppID无权限访问该API
ERROR_THIRD 805 ERROR_APP3RD_OAUTH2_ACCESSTOKEN_ILLEGAL AccessToken有误
ERROR_THIRD 806 ERROR_APP3RD_OAUTH2_ACCESSTOKEN_EXPIRED AccessToken过期
ERROR_THIRD 807 ERROR_APP3RD_OAUTH2_REFRESHTOKEN_ILLEGAL RefreshToken有误
ERROR_THIRD 808 ERROR_APP3RD_OAUTH2_REFRESHTOKEN_EXPIRED RefreshToken过期
ERROR_OTA 901 ERROR_OTA_FIRMWARE_NOT_EXIST 不存在该Firmware

资源定义

云端开发的完整资源请查看AIOT开放平台的“资源授权”页面,以下为部分特殊资源的定义说明。

资源:ac_state

空调命令压缩格式(4 bytes): (二进制)

|0 1 2 3|4 5 6 7|8 9 10 11|12 13 14 15|16 17 18 19 20 21 22 23|24 25 26 27 28 29 30 31|

位置 描述
[0 ~3] 0: off; 1: on; 2: toggle; E: circle; F: invalid; else: reserve 开关
[4 ~ 7] 0: heat; 1: cool; 2: auto; 3: dry; 4: wind; E: circle; F: invalid; else: reserve 模式
[8 ~ 11] 0: low; 1: middle; 2: high; 3: auto; E: circle; F: invalid; else: reserve 风速
[12 ~ 13] 0: horizontal; 1: vertical; 2: circle; 3: invalid; 风向
[14 ~ 15] 0: swing; 1: fix; 2: circle; 3: invalid; 扫风
[16 ~ 23] 0 ~ 240; 243: up; 244: down; FF: invalid 温度
[24] 默认为0 扩展位
[25] 默认为0 是否为压缩码
[26] 默认为0 LED显示
[27] 0: 开关命令; 1: 非开关命令 是否为开关命令
[28 ~ 31] 00: 无状态; 01: 有状态; 02: 协议; 03: 推荐场景; 04: 半状态; 11: 忽略 空调类型

注意:

  • [16-23]温度数值0~240为十进制,如果设置为25度,那么二进制为00011001 。
  • "ac_state"值必须采用10进制数。
  • 在控制空调时,模式、风速和风向不要设置为“F(invaild)”,可能出现无法识别导致控制失败的情况。建议在设置ac_state值之前,可以先通过/open/resource/query接口查询ac_state当前值,然后根据需求修改对应值。

例如:设置为“开空调,模式为制冷,风速为低档,风向为水平,摆动扫风,温度为25度” 对应的二进制数为:00010001000000000001100100000001,二进制数转换为十进制,则ac_state值为“285219073”。

资源:cfg_param

参数 类型 描述 可写可读
WriteMask uint16 标志要写的成员是哪一个,需要写的成员的对应位为1 NA
bPosLimitState bool_t 电机是否已经设置了行程 RW
bPolarity bool_t 电机旋转的极性 RW
u8MotorStatus uint8 电机当前的状态 RO
bManualEnabled bool_t 电机是否使能了手拉功能 RW
u8TransTime uint8 窗帘从起点允许到终点的使用时间,单位s RO