index

优质
小牛编辑
112浏览
2023-12-01

GraphQL Reference

该文档由 graphql-docs 生成,并且对部分模板进行了修改.

文档结构借鉴 https://developer.github.com/v4/

  1. 本页是对文档的说明及此API的基本使用说明,必读
  2. Grapqhl接口应该从左侧 sidebar QUERIS开始浏览
  3. Mutation 的文档与 Query 不同,你需要从左侧 sidebar MUTATIONS下点击单个 mutation 才能查看。

New to GraphQL?

刚开始使用GraphQL? 查看GraphQL的官方文档

你还可以在浏览器使用 graphql-playground (Github地址) 来快速熟悉 GraphqlRokid IoT Open API

使用方式

接口地址: https://homebase-open.rokid.comhttps://homebase-open.rokid.com/graphql

接口使用 GraphQL 提供, GraphQL的具体使用方法可以参考 https:/https://homebase-open.rokid.com/graphql.org/learn/, 客户端支持 Java/AndroidJavascript , 更多参考这里, 当然完全手写也不是太麻烦的事。

无论使用何种方法,你都必须先学会 GraphQL 的语法和基本概念! 任何时候,我们都鼓励你先在 graphql-playground 中得到正确结果后再进行后续开发。

你可以通过 Get 和 Post 来访问 GraphQL HTTP API,见https:/https://homebase-open.rokid.com/graphql.org/learn/serving-over-http/,及示例

  1. 通过 Get 方法, 通过 url 参数发送 query
    GET https://homebase-open.rokid.com/graphql?query={me{name}}
  2. 通过 POST 方法, post json 的方式发送
    POST https://homebase-open.rokid.com/graphql
{
  "query": "...",
  "operationName": "...",
  "variables": { "myVariable": "someValue" }
}

返回结果说明:

你完全可以按照https:/https://homebase-open.rokid.com/graphql.org/learn/serving-over-http/#response返回的 data(只在语法错误时缺失)和 errors(只在有错误时返回)来处理返回结果。

除了标准的用法,我们还添加/修改了HTTP headers来帮助调试及监控:

  1. 头部中的 x-trace-id 是每个请求的唯一 ID,记录此字段可在向我们反馈问题时快速定位此请求。此用法会相对固定
  2. 响应头部的状态码只在无 errors 时为 200(非标准用法),400时一定为Graphql解析或Validation错误、输入错误,403为鉴权出错 (见接口授权)。此用法可能在未来发生变化

接口授权

  1. 手机SDK 获取用户 Token
  2. 设备SDK 登录后,key, secret 签名方式
  3. 后续考虑基于OAuth 的授权方式

通过 HTTP Authorization Header 对接口进行验权

  1. 通过设备SDK获取的token, 使用如下方式授权
    Authorization: AuthKey1.0 <Token>
  2. 通过手机SDK获取的Token, 使用如下
    Authorization: MobileToken1.0 <Token>

AuthKey1.0 示例算法

/**
 * make sign string
 * @param {object} info
 * @param {string} info.service 'rest'
 * @param {string} info.version '1'
 * @param {string} info.time 时间戳,按秒
 * @param {string} info.key key from sdk
 * @param {string} info.deviceId deviceId from sdk
 * @param {string} info.deviceTypeId deviceTypeId from sdk
 * @param {string} secret 开放平台 appSecret
 */
function makeSign(info, secret) {
  var s = `key=${info.key}&` +
    `device_type_id=${info.deviceTypeId}&` +
    `device_id=${info.deviceId}&` +
    `service=${info.service}&` +
    `version=${info.version}&` +
    `time=${info.time}&` +
    `secret=${secret}`
  return crypto.createHash('md5')
    .update(s).digest('hex').toUpperCase()
}

/**
 * generateToken
 * @param {object} data
 * @param {string} data.service 'rest'
 * @param {string} data.version '1'
 * @param {string} data.time 时间戳,按秒
 * @param {string} data.key key from sdk
 * @param {string} data.deviceId deviceId from sdk
 * @param {string} data.deviceTypeId deviceTypeId from sdk
 * @param {string} secret 开放平台 appSecret
 */
function generateAuthKey(data, secret) {
  var signature = makeSign(data, secret)
  var json = Object.assign({}, data, {
    signature: signature
  })
  return Buffer.from(JSON.stringify(json)).toString('base64')
}

示例

以下为部分参考示例,每个示例的每个步骤分开执行,每个步骤第一部分 query (QueryMutation),第二部分为可选的 variables

获取/创建家庭

对于绝大多数接口都需要 Home ID,因此你需要先获取一个 homeId

# 1. 列出家庭
{
  homes {
    id
  }
}

# 2. (Optional) 如果没有家庭,添加家庭
mutation AddHome($input: AddHomeInput!) {
  addHome(input: $input) {
    # 获取 homeId
    id
  }
}
# Variables
{
  "input": {
    "name": "杭州的家"
  }
}

授权 Skill

需要skillAuthURL Query 获取 URL,之后手动访问该 URL 完成授权。

# 授权 Skill
query SkillAuthURL(
  $skillId: String!, $callbackUri: String!, $homeId: String!) {
  skillAuthURL(
    skillId: $skillId,
    callbackUri: $callbackUri,
    homeId: $homeId
  ) {
    url
  }
}
# Variables, <home-id> 从上面的步骤获取,以 360 为例
{
  "skillId": "360",
  "callbackUri": "http://amazing.uri.com/callback",
  "homeId": "<home-id>"
}

同步终端列表

拉取单个云端技能的终端列表。该操作是异步的,需要创建一个任务 (Search),同步结果要查询一次或多次(如果 statusPENDING)该 Search 以获得。

# 1. 获取 skillAccountId
{
  skillAccounts {
    id
    homeId
    skillId
  }
}

# 2. 创建终端搜索
mutation CreateSearch(
  $homeId: String!,
  $skillAccountId: String!
) {
  createSearch(
    homeId: $homeId,
    skillAccountId: $skillAccountId
  ) {
    id
  }
}
# Variables
{
  "homeId": "<home-id>",
  "skillAccountId": "<skill-account-id>"
}

# 3. 获取终端同步结果,如果 status 是 PENDING 说明同步未完成,需要一定时间后再查询
query Search($searchId: String!) {
  search(searchId: $searchId) {
    status
    error {
      code
      name
    }
  }
}
# Variables
{
  "searchId": "<search-id>"
}

控制终端

使用create Mutation,参考 https://developer.rokid.com/docs/rokid-homebase-docs/v1/device/actions-and-state.html

# 1. 获取终端列表
query Endpoints($homeId: String!) {
  endpoints(homeId: $homeId) {
    id
    homeId
    roomId
    name
  }
}
# Variables, <home-id> 从上面的步骤获取
{
  "homeId": "<home-id>"
}

# 2. 控制特定终端,返回的 ID 需要控制完成后才能查询
mutation CreateAction(
  $homeId: String!,
  $endpointId: String!,
  $property: String!,
  $name: String!
) {
  createAction(
    endpointId: $endpointId,
    homeId: $homeId,
    property:$property,
    name: $name
  ){
    id
  }
}
# Variables, <home-id> 及 <endpointId> 从上面的步骤获取,以
# switch.on 为例,将打开 <endpointId> 终端
{
  "homeId": "<home-id>",
  "endpointId": "<endpoint-id>",
  "property": "switch",
  "name": "on"
}

# 3. 查询控制结果
query Action($actionId: String!) {
  action(actionId: $actionId) {
    error
    execList
  }
}
# Variables
{
  "actionId": "<action-id>"
}