# 2. 云云对接

为了方便开发者快速接入,本平台整合了接口服务。您只需要按照本文档,开发链接一二三所示接口,提供其URL,并对接云端提供链接四所示上报接口,就能实现设备与本平台互通。

  • 链接一 :参考授权页,授权页面,其覆盖了"获取授权页"相关逻辑
  • 链接二 :参考授权,授权服务,其覆盖了"获取、刷新令牌口令"相关逻辑
  • 链接三 :参考第三方提供的统一接入接口,统一接口服务,其覆盖了"授权、设备相关"相关逻辑
  • 链接四 :参考第三方设备统一上报接口,统一三方设备状态上报,其覆盖了"设备新增、删除、状态变更"相关逻辑

接入产品涉及的交互流程如下图所示:

全交互流程

# 2.1 示例代码

云云对接均采用https协议,与开发语言无关。此处仅提供可读性较强的Java样例 接口均为"创建产品"时配置,故示例接口名称仅供参考,请根据实际情况调整 示例实现了云云对接全套的https方法,包含实现,流程流程和参数说明。对照代码阅读接口文档可以互相印证,加快开发进度。您也可以采用为脚手架代码。

  1. 示例为spring boot项目,采用最近的2.2.7.RELEASE,您可以根据实际需要适当降低版本。点击下载Java示例:

云云对接脚手架 (opens new window)

  1. 用IDE导入为maven项目,无需更改配置即可运行,项目架构如下:

image-20191220164836373

接口 作用 目录(com/cloud/controller) 接口
/oauth2/authorize 被美的IoT唤起的授权页面 AuthorizeController.java 授权页
/login 授权页面点击确认后触发 AccessTokenController.java 仅作为示例用
/auth 包括获取和刷新令牌 AccessTokenController.java 获取令牌接口刷新令牌接口
/cloud2cloud/operation 授权、设备相关所有的操作 CloudOperationController.java 第三方提供的统一接入接口
  1. 在src/com/cloudm目录下,右键运行"Application",可启动该服务,默认为8080端口。
  2. 点击如下链接打开授权页,授权页采用了bootstrap,能较好适应各种手机尺寸: http://localhost:8080/oauth2/authorize?client_id=%221111%22&state=%222222%22&response_type=code&redirect_uri=%22https://www.baidu.com/%22

Demo页面

# 2.2 美的IoT云端接口约定

开发者提供的云控端产品想要接入美的美居套系时,需要实现本文接口,从而云云互通。 所有请求返回遵循HTTP请求状态的Http状态编码,HTTP Status Code描述:

http返回码 业务返回代码 信息 描述
200 0 OK 成功
401 INVALID_SIGNATURE 验签失败
409 业务异常 业务异常
500 服务器异常 服务器异常
200 10001 INTERNAL_ERROR 内部错误
200 10002 UNAUTHORIZED 未经授权或权限不够
200 10003 EXPIRED_ACCESSTOKEN_CREDENTIAL 表示三方授权凭据AT已过期或失效
200 10004 INVALID_PARAMETER 请求接口的参数非法
200 10005 DEVICE_DOES_NOT_EXIST 设备不存在
200 10006 INVALID_JSON_FORMAT JSON格式非法
200 10007 RATE_LIMIT_EXCEEDED 请求过于频繁

# 2.3授权

云云级别针对用户的授权。

接口 描述
获取授权页接口 获取授权页
授权页本体 一个HTML的页面,授权用
用户标识交换&code获取 交换双方的用户标识,获取授权code
获取令牌接口 获取令牌
刷新令牌接口 刷新令牌

# 2.3.1 获取授权页接口(插件类型)

开发者实现该接口,供开发者平台调用,期待的效果为:弹出授权页面。

  1. 接口说明:返回相应的授权登录页面

  2. 详细说明:获取美居标准授权需要用OAuth2授权方式,目前只response_type=code

  3. URL:由三方提供

  4. 支持格式:url 参数

  5. HTTP请求格式:GET

  6. 请求参数:

参数 必选 类型 说明
client_id true String 第三方分配给美的的APP ID
state true String 请求授权方的校验字段,授权服务透传原值返回
response_type true String 固定值code
redirect_uri true String 重定向URI
scope false String 申请的权限范围
  1. 请求样例:

/v1/open/oauth2/authorize?client_id=clientId*************************1234&state=1&response_type=code

  1. 返回字段: 返回login页面,让用户输入用户名密码

# 2.3.2 授权页本体(插件类型)

授权采用标准的OAuth2.0协议,该页面的使能场景为: 当用户使用美的IoT的美居APP、小程序等系列前端产品时,想用开发者提供的云云产品。这时候需要跳转到该开发者提供的授权页进行授权。进而获取其云云产品的设备,包括列表以及当前状态等。然后用户就能在美居APP、小程序就能看到这些设备,并对设备进行操控。

  • 示例页面路径: resources\templates\authorize.html
  • 参照交互流程,认证成功后,需要返回redirect_uri供本平台跳转(重定向)。

根据政策要求,该页面需要包含用户许可和隐私声明等说明,请自行提供。并需要用户手动勾选。

# 2.3.3 用户标识交换&code获取(配网类型)

  1. 接口说明:用于和三方交换用户标识和获取授权code

  2. 详细说明:用于配网类型授权,初次调用交换双方用户标识及获取授权code,之后调用只获取授权code

  3. HTTP方法:POST

  4. 接口URL:由三方提供,应用创建时的authCodeUrl

  5. Content-Type: application/json

  6. 请求参数:

请求体header:

参数名称 必选 类型及范围 描述
reqId true String 请求ID
namespace true String UserGrantExchange
clientId true String 第三方分配给美的的App Id
timeStamp true String 请求时间戳,毫秒级区分
granteeId true String 美的用户标识

请求体payload:

参数名称 必选 类型及范围 描述
granteeId true String 美的用户标识
thirdUid false String 三方用户标识,初次交换不会携带,双方交换标识后会携带

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01", 
    "clientId":"103135035", 
    "namespace":"UserGrantExchange", 
    "timeStamp":"20181201160518000", 
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
    }, 
  "payload":{
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53", 
    "thirdUid":""
  }
}
  1. 响应信息
参数名称 类型及范围 描述
code int 错误码
message String 错误描述

返回字段说明:

参数名称 必选 类型及范围 描述
thirdCode true String 授权code
thirdUid false String 三方用户标识,请求中未携带thirdUid则必须返回

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "clientId":"103135035",
    "namespace":"UserGrantExchange",
    "timeStamp":"20181201160518000", 
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "code":0,
    "message":"*****",
    "thirdCode":"kh84WSocSobB6Oe1rtmeyenmyQqQ9CkL", 
    "thirdUid":"abcd1234efg"
  }
}

# 2.3.4 获取令牌接口

  1. 接口说明:上述插件类型或配网类型获取的code,通过该接口获取访问三方接口的AccessToken

  2. 接口URI:由三方提供

  3. HTTP方法:POST

  4. Content-Type: application/x-www-form-urlencoded 或 application/json

  5. 请求参数:

参数 必选 类型 说明
client_id true String 第三方分配给美的的APP ID
client_secret true String 第三方分配给美的的开发者密钥
grant_type true String 固定值:authorization_code<br /仅当作为服务提供方,供美的云云调用时固定值为:client_credentials
code true String 上述插件类型或配网类型获取的code<br /仅当作为服务提供方,供美的云云调用时,该值非必选

JSON示例:

{
  "client_id": "clientId*************************1234",
  "grant_type": "authorization_code",
  "client_secret": "client_secret*************************abcd",
  "code": "code**********************1234"
}
  1. 返回字段
字段 类型 说明
access_token String 访问令牌
expires_in Integer 令牌有效期
refresh_token String 刷新令牌
token_type String 令牌类型

JSON示例:

{
  "refresh_token": "refresh_token*********************abcd1234",
  "token_type": "bearer",
  "access_token": "access_token*********************abcd",
  "expires_in": 7200
}

# 2.3.5 刷新令牌接口

  1. 接口说明:当AccessToken过期时通过RefreshToken刷新令牌

  2. 接口URI:由三方提供

  3. HTTP方法:POST

  4. Content-Type: application/x-www-form-urlencoded 或 application/json

  5. 请求参数:

参数 必选 类型 说明
client_id true String 第三方分配给美的的APP ID
client_secret true String 第三方分配给美的的开发者密钥
grant_type true String 固定值:refresh_token
refresh_token true String 从第三方处获取到的refresh_token

JSON示例:

{
  "client_id": "clientId*************************1234",
  "grant_type": " refresh_token",
  "client_secret": "client_secret*************************abcd",
  "refresh_token": "refresh_token*********************abcd1234"
}

6.返回字段:

字段 类型 说明
access_token String 访问令牌
expires_in Integer 令牌有效期
refresh_token String 刷新令牌
token_type String 令牌类型

JSON示例:

{
  "refresh_token": "refresh_token*********************abcd1234",
  "token_type": "bearer",
  "access_token": "access_token*********************abcd",
  "expires_in": 7200
}

# 2.4 第三方提供的统一接入接口

注意:此接口为美的云请求第三方云

用户控制设备相关的所有接口都在这里。

接口 描述
接口总述 整个接口的基本使用规范
账号授权 对用户的设备行为的授权
取消授权 对用户的设备取消授权
获取用户设备列表 用户设备列表
设备控制 同步控制设备
设备状态查询 同步查询设备的状态
发送异步指令 发送异步指令给三方设备

接口说明:发送异步指令为异步返回,与[设备控制设备状态查询]俩个同步接口 只能二选一,可联系客服配置

# 2.4.1 接口总述

  1. 接口URL:由三方提供

  2. HTTP方法:POST

  3. Content-Type: application/json

  4. 接口说明:提供一系列设备相关的开放接入的统一接口,使用上一步授权获得的用户级Accesstoken进行鉴权

  5. 请求参数:

请求头部:

参数名称 必选 类型及范围 描述
Authorization true String Bearer开头的用户级AccessToken 例如:Bearer 0lemRvfLicjkHtno
ClientId true String 第三方分配给美的的AppId
SignatureVersion true String 签名版本号,2.0
Signature true String 签名摘要,签名方式请参照签名摘要规则说明(密钥为第三方分配给美的的ClientSecret)

请求体header[header为所有请求统一格式,在返回信息里面原样返回]:

参数名称 必选 类型及范围 描述
reqId true String 请求ID
namespace true String 请求功能名称(UserAcceptGrant、UserAcceptGrant、UserCancelGrant、ApplianceDiscovery、ApplianceControl、ApplianceState、AsyncApplianceOrder)
timeStamp true String 请求时间戳,毫秒级区分
granteeId true String 美的用户标识
  1. 响应信息
参数名称 类型及范围 描述
code int 错误码
message String 错误描述

# 2.4.2 账号关联

  1. 接口说明: 完成用户级账号鉴权后,交换美的与三方标识完成账号关联

  2. 请求参数:

请求体payload[根据不同的namespace,payload可能会不一样]:

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"UserAcceptGrant",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg"
  },
  "payload":{
  }
}

3.返回参数:

返回字段说明:

参数名称 类型 描述
openUid String 第三方用户标识

JSON示例:

{
  "header":{
  "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
  "namespace":"UserAcceptGrant",
  "timeStamp":"20181201160518000",
  "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "code":0,
    "message":"*****",
    "openUid":"openUid*********************abcd"
  }
}

# 2.4.3 取消授权

  1. 接口说明: 用户取消授权时删除美的和三方用户的关联关系以及设备订阅关系

  2. 请求参数:

请求体payload[根据不同的namespace,payload可能会不一样]:
JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"UserCancelGrant",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
  }
}
  1. 返回参数:

JSON示例:

{
  "header":{
  "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
  "namespace":"UserCancelGrant",
  "timeStamp":"20181201160518000",
  "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "code":0,
    "message":"*****"
  }
}

# 2.4.4 获取用户设备列表

  1. 接口说明:获取第三方用户的设备列表

  2. 请求参数

请求体payload[根据不同的namespace,payload可能会不一样]:

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"ApplianceDiscovery",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
  }
}

3.返回参数

返回字段说明:

参数名称 类型 描述
applianceList JSONArray 设备列表
spid String 设备产品标识(在美的开发者平台创建产品时获取到的产品标识)
subType String 设备类型(在美的开发者平台创建产品时获取到的sn8)
applianceCode String 三方设备虚拟ID,用于设备相关操作
type String 设备品类码(在美的开发者平台创建产品时获取到的品类码)
name String 设备名称
onlineStatus String 设备在线状态,1为在线,0为离线

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"ApplianceDiscovery",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "code":0,
    "message":"*****",
    "applianceList":[
      {
        "applianceCode":"1099511841782",
        "spid": "12345678",
        "subType":"L0000001",
        "onlineStatus":"1",
        "type":"0x13",
        "name":"智能灯"
      }
    ]
  }
}

# 2.4.5 设备控制

  1. 接口说明:用于同步控制三方设备,接口补充说明

  2. 请求参数

请求体payload[根据不同的namespace,payload可能会不一样]:

参数名称 必选 类型及范围 描述
applianceCode true String 设备虚拟ID,用于设备相关操作
control true JSONObject 设备控制的指令

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"ApplianceControl",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "control":{
      "power":"off"
    },
    "applianceCode":"1099511824210"
  }
}

3.返回结果

返回字段说明:

参数名称 类型 描述
appliance JSONObject 控制设备对象
status JSONObject 返回设备的当前状态
applianceCode String 设备虚拟ID,用于设备相关操作
onlineStatus String 设备在线状态,1为在线,0为离线

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"ApplianceControl",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "code":0,
    "message":"*****",
    "appliance":{
      "applianceCode":"1099511824210",
      "onlineStatus":"1",
      "status":{
        "small_temperature":0,
        "indoor_temperature":21.9,
        "wind_swing_lr":"off",
        "power_on_time_value":0
      }
    }
  }
}

# 2.4.6 设备状态查询

  1. 接口说明:同步获取第三方设备状态,接口补充说明

  2. 请求参数:

请求体payload[根据不同的namespace,payload可能会不一样]:

参数名称 必选 类型及范围 描述
applianceCodes true Array 三方设备ID列表,可传多个

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"ApplianceState",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "applianceCodes":["1099511824210"]
  }
}

3.返回结果

返回字段说明:

参数名称 类型 描述
applianceList JSONArray 设备列表
status JSONObject 返回设备的当前状态
applianceCode String 设备虚拟ID,用于设备相关操作
onlineStatus String 设备在线状态,1为在线,0为离线

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"ApplianceState",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "code":0,
    "message":"*****",
    "applianceList":[
      {
        "applianceCode":"1099511824210",
        "onlineStatus":"1",
        "status":{
          "small_temperature":0,
          "indoor_temperature":21.9,
          "wind_swing_lr":"off",
          "power_on_time_value":0
        }
      }
    ]
  }
}

# 2.4.7 发送异步指令

  1. 接口说明:发送异步指令给三方设备,接口补充说明
   指令的执行为异步模式,开发者发送请求后:
 1 服务端立即返回"已接收"应答
 2 实际业务处理在后台执行
 3 最终结果通过[设备指令回调接口]返回

该接口发送异步指令为异步返回,与[设备控制设备状态查询]俩个同步接口 只能二选一,在后台配置 2. 请求参数

请求体header[header为所有请求统一格式,在返回信息里面原样返回]:

参数名称 必选 类型及范围 描述
reqId true String 指令跟踪ID ,调用异步接口后,可通过该ID在回调通知中匹配原始请求

请求体payload[根据不同的namespace,payload可能会不一样]:

参数名称 必选 类型及范围 描述
applianceCode true String 设备虚拟ID,用于设备相关操作
order false JSONObject 设备发送指令

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"AsyncApplianceOrder",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "order":{
      "power":"off"
    },
    "applianceCode":"1099511824210"
  }
}

3.返回结果

返回字段说明:

参数名称 类型 描述
code int 错误码 0 接收成功
message String 描述

JSON示例:

{
  "header":{
    "reqId":"fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace":"AsyncApplianceOrder",
    "timeStamp":"20181201160518000",
    "granteeId":"granteeId*********************abcd1234efg65b0e24a53"
  },
  "payload":{
    "code":0,
    "message":"****"
  }
}

# 2.5 第三方设备统一上报接口(接入物模型可使用)

注意:此接口为第三方云请求美的云

# 2.5.1 接口总述

  1. 请求域名:https://api-prod.smartmidea.net

  2. 接口URL:/v2/open/skill/thing/notify

  3. HTTP方法:POST

  4. Content-Type: application/json

  5. 接口说明:提当第三方设备信息变化时,第三方调用此统一接口通知美的云,根据请求体header部分中相应的namespace进行不同的事件通知,使用应用级AccessToken进行鉴权

  6. 请求参数:

请求头部:

参数名称 必选 类型及范围 描述
Authorization true String Bearer开头的应用级AccessToken 例如:Bearer 0lemRvfLicjkHtno
access_token获取方式客户端授权(ClientId与ClientSecret请使用开发者平台创建应用后返回值)
ClientId true String 开发者平台创建云应用时返回的ClientId
SignatureVersion true String 签名版本号,2.0
Signature true String 签名摘要,签名方式请参照签名摘要规则说明(密钥使用发者平台创建云应用时返回的ClientSecret)

请求体header[header为所有请求统一格式,在返回信息里面原样返回]:

参数名称 必选 类型及范围 描述
reqId true String 请求ID
namespace true String 请求功能名称(ApplianceAdd、ApplianceDelete、ApplianceStateChange、ApplianceOrderNotify)
timeStamp true String 请求时间戳,毫秒级区分
openUid true String 三方用户标识

请求体payload对象:

参数名称 必选 类型及范围 描述
payload true JSONObject 请求参数
  1. 响应信息
参数名称 类型及范围 描述
code int 错误码
message String 错误描述

# 2.5.2 新增设备

请求体中payload部分:

参数名称 必选 类型及范围 描述
applianceList true JSONArray 设备列表
spid true String 设备产品标识(在美的开发者平台创建产品时获取到的产品标识)
subType true String 设备类型(在美的开发者平台创建产品时获取到的sn8)
applianceCode true String 三方设备虚拟ID,用于设备相关操作
type true String 设备品类码(在美的开发者平台创建产品时获取到的品类码)
name true String 设备名称
onlineStatus true String 设备在线状态,1为在线,0为离线

JSON示例:

{
  "header": {
    "reqId": "fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace": "ApplianceAdd",
    "timeStamp": "20181201160518000",
    "openUid": "6bcbe05266d1e096b3540cc225bbf99dd789609edef91eddcadc2f65b0e24a53"
  },
  "payload": {
    "applianceList": [
      {
        "applianceCode": "1099511841782",
        "subType": "L0000001",
        "onlineStatus": "1",
        "type": "0xAC",
        "name": "智能灯"
      }
    ]
  }
}

# 2.5.3 删除设备

请求体中payload部分:

参数名称 必选 类型及范围 描述
applianceCodes true Array 三方设备ID列表,可传多个

JSON示例:

{
  "header": {
    "reqId": "fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace": "ApplianceDelete",
    "timeStamp": "20181201160518000",
    "openUid": "6bcbe05266d1e096b3540cc225bbf99dd789609edef91eddcadc2f6\t5b0e24a53"
  },
  "payload": {
    "applianceCodes": [
      "1099511824210"
    ]
  }
}

# 2.5.4 设备状态变更

请求体中payload部分:

参数名称 必选 类型及范围 描述
status true JSONObject 返回设备的当前状态
applianceCode true String 设备虚拟ID,用于设备相关操作
onlineStatus true String 设备在线状态,1为在线,0为离线

JSON示例:

{
  "header": {
    "reqId": "fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace": "ApplianceStateChange",
    "timeStamp": "20181201160518000",
    "openUid": "6bcbe05266d1e096b3540cc225bbf99dd789609edef91eddcadc2f6\t5b0e24a53"
  },
  "payload": {
    "applianceCode": "1099511824210",
    "onlineStatus": "1",
    "status": {
      "power": "on",
      "light": "off",
      "dry": "on"
    }
  }
}

# 2.5.5 设备指令回调

  1. 接口说明:发送异步指令接口的回调通知
  2. 请求参数

请求体header部分:

参数名称 必选 类型及范围 描述
reqId true String 指令跟踪ID ,调用异步接口后,可通过该ID在回调通知中匹配原始请求

请求体中payload部分:

参数名称 必选 类型及范围 描述
code true number 指令执行结果 0 成功
msg true String 指令执行结果描述
applianceCode true String 设备虚拟ID,用于设备相关操作
onlineStatus true String 设备在线状态,1为在线,0为离线
order true JSONObject 设备指令结果

JSON示例:

{
  "header": {
    "reqId": "fe8234bf-e94c-4cdf-8ea9-c3112962ab01",
    "namespace": "ApplianceOrderNotify",
    "timeStamp": "20181201160518000",
    "openUid": "6bcbe05266d1e096b3540cc225bbf99dd789609edef91eddcadc2f6\t5b0e24a53"
  },
  "payload": {
    "code":0,
    "message":"*****",
    "applianceCode": "1099511824210",
    "onlineStatus": "1",
    "order":{
          "status": {
          "power": "on",
          "light": "off",
          "dry": "on"
        }
     }
  }
}
最后修改于: 2025-04-14