设备影子数据流

最近更新时间:2019-08-28 16:22:38

设备影子 Topic

设备影子充当中介,支持设备和用户应用程序查看和更新设备状态。设备、用户应用程序、设备影子三者之间通过两个特殊的 Topic 来实现通信:

  • $shadow/operation/${productId}/${deviceName}:用于发布(上行)消息,可实现对设备影子数据的 get/update 操作。
  • $shadow/operation/result/${productId}/${deviceName}:用于订阅(下行)消息,影子服务端通过此 Topic 发送应答和推送消息。
说明:

以上主题均为设备创建时由系统默认创建,设备 SDK 内部会自动订阅上述主题。

设备获取影子状态

如果设备想要获取设备影子最近的状态时,需要向 $shadow/operation/${productId}/${deviceName} 主题发布 get 消息。SDK 会提供 API 发送 get 消息,get 消息使用特定的 JSON 字符串格式:

{
 "type": "get",
 "clientToken": "clientToken"
}
说明:

clientToken 是用于唯一标识会话业务的 TOKEN ,由请求端生成,应答端原样传回。

例如:空调设备,可以通过 SDK 提供的 API 向 $shadow/operation/ABC1234567/AirConditioner 发送 get 消息,获取最新的设备参数。

设备影子服务端通过向 $shadow/operation/result/${productId}/${deviceName} 主题发布消息进行响应,通过 JSON 数据返回设备影子所有数据内容,SDK 会通过相应的回调函数通知业务层。

影子服务端通过向 $shadow/operation/result/ABC1234567/AirConditioner 发送下列数据来响应空调设备的 get 请求。示例代码如下:

{
 "type": "get",
 "result": 0,
 "timestamp": 1514967088,
 "clientToken": "clientToken",
 "payload": {
  "state": {
   "reported": {
    "temperature": 27
   },
   "desired": {
    "temperature": 25
   },
   "delta": {
    "temperature": 25
   }
  },
  "metadata": {
   "reported": {
    "temperature": {
     "timestamp": 1514967066
    }
   },
   "desired": {
    "temperature": {
     "timestamp": 1514967076
    }
   },
   "delta": {
    "temperature": {
     "timestamp": 1514967076
    }
   }
  },
  "version": 1,
  "timestamp": 1514967076
 }
}

如果设备影子文档中有 desired 部分,则设备影子服务会自动生成相应的 delta 部分。如果没有 desired 部分,则没有 desired 和 delta 部分的内容。

说明:

设备影子服务 不存储 delta 消息。

设备更新影子

设备通过向 $shadow/operation/${productId}/${deviceName} 主题发送 update 消息,告知设备影子服务端其当前状态。SDK 提供相应的 API 发送 update 消息,业务层只需指定 reported 字段的内容。消息内容使用特定的 JSON 字串格式。

空调设备向 $shadow/operation/ABC1234567/AirConditioner 发送 update 消息以报告设备当前的设备状态。示例代码如下:

{
 "type": "update",
 "state": {
  "reported": {
   "temperature": 27
  }
 },
 "version": 1,
 "clientToken": "clientToken"
}

当设备影子服务端收到此消息时,首先判断消息中的 version 是否与设备影子服务端中的 version 一致。如果一致,则设备影子服务端执行更新设备影子流程。

影子服务端向空调设备应答消息。示例代码如下:

{
 "type": "update",
 "result": 0,
 "timestamp": 1514967066,
 "clientToken": "clientToken",
 "payload": {
  "state": {
   "reported": {
    "temperature": 27
   }
  },
  "metadata": {
   "reported": {
    "temperature": {
     "timestamp": 1514967066
    }
   }
  },
  "version": 2,
  "timestamp": 1514967066
 }
}

如果消息中的 version 与设备影子服务端的 version 不一致,则设备影子服务向 $shadow/operation/result/ABC1234567/AirConditioner 发送以下消息进行回应。

{
 "type": "update",
 "result": 5005,
 "timestamp": 1514967066,
 "clientToken": "clientToken",
 "payload": {
  "state": {
   "reported": {
    "temperature": 27,
    "mode": "cool"
   }
  },
  "metadata": {
   "reported": {
    "temperature": {
     "timestamp": 1514967066
    },
    "mode": {
     "timestamp": 1514967050
    }
   }
  },
  "version": 2,
  "timestamp": 1514967066
 }
}

此时 payload 中的内容将返回完整的设备影子文档内容。

应用程序更新影子

用户应用程序通过 HTTP RESTful API 修改设备影子 desired 字段。

用户应用程序通过 HTTP RESTful API 修改空调运行参数。示例代码如下:

{
 "type": "update",
 "state": {
  "desired": {
   "temperature": 25
  }
 },
 "version": 2,
 "clientToken": "clientToken"
}

当设备影子服务端收到此消息后,首先判断消息中的 version 是否与设备影子服务端中的 version 一致。如果一致,则执行更新设备影子流程,并通过 HTTP RESTful API 给应用程序应答 JSON 消息。

{
 "type": "update",
 "result": 0,
 "timestamp": 1514967076,
 "clientToken": "clientToken",
 "payload": {
  "state": {
   "desired": {
    "temperature": 25
   }
  },
  "metadata": {
   "desired": {
    "temperature": {
     "timestamp": 1514967076
    }
   }
  },
  "version": 3,
  "timestamp": 1514967076
 }
}

另外,影子服务端通过向 $shadow/operation/result/ABC1234567/AirConditioner 发送 delta 消息。

{
 "type": "delta",
 "timestamp": 1514967076,
 "payload": {
  "state": {
   "temperature": 25
  },
  "metadata": {
   "temperature": {
    "timestamp": 1514967076
   }
  },
  "version": 3,
  "timestamp": 1514967076
 }
}

SDK 通过相应的回调函数通知业务层消息已收到。

设备应答 delta 消息

当设备收到 delta 消息后,业务层可以将 desired 字段内容置空并发送给设备影子服务端,表示设备已经 响应 本次 delta 消息,方式是通过向 $shadow/operation/${productId}/${deviceName} 主题发送消息。

例如:空调调整温度后,向 $shadow/operation/ABC1234567/AirConditioner 发送消息:

{
 "type": "update",
 "state": {
  "desired": null
 },
 "version": 3,
 "clientToken": "clientToken"
}

SDK 提供相应的 API 发送上述消息。当设备影子服务端收到该消息后,会将 desired 字段内容清除,防止由于 reported 与 desired 中属性值不同引起的重复下发。

影子服务端收到消息后,通过向: $shadow/operation/result/${productId}/${deviceName} 发送应答消息。

例如:影子服务端收到空调的 "desired":null 消息后,通过向 $shadow/operation/result/ABC1234567/AirConditioner 发送更新设备影子文档成功的消息。

{
 "type": "update",
 "result": 0,
 "timestamp": 1514967086,
 "clientToken": "clientToken",
 "payload": {
  "state": {
   "reported": {
    "temperature": 25
   },
   "desired": null
  },
  "metadata": {
   "reported": {
    "temperature": {
     "timestamp": 1514967086
    }
   },
   "desired": {
    "temperature": {
     "timestamp": 1514967086
    }
   }
  },
  "version": 4,
  "timestamp": 1514967086
 }
}

如果设备 reported 某些属性字段为 null,则代表要将设备影子中相应的字段删除。update 成功时,返回的 payload 内容中,字段仅包含对此次更新字段的相关内容。

如果设备 update 时携带上的 version 值小于服务端上保存的 version 值,则代表设备上的数据是旧的。此时服务端将发送失败消息,其中的返回码( result 字段)会明确告知 SDK 本次 update 失败,原因是 version 版本过低,同时在 payload 中携带最新的内容一同下发给设备端。