diff --git a/doc/24.How_To_Use_Esp8266_Tencent_Firamware_Connect_Iot_Explorer.md b/doc/24.How_To_Use_Esp8266_Tencent_Firamware_Connect_Iot_Explorer.md
new file mode 100644
index 00000000..66cb448f
--- /dev/null
+++ b/doc/24.How_To_Use_Esp8266_Tencent_Firamware_Connect_Iot_Explorer.md
@@ -0,0 +1,691 @@
+# 1. 腾讯云ESP8266定制固件说明及烧录
+腾讯云IoT AT指令是一套针对使用通讯模组(2G/4G/NB/WIFI)接入腾讯云物联平台的定制AT指令集,如果通讯模组实现了该指令集,则设备接入和通讯更为简单,所需代码量更少。 ESP8266作为IoT领域使用最广泛的一款WiFi芯片/模组,我们在其通用AT指令基础上,增加了腾讯云IoT AT指令集,形成一个定制的模组固件QCloud_IoT_AT_ESP8266,腾讯云IoT定制的AT模组固件QCloud_IoT_AT_ESP8266,适用于所有FLASH大小为2MB或者2MB以上的ESP8266模组。
+
+固件烧录方法请阅读文档:[腾讯云 IoT AT ESP8266 定制固件及说明](https://github.com/tencentyun/qcloud-iot-esp-wifi)。
+
+# 2. 云端配置
+登录[腾讯云物联网开发平台(IoT Explorer)](https://cloud.tencent.com/product/iotexplorer),点击“立即使用”进入控制台。
+
+## 2.1. 新建项目
+项目是为了用户面对不同的产品迭代或不同的项目角色而设计的一种隔离机制,便于用户清晰管理物联网项目,并能灵活地配置项目权限。
+
+- 项目下可以建立多个产品与应用,应用默认有权限访问该项目下的**所有产品**;
+- 每个项目会有自己的唯一 ID,数据会根据项目进行隔离,以确保数据安全;
+- 项目删除后,该项目所属产品等数据都将被删除且不能恢复;
+- 开发平台提供资源级的权限控制,可为不同的子用户分配项目级、产品级的权限控制;
+
+点击新建项目,填写项目名称和简介:
+
+
+## 2.2. 产品开发
+### 2.2.1. 新建产品
+点击项目名称进入到该项目中,点击新建产品:
+
+填写产品的一些信息:
+
+- 产品名称:名称为中文、字母、数字、下划线的组合,1 - 20位且不能为空。
+- 产品品类:选择您所创建产品的所属品类,不同类型产品的属性、事件等数据模板会有所不同。详情请参见 数据模板。
+- 设备类型:设备使用2G/3G/4G/Wi-Fi无线通信或有线通信方式,网关可提供云端通信能力,帮助设备与平台通信。
+- 认证方式:物联网开发平台提供两种认证方式用于设备与平台之间鉴权认证。
+ - 证书认证:在创建设备时,平台将为设备生成一个证书文件和一个私钥文件,实现设备与云之间的双向认证。
+ - 密钥认证:在创建设备时,使用平台为设备随机生成的 PSK。
+- 通信方式:您可以选择 Wi-Fi、移动蜂窝(2G/3G/4G)和其他通信方式。
+- 数据协议:默认采用数据模板的数据协议,您也可以自定义协议进行透传。
+- 描述:字数不能超过80个,您可以根据需要选填。
+
+
+
+ 产品新建成功后,可在产品列表页查看到“智能灯”。
+
+
+### 2.2.2. 数据模板
+数据模板是将物理实体设备进行数字化描述,构建其数字模型。在物联网开发平台定义数据模板即定义产品功能。完成功能定义后,系统将自动生成该产品的数据模板。
+
+进入产品,点击新建功能。
+
+填写功能信息。
+
+功能类型包含三元素:
+
+- 属性:包括布尔型、整数型、字符型、浮点型、枚举型和时间型等6种基本数据类型;
+- 事件:包括告警、故障和信息三种类型,事件型功能属性可以添加具体的事件参数,这些参数可以由属性中6种基本数据类型组成;
+- 行为:用于实现更复杂的业务逻辑,可包含输入参数和输出参数,可用于让设备执行某项特定的任务。行为的输入参数和输出参数可添加上述6种属性的基本数据类型。
+
+| 功能元素 | 功能描述 |功能标识符|
+|:---------:|---------|:--------:|
+| 属性 | 用于描述设备的实时状态,支持读取和设置,如模式、亮度、开关等。|PropertiesId|
+| 事件 | 用于描述设备运行时的事件,包括告警、信息和故障等三种事件类型,可添加多个输出参数,如环境传感器检测到空气质量很差,空调异常告警等。 |EventId|
+| 行为 | 用于描述复杂的业务逻辑,可添加多个调用参数和返回参数,用于让设备执行某项定特定的任务,例如,开锁动作需要知道是哪个用户在什么时间开锁,锁的状态如何等。 |ActionId|
+
+数据类型支持6种:
+
+- 布尔型:非真即假的二值型变量。例如,开关功能。
+- 整数型:可用于线性调节的整数变量。例如,空调的温度。
+- 字符型:以字符串形式表达的功能点,例如,灯的位置。
+- 浮点型:精度为浮点型的功能点。例如,压力值的范围:0.0 - 24.0。
+- 枚举型:自定义的有限集合值。例如,灯的颜色:白色、红色、黄色等。
+- 时间型:string 类型的 UTC 时间戳(毫秒)。
+
+选择“智能灯”类型后,系统会自动生成标准功能:
+
+
+数据模板是一个 JSON 格式的文件,使用数据模板协议,用户的设备需按数据模板定义要求传输设备数据到云端,并可使用基于数据模板的诸多业务功能,点击查看json可以看到上面创建功能的json格式:
+```json
+{
+ "version": "1.0",
+ "properties": [
+ {
+ "id": "power_switch",
+ "name": "电灯开关",
+ "desc": "控制电灯开灭",
+ "required": true,
+ "mode": "rw",
+ "define": {
+ "type": "bool",
+ "mapping": {
+ "0": "关",
+ "1": "开"
+ }
+ }
+ },
+ {
+ "id": "color",
+ "name": "颜色",
+ "desc": "灯光颜色",
+ "mode": "rw",
+ "define": {
+ "type": "enum",
+ "mapping": {
+ "0": "Red",
+ "1": "Green",
+ "2": "Blue"
+ }
+ }
+ },
+ {
+ "id": "brightness",
+ "name": "亮度",
+ "desc": "灯光亮度",
+ "mode": "rw",
+ "define": {
+ "type": "int",
+ "unit": "%",
+ "step": "1",
+ "min": "0",
+ "max": "100",
+ "start": "1"
+ }
+ },
+ {
+ "id": "name",
+ "name": "灯位置名称",
+ "desc": "灯位置名称:书房、客厅等",
+ "mode": "rw",
+ "required": false,
+ "define": {
+ "type": "string",
+ "min": "0",
+ "max": "64"
+ }
+ }
+ ],
+ "events": [
+ {
+ "id": "status_report",
+ "name": "DeviceStatus",
+ "desc": "Report the device status",
+ "type": "info",
+ "required": false,
+ "params": [
+ {
+ "id": "status",
+ "name": "running_state",
+ "desc": "Report current device running state",
+ "define": {
+ "type": "bool",
+ "mapping": {
+ "0": "normal",
+ "1": "fault"
+ }
+ }
+ },
+ {
+ "id": "message",
+ "name": "Message",
+ "desc": "Some extra message",
+ "define": {
+ "type": "string",
+ "min": "0",
+ "max": "64"
+ }
+ }
+ ]
+ },
+ {
+ "id": "low_voltage",
+ "name": "LowVoltage",
+ "desc": "Alert for device voltage is low",
+ "type": "alert",
+ "required": false,
+ "params": [
+ {
+ "id": "voltage",
+ "name": "Voltage",
+ "desc": "Current voltage",
+ "define": {
+ "type": "float",
+ "unit": "V",
+ "step": "1",
+ "min": "0.0",
+ "max": "24.0",
+ "start": "1"
+ }
+ }
+ ]
+ },
+ {
+ "id": "hardware_fault",
+ "name": "Hardware_fault",
+ "desc": "Report hardware fault",
+ "type": "fault",
+ "required": false,
+ "params": [
+ {
+ "id": "name",
+ "name": "Name",
+ "desc": "Name like: memory,tf card, censors ...",
+ "define": {
+ "type": "string",
+ "min": "0",
+ "max": "64"
+ }
+ },
+ {
+ "id": "error_code",
+ "name": "Error_Code",
+ "desc": "Error code for fault",
+ "define": {
+ "type": "int",
+ "unit": "",
+ "step": "1",
+ "min": "0",
+ "max": "2000",
+ "start": "1"
+ }
+ }
+ ]
+ }
+ ],
+ "profile": {
+ "ProductId": "FWR8PGACUS",
+ "CategoryId": "3"
+ },
+ "actions": []
+}
+```
+### 2.3. 创建设备
+进入设备调试界面,新建设备:
+
+
+进入设备之后即可看到对接信息。
+
+# 3. 设备端对接测试
+使用USB转串口将烧录好腾讯云定制固件的ESP8266连接到PC,使用串口助手打开串口开始调试。
+
+## 3.1. 入网
+测试AT指令是否正常:
+```
+AT
+
+OK
+```
+设置ESP8266工作模式为AP和STA并存:
+```
+AT+CWMODE=3
+
+OK
+```
+设置传输模式为普通传输模式:
+```
+AT+CIPMODE=0
+
+OK
+```
+开启多路模式:
+```
+AT+CIPMUX=1
+
+OK
+```
+入网:
+```
+AT+CWJAP="Mculover666","mculover666"
+WIFI CONNECTED
+WIFI GOT IP
+
+OK
+```
+
+## 3.2. 设置腾讯云对接信息
+
+示例:
+```
+AT+TCDEVINFOSET=1,"FWR8PGACUS","ESP8266_Dev_001","0VqX0xzrvwmivBHwzuBrCQ=="
+OK
++TCDEVINFOSET:OK
+```
+此信息会保存到Flash中,可以使用下面的命令查看:
+```
+AT+TCDEVINFOSET?
+```
+
+## 3.3. 连接腾讯云
+示例:
+```
+AT+TCMQTTCONN=1,5000,240,1,1
+OK
++TCMQTTCONN:OK
+```
+连接成功,此时在腾讯云IoT Explorer平台即可看到设备在线:
+
+
+
+## 3.4. 订阅和发布主题
+Explorer平台相比IoThub平台,支持的topic比较多,主要有如下功能:
+
+- 设备属性上报:设备端将定义的属性根据设备端的业务逻辑向云端上报。
+- 设备远程控制:从云端向设备端下发控制指令,即设置设备可写属性。
+- 获取设备最新上报信息:获取设备最新的上报数据。
+- 设备事件上报:设备可根据定义的数据模板中的事件,当事件被触发,则根据设备事件上报的协议上报告警、故障等事件信息。
+- 设备行为:云端可以通过 RPC 的方式来要求设备执行某个动作行为,适用于应用需要实时获取设备的执行结果的场景。
+
+### 3.4.1. 设备属性上报
+
+设备向云端上报数据的topic如下:
+
+ - 上行请求 Topic: `$thing/up/property/{ProductID}/{DeviceName}`
+ - 上行响应 Topic: `$thing/down/property/{ProductID}/{DeviceName}`
+
+这两个topic咋玩呢?
+
+**首先订阅上行响应topic:**
+```c
+AT+TCMQTTSUB="$thing/down/property/FWR8PGACUS/ESP8266_Dev_001",0
+```
+返回结果如下:
+```
+OK
++TCMQTTSUB:OK
+```
+
+接着向上行请求topic上报数据,上报数据时平台不仅规定了topic,还规定了数据内容,如下:
+```json
+{
+ "method":"report",
+ "clientToken":"clientToken-145023f5-bc9b-4174-ba3b-430ba5956e5c",
+ "params":
+ {
+ "brightness":55,
+ "name":"bedroom",
+ "power_switch":1,
+ "color":2
+ }
+}
+```
+其中每一项的意义如下;
+
+
+ 参数 |
+ 类型 |
+ 说明 |
+
+
+ method |
+ String |
+ report 表示设备属性上报。 |
+
+
+ clientToken |
+ String |
+ 用于上下行消息配对标识 |
+
+
+ timestamp |
+ Integer |
+ 属性上报的时间 |
+
+
+ params |
+ JSON |
+ JSON 结构内为设备上报的属性值 |
+
+
+
+所以组合出来上报数据的AT指令如下:
+```c
+AT+TCMQTTPUB="$thing/up/property/FWR8PGACUS/ESP8266_Dev_001",0,"{\"method\":\"report\"\,\"clientToken\":\"clientToken-145023f5-bc9b-4174-ba3b-430ba5956e5c\"\,\"params\":{\"brightness\":55\,\"name\":\"bedroom\"\,\"power_switch\":1\,\"color\":2}}"
+```
+返回结果如下:
+```
+OK
++TCMQTTPUB:OK
+```
+同时,因为订阅了上行响应topic,所以模组会收到云端下发的响应并通过URC模式上报:
+```c
++TCMQTTRCVPUB:"$thing/down/property/FWR8PGACUS/ESP8266_Dev_001",118,"{"method":"report_reply","clientToken":"clientToken-145023f5-bc9b-4174-ba3b-430ba5956e5c","code":0,"status":"success"}"
+```
+云端响应报文整理一下格式如下:
+```json
+{
+ "method":"report_reply",
+ "clientToken":"clientToken-145023f5-bc9b-4174-ba3b-430ba5956e5c",
+ "code":0,
+ "status":"success"
+}
+```
+其中每一项也有具体的含义:
+
+
+
+ 参数 |
+ 类型 |
+ 说明 |
+
+
+ method |
+ String |
+ report_reply 表示云端接收设备上报后的响应报文 |
+
+
+ clientToken |
+ String |
+ 用于上下行消息配对标识 |
+
+
+ code |
+ Integer |
+ 0表示云端成功收到设备上报的属性 |
+
+
+ status |
+ String |
+ 当code非0的时候, 提示错误信息 |
+
+
+
+在云端查看设备上报的数据:
+
+同时在设备日志中可以查看设别上报的数据内容。
+
+### 3.4.2. 设备远程控制
+经过3.4.1节的玩法说明,后续都是一样的玩法。
+
+云端下发控制指令的 Topic如下:
+
+ - 下发 Topic: `$thing/down/property/{ProductID}/{DeviceName}`
+ - 响应 Topic: `$thing/up/property/{ProductID}/{DeviceName}`
+
+下面讲述如何玩。
+
+首先订阅下发Topic:
+```c
+AT+TCMQTTSUB="$thing/down/property/FWR8PGACUS/ESP8266_Dev_001",0
+```
+返回结果如下,订阅成功:
+```
+OK
++TCMQTTSUB:OK
+```
+
+然后在云端进入设备在线调试,修改灯的属性,然后下发控制命令:
+
+在串口助手中可以看到设备收到了云端下发的数据,并以URC模式上报:
+```c
++TCMQTTRCVPUB:"$thing/down/property/FWR8PGACUS/ESP8266_Dev_001",156,"{"method":"control","clientToken":"clientToken-e037d04b-c3a4-4350-8d67-5c6be19b888a","params":{"name":"bedroom","power_switch":0,"color":0,"brightness":30}}"
+```
+整理一下json内容的格式,可以看到与我们期待下发的数据相对应:
+```json
+{
+ "method":"control",
+ "clientToken":"clientToken-e037d04b-c3a4-4350-8d67-5c6be19b888a",
+ "params":
+ {
+ "name":"bedroom",
+ "power_switch":0,
+ "color":0,
+ "brightness":30
+ }
+}
+```
+
+注意,此时设备还需要手动给平台回复内容给下发响应topic,内容格式如下:
+```json
+{
+ "method":"control_reply",
+ "clientToken":"clientToken-e037d04b-c3a4-4350-8d67-5c6be19b888a",
+ "code":0,
+ "status":"success"
+}
+```
+组合出来发布回应消息的AT指令如下:
+```c
+AT+TCMQTTPUB="$thing/up/property/FWR8PGACUS/ESP8266_Dev_001",0,"{ \"method\":\"control_reply\"\, \"clientToken\":\"clientToken-e037d04b-c3a4-4350-8d67-5c6be19b888a\"\, \"code\":0\, \"status\":\"success\" }"
+```
+返回结果如下:
+```
+OK
++TCMQTTPUB:OK
+```
+
+### 3.4.3. 获取设备最新上报信息
+设备从云端接收最新消息使用的 Topic如下:
+
+ - 请求 Topic: `$thing/up/property/{ProductID}/{DeviceName}`
+ - 响应 Topic: `$thing/down/property/{ProductID}/{DeviceName}`
+
+首先订阅响应topic(之前已经订阅过,不用重复订阅)。
+
+向请求Topic发送数据,请求内容如下:
+```json
+{
+ "method": "get_status",
+ "clientToken": "123",
+ "type" : "report",
+ "showmeta": 0
+}
+```
+组合一下发出的AT指令如下:
+```c
+AT+TCMQTTPUB="$thing/up/property/FWR8PGACUS/ESP8266_Dev_001",0,"{ \"method\": \"get_status\"\, \"clientToken\": \"123\"\, \"type\" : \"report\"\, \"showmeta\": 0 }"
+```
+返回结果如下:
+```
+OK
++TCMQTTPUB:OK
+```
+同时设备收到了云端的响应:
+```c
++TCMQTTRCVPUB:"$thing/down/property/FWR8PGACUS/ESP8266_Dev_001",175,"{"method":"get_status_reply","clientToken":"123","code":0,"status":"success","type":"report","data":{"reported":{"brightness":55,"name":"bedroom","power_switch":1,"color":2}}}"
+```
+将其中的json内容整理格式如下,和当前设备最后一次上报数据的状态对应:
+```c
+{
+ "method":"get_status_reply",
+ "clientToken":"123",
+ "code":0,
+ "status":"success",
+ "type":"report",
+ "data":
+ {
+ "reported":
+ {
+ "brightness":55,
+ "name":"bedroom",
+ "power_switch":1,
+ "color":2
+ }
+ }
+}
+```
+### 3.4.4. 设备事件上报
+设备向云端上报事件的 Topic如下:
+
+ - 上行请求 Topic: `$thing/up/event/{ProductID}/{DeviceName}`
+ - 上行响应 Topic: `$thing/down/event/{ProductID}/{DeviceName}`
+
+首先订阅上行响应Topic:
+```c
+AT+TCMQTTSUB="$thing/down/event/FWR8PGACUS/ESP8266_Dev_001",0
+```
+返回结果如下:
+```
+OK
++TCMQTTSUB:OK
+```
+
+接着向上行请求Topic发布消息,事件内容格式如下:
+```c
+{
+ "method":"event_post",
+ "clientToken":"123",
+ "version":"1.0",
+ "eventId":"low_voltage",
+ "type":"alert ",
+ "params":
+ {
+ "Voltage":2.8
+ }
+}
+```
+
+其中参数说明如下:
+
+
+
+ 参数 |
+ 类型 |
+ 说明 |
+
+
+ method |
+ String |
+ event_post 表示事件上报。 |
+
+
+ clientToken |
+ String |
+ 消息 ID,回复的消息将会返回该数据, 用于请求响应消息的对比。 |
+
+
+ version |
+ String |
+ 协议版本,默认为1.0。 |
+
+
+ eventId |
+ String |
+ 事件的 ID,在数据模板事件中定义。 |
+
+
+ params |
+ String |
+ 事件的参数,在数据模板事件中定义。 |
+
+
+ timestamp |
+ Integer |
+ 事件上报的时间,不填写该字段表示就使用事件上报本身的时间。 |
+
+
+ type |
+ String |
+ 事件类型,info 为信息,alert 为告警,fault 为故障。 |
+
+
+
+组合出向上行请求发送的AT命令如下:
+```c
+AT+TCMQTTPUB="$thing/up/event/FWR8PGACUS/ESP8266_Dev_001",0,"{ \"method\":\"event_post\"\, \"clientToken\":\"123\"\, \"version\":\"1.0\"\, \"eventId\":\"low_voltage\"\, \"type\":\"alert \"\, \"params\": { \"voltage\":2.8 } }"
+```
+返回结果如下,上报成功:
+```
+OK
++TCMQTTPUB:OK
+```
+同时收到平台发给设备的回应:
+```
++TCMQTTRCVPUB:"$thing/down/event/FWR8PGACUS/ESP8266_Dev_001",75,"{"method":"event_reply","clientToken":"123","code":0,"status":"","data":{}}"
+```
+其中的json数据整理一下如下:
+```c
+{
+ "method":"event_reply",
+ "clientToken":"123",
+ "code":0,
+ "status":"",
+ "data":{}
+}
+```
+在云端设备事件日志中可以看到:
+
+
+### 3.4.5. 设备行为调用
+当应用通过云端向设备发起某个行为调用时,开发平台为设备行为的处理设定了默认的 Topic 如下:
+
+ - 应用调用设备行为 Topic: `$thing/down/action/{ProductID}/{DeviceName}`
+ - 设备响应行为执行结果 Topic: `$thing/up/action/{ProductID}/{DeviceName}`
+
+首先订阅设备应用调用设备行为的Topic:
+```c
+AT+TCMQTTSUB="$thing/down/action/FWR8PGACUS/ESP8266_Dev_001",0
+```
+返回结果如下:
+```
+OK
++TCMQTTSUB:OK
+```
+智能灯默认数据模板中没有……需要手动创建,新建一个行为功能:
+
+新建之后在自定义功能这一栏即可看到:
+
+进入设备在线调试界面,发送行为:
+
+在串口助手中可以看到模组接收到云端的消息:
+```c
++TCMQTTRCVPUB:"$thing/down/action/FWR8PGACUS/ESP8266_Dev_001",132,"{"method":"action","clientToken":"1d603a84c71e4d1da38c2dacce27112e","actionId":"blink","timestamp":1593396804,"params":{"period":5}}"
+```
+整理一下json格式如下:
+```json
+{
+ "method":"action",
+ "clientToken":"1d603a84c71e4d1da38c2dacce27112e",
+ "actionId":"blink",
+ "timestamp":1593396804,
+ "params":
+ {
+ "period":5
+ }
+}
+```
+在串口助手中向设备响应行为执行结果 Topic回复响应,响应内容格式如下:
+```json
+{
+ "method": "action_reply",
+ "clientToken": "1d603a84c71e4d1da38c2dacce27112e",
+ "code": 0,
+ "status": "success",
+ "response": {
+ "Code": 0
+ }
+}
+```
+组合出发送响应的AT指令如下;
+```c
+AT+TCMQTTPUB="$thing/up/action/FWR8PGACUS/ESP8266_Dev_001",0,"{ \"method\": \"action_reply\"\, \"clientToken\": \"1d603a84c71e4d1da38c2dacce27112e\"\, \"code\": 0\, \"status\": \"success\"\, \"response\": { \"Code\": 0 } }"
+```
+返回结果为:
+```
+OK
++TCMQTTPUB:OK
+```
+至此,使用ESP8266腾讯云定制固件对接腾讯云IoT Explorer平台的测试完成。
diff --git a/doc/25.How_To_Use_Esp8266_Tencent_Firamware_Connect_Iot_Hub.md b/doc/25.How_To_Use_Esp8266_Tencent_Firamware_Connect_Iot_Hub.md
new file mode 100644
index 00000000..446539cb
--- /dev/null
+++ b/doc/25.How_To_Use_Esp8266_Tencent_Firamware_Connect_Iot_Hub.md
@@ -0,0 +1,248 @@
+# 1. 腾讯云ESP8266定制固件说明及烧录
+
+腾讯云IoT AT指令是一套针对使用通讯模组(2G/4G/NB/WIFI)接入腾讯云物联平台的定制AT指令集,如果通讯模组实现了该指令集,则设备接入和通讯更为简单,所需代码量更少。 ESP8266作为IoT领域使用最广泛的一款WiFi芯片/模组,我们在其通用AT指令基础上,增加了腾讯云IoT AT指令集,形成一个定制的模组固件QCloud_IoT_AT_ESP8266,腾讯云IoT定制的AT模组固件QCloud_IoT_AT_ESP8266,适用于所有FLASH大小为2MB或者2MB以上的ESP8266模组。
+
+固件烧录方法请阅读文档:[腾讯云 IoT AT ESP8266 定制固件及说明](https://github.com/tencentyun/qcloud-iot-esp-wifi)。
+
+# 2. 云端配置
+登录腾讯云, 搜索"云产品"下的"物联网通信"产品, 或直接访问:
+
+[https://console.cloud.tencent.com/iotcloud](https://console.cloud.tencent.com/iotcloud)
+
+
+
+## 2.1. 创建新产品
+
+> 对于认证方式, 指定了设备通过何种方式和云端进行双向认证. 默认的证书方式相对于密钥认证安全性高一点, 但是问题在于证书方式需要在嵌入式设备端存储证书同时实现证书的相关处理, 对设备的RAM和ROM要求较高, 相对而言, 密钥认证的方式资源占用量就小点, 由于我们主要支持的设备都是小型嵌入式设备, 因此选用密钥认证。
+
+> 数据格式指的是设备和云端进行数据交互时候使用的格式, json格式为文本字符串, 可读性高, 并且便于解析, 对于功能复杂的设备交互而已比较理想, 但是对于小型设备或是定制设备, 数据单一, 或是有自定义的格式(二进制或是文本), 这种时候, 用自定义的数据格式, 一方面节约流量, 另一方面比较灵活.。
+
+创建成功后,获取到产品ID:
+
+
+## 2.2. 创建新设备
+
+
+添加完设备后, 会告知设备对应的密钥. 该密钥将会用于之后设备与平台通信时的认证:
+
+为了实现设备间的通信, 我们还需要创建第二个设备, 操作同上, 将其命名为"dev2":
+
+
+## 2.3. 设置Topic
+可以在"权限列表"中看到Topic对应的操作权限:
+
+
+平台默认配置了三类的Topic, 用于执行发布和订阅.,这里之所以**是三类而不是三个**, 是因为Topic里使用了变量.。
+
+- `WDRRDCF1TE`实际上是productID;
+- `${deviceName}`为平台设置的变量, 即设备名;
+- `control`和`data`以及`event`为Topic名字.;
+
+所以, 在我们创建了2个设备dev1和dev2的情况下, 在 BearPiTest 产品下, 即存在6个Topic, 分别为:
+
+- WDRRDCF1T/dev1/control 订阅权限
+- WDRRDCF1T/dev1/data 发布和订阅权限
+- WDRRDCF1T/dev1/event 发布权限
+- WDRRDCF1T/dev2/control 订阅权限
+- WDRRDCF1T/dev2/data 发布和订阅权限
+- WDRRDCF1T/dev2/event 发布权限
+
+这里默认的Topic已经足够我们使用, 不需要额外添加Topic和权限了。
+
+## 2.4. 设置规则引擎
+规则引擎本身不属于MQTT协议的范畴, 但是平台侧出于安全角度考虑添加了规则引擎, 实现了Topic之间的转发操作, 我们需要合理的设置规则引擎才能实现多个设备之间的数据收发, 由于理解起来比较复杂, 我们这里简要讲解下为什么需要规则引擎, 规则引擎的作用, 如何设置规则引擎.
+
+1. 为什么需要规则引擎
+
+ 在上节的Topic中, 我们知道, 在平台侧, 对于不同的Topic, 规定了不同的权限, 例如, 对于`WDRRDCF1T/dev1/event`这个Topic, 只具有发布权限, 而对于`WDRRDCF1T/dev1/control`这个Topic, 只具有订阅权限. 对于设备dev1, 很自然的, 会朝`WDRRDCF1T/dev1/event`这个Topic发送数据, 并且订阅`WDRRDCF1T/dev1/control`这个Topic的消息. 但是这里就会涉及到, event的数据最后到哪去, control的数据从哪里来的问题.
+
+ 在本文的例子中, 我们希望dev1和dev2发生交互, 即相互收发消息. 由于MQTT是基于Topic的发布订阅机制, 因此, dev1想要获得dev2的数据, 直觉上, 需要订阅dev2发布消息的那个Topic. 假定dev2朝`25KCIUIR1G/dev2/event`Topic上发送数据, 那么dev1想要获得dev2发布的消息, 最直接的办法是订阅同样的Topic, 即`25KCIUIR1G/dev2/event`, 但是这里存在几个问题, 首先, event Topic只具有发布权限, 没有订阅权限, 其次, **在平台侧, 规定了, 不允许跨设备发布或是订阅Topic**, 也就是说, 对于dev1, 只能看到或只允许访问`WDRRDCF1T/dev1`这个Topic以及其下属的Topic, 不能访问`WDRRDCF1T/dev2`及其下属Topic.
+
+ > 平台侧添加不允许跨设备访问Topic的规则虽然不直观, 但却是合理的. 如果不添加这条限制, 那么一个设备可以不加限制的订阅同一个产品下所有其他设备的Topic, 获取其上报的消息, 这存在潜在的安全漏洞.
+
+2. 规则引擎的作用
+
+ 因为不允许直接跨设备访问Topic, 所以需要依靠"规则引擎"来手动添加规则, 将指定的Topic消息转发到另一个Topic上, 实现不同设备之间的通信.
+
+
+
+ 上图介绍了规则引擎的主要作用"republish", 即将一个Topic下的消息republish到另一个Topic下. 从图中我们可以看到, 规则引擎将`WDRRDCF1TE/dev2/event`的消息republish到了`WDRRDCF1TE/dev1/control`下. 将`WDRRDCF1TE/dev1/event`的消息republish到了`WDRRDCF1TE/dev2/control`下。
+
+ 这样, 对于dev1而言, 只需要订阅`WDRRDCF1TE/dev1/control`就可以接收来自`25KCIUIR1G/dev2/event`的消息了,dev2同理。
+
+3. 设置规则引擎
+
+ 在物联网通信界面选择"规则引擎"--"新建规则", 随意指定一个规则名称, 我们这里不妨设置为"1to2":
+
+
+
+这里, 我们看到规则的详细设置信息, 主要包括"筛选数据"和"行为操作"。
+
+"筛选数据"针对指定Topic接收到的消息内容进行进一步的筛选, 比如匹配消息中的字段来决定是否执行之后的设置的"行为操作".,而"行为操作"则是指定对通过匹配的消息进行何种操作, 主要的操作有"数据转发到另一个Topic(Republish)", "转发到第三方服务(Forward)"以及转发到腾讯云各个对应组件中。
+
+
+
+ 上图是设置好的规则, 这里, 我们将"筛选数据"部分的筛选字段设置为`*`, 筛选的Topic为`WDRRDCF1T/dev1/event`, 条件设置为空, 即不筛选数据, 全部匹配,然后, 执行的操作是将数据转发到`WDRRDCF1T/dev2/control`, 设置完这条规则, 就实现了dev2通过订阅control就能收到dev1发送到event的数据。
+
+ > 关于"筛选数据"的设定:
+ >
+ > 由于我们在新建产品, 设置数据格式的时候选择了自定义数据格式, 在自定义数据格式的情况下, 当前平台将其当做二进制流来处理, 也就无法通过匹配字段进行数据筛选.
+ >
+ > 如果在进行产品的时候, 使用数据格式是json, 那么此处就可以根据json中的字段进行SQL的匹配和筛选.
+
+ 同理, 我们再设置新的一个规则"2to1", 实现`WDRRDCF1T/dev2/event`到`WDRRDCF1T/dev1/control`的转发:
+
+
+ 规则引擎都设置好后,记得点启用按钮,这样, 在平台侧dev1到dev2的双向数据通路就打通了:
+
+
+## 2.5. 云日志
+在平台侧都设置好后, 我们在之后的测试过程或是通信过程中, 往往还需要查看平台是否收到了设备发送上来的消息, 对消息执行了哪些操作, 消息的具体内容(payload)是什么. 腾讯云提供了物联网通信产品的"云日志"功能和腾讯云组件"消息队列CMQ"。
+
+
+
+日志中可以看到日志记录了设备的连接, 连接断开, 发布, 订阅等行为, 也记录了规则引擎的操作, 还有CMQ队列的一些行为日志.。
+
+## 2.6. 消息队列CMQ
+可以在产品列表中找到"消息队列"选项, 设置队列所想要接收的消息类型后保存配置, 即可将平台侧收到的设备消息额外发送到腾讯云消息队列CMQ组件中:
+
+> 在密钥认证下, 消息的内容(payload)是经过base64编码的, 所以在平台侧看到的数据类似乱码实际上是经过编码后的结果, 想要查看具体的内容, 可以在linux下, `echo | base64 --decode`.
+
+# 3. 设备端对接测试
+使用USB转串口将烧录好腾讯云定制固件的ESP8266连接到PC,使用串口助手打开串口开始调试。
+
+## 3.1. 入网
+测试AT指令是否正常:
+```
+AT
+
+OK
+```
+设置ESP8266工作模式为AP和STA并存:
+```
+AT+CWMODE=3
+
+OK
+```
+设置传输模式为普通传输模式:
+```
+AT+CIPMODE=0
+
+OK
+```
+开启多路模式:
+```
+AT+CIPMUX=1
+
+OK
+```
+入网:
+```
+AT+CWJAP="Mculover666","mculover666"
+WIFI CONNECTED
+WIFI GOT IP
+
+OK
+```
+
+## 3.2. 设置腾讯云对接信息
+
+示例:
+```
+AT+TCDEVINFOSET=1,"WDRRDCF1TE","dev1","ULtbpSxXtSQyaFyeaax6pw=="
+OK
++TCDEVINFOSET:OK
+```
+此信息会保存到Flash中,可以使用下面的命令查看:
+```
+AT+TCDEVINFOSET?
++TCDEVINFOSET:1,"WDRRDCF1TE","dev1",113
+
+OK
+```
+
+## 3.3. 连接腾讯云
+示例:
+```
+AT+TCMQTTCONN=1,5000,240,1,1
+OK
++TCMQTTCONN:OK
+```
+连接成功,此时在腾讯云IoThub平台即可看到设备在线:
+
+## 3.4. 订阅主题
+示例:
+```
+AT+TCMQTTSUB="WDRRDCF1TE/dev1/data",0
+OK
++TCMQTTSUB:OK
+```
+订阅成功之后,在云端进入设备在线调试,发送测试数据:
+
+在串口助手中可以看到ESP8266模组通过URC方式上报的数据:
+
+## 3.5. 发布消息
+示例:
+```
+AT+TCMQTTPUB="WDRRDCF1TE/dev1/data",0,"helloworld"
+```
+返回结果为:
+```
+OK
++TCMQTTPUB:OK
+```
+在云端可以看到设备上报的消息:
+
+
+# 4. OTA升级
+腾讯云定制固件中内置了与IoThub平台OTA固件升级对接的AT指令,整个升级流程如下:
+
+在模组连接IoThub平台成功之后进行如下的操作。
+
+## 4.1. 使能OTA功能
+```c
+AT+TCOTASET=1,"0.1"
+```
+返回结果如下:
+```
+OK
++TCOTASET:OK
+```
+
+指令成功,此时模组已经处于监听升级命令状态。
+
+## 4.2. 云端下发固件
+将待升级的固件上传到云平台:
+
+选择下发0.2版本的固件:
+
+在串口助手中可以看到模组上报的URC数据:
+```
++TCOTASTATUS:ENTERUPDATE
++TCOTASTATUS:UPDATESUCCESS
+```
+## 4.3. 读取模组缓存的固件信息
+```c
+AT+TCFWINFO?
+```
+返回结果为:
+```c
+OK
++TCFWINFO:"0.2",6892,"1eb6c5f8622f5b005bc3ff8f01575df8",716800
+```
+从中得到缓存的固件信息如下:
+
+- 固件版本:0.2
+- 固件大小:6892字节
+- 固件MD5
+- 用户待升级的OTA固件的最大字节数,700KB
+
+## 4.4. 读取模组缓存的固件数据
+每次读取512字节:
+```c
+AT+TCREADFWDATA=512
+```
+
+当最后一次读取的时候,模组实际返回读取大小为236字节,小于512字节,表示读取结束。
+
+