
# 设备侧适配开发指导
 #### 概述
设备的OTA软件升级是基于华为定义的[PCP协议](https://support.huaweicloud.com/devg-iothub/iot_01_0047_3.html)进行的，设备侧需根据PCP协议定义的交互流程进行适配开发。下面我们将结合物联网平台与设备的软件升级交互流程，介绍终端设备将如何基于PCP协议构建交互过程中的请求消息和应答消息，帮助您更好的根据PCP协议进行终端侧的软件升级功能开发。
下面我们先了解下PCP消息的结构，PCP协议的请求消息和应答消息都遵循相同的消息结构，主要由这几部分组成：
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000001921587329.png "点击放大")
PCP协议消息由：起始标识位、版本号、消息码、校验码、数据区长度和数据区组成，各字段的要求和描述如下表所示。
| **字段名** | **字段类型**  | **描述和要求**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
|:---|:---|:---|
| 起始标识    | WORD      | 起始标识，固定为0XFFFE。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| 版本号     | BYTE      | 高四位预留；低四位表示协议版本号，当前为1。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 消息码     | BYTE      | 标识物联网平台与设备之间的请求消息类型，应答消息的消息码和请求消息相同。消息码的定义为： - 0-18：预留消息码，暂未使用。  - 19：查询设备版本。  - 20：下载新版本软件包通知。  - 21：请求下载升级包。  - 22：上报升级包下载结果。  - 23：执行软件升级。  - 24：上报升级结果。  - 25-127：预留消息码，暂未使用。   |
| 校验码     | WORD      | 从起始标识到数据区的最后一个字节的CRC16校验值，计算前先把校验码字段置为0，计算完成后把结果写到校验码字段。 说明： CRC16算法：CRC16/CCITT x16+x12+x5+1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| 数据区长度   | WORD      | 数据区的长度。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| 数据区     | BYTE\[n\] | 可变长度，具体由各个指令定义，可参考下面介绍的各个指令对应的请求消息和应答消息定义。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
   
| **数据类型**  | **描述**    |
|:---|:---|
| BYTE      | 无符号一字节整数  |
| WORD      | 无符号二字节整数  |
| DWORD     | 无符号四字节整数  |
| BYTE\[n\] | n字节的十六进制数 |
| STRING    | 字符串       |
   
#### 查询设备版本号
从设备的软件升级流程（本流程只描述物联网平台与设备基于PCP协议交互的流程）可以看到，首先物联网平台向设备下发查询版本号信息，设备进行应答。
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000001875668216.png)
**物联网平台发送消息**
根据[PCP消息结构的定义]可以得出，物联网平台向设备下发查询版本号时，各消息字段的填写如下：
- 起始标识：固定为消息流的前2个字节，固定为FFFE。
- 版本号：数据类型为1个字节整数，且固定为1，即在消息流中为01。
- 消息码：数据类型为1个字节整数，查询设备版本的消息码为19，转换为十六进制为13。
- 校验码：数据类型为2个字节整数，先将校验码置为0000，然后将完整的消息码流进行CRC16的算法计算得到校验码，再将得到的校验码替换原消息中的0000。
- 数据区长度：数据类型为2个字节整数，代表数据区的消息长度，根据数据区的数据结构可以得出该条消息无数据区，即数据区长度为0000。
- 数据区：数据区代表要真正发送给设备的数据，根据查询版本信息的数据区定义，该条消息是没有实际要传送的数据的，即无需数据区字段。
  
  | **字段** | **数据类型** | **描述及要求** |
  |:---|:---|:---|
  | 无数据区                        |||
     
  
因此将查询版本消息的码流组合起来得到：FFFE 01 13 0000 0000。前面的校验码时讲了，需要将组合后的消息码流进行CRC16算法（物联网平台提供了基于JAVA和C语言的[CRC16算法代码样例]，您可以直接使用）得到校验码4C9A，然后将该校验码替换原码流中的0000后得到FFFE01134C9A0000，该消息码流即为物联网平台发送给设备的查询版本信息的消息码流。
**设备返回的应答消息**
设备收到物联网平台要查询设备的软件版本号消息，设备要向物联网平台反馈查询的结果，各消息字段的填写如下。
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致，为13。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段的数据类型得出数据区长度为17个字节，转换为十六进制为：0011。
- 数据区：根据数据区的定义可知，处理成功的结果码为00，版本号信息假设为V0.9，将V0.9进行ASCII转码得到56302E39，由于版本号的数据类型为BYTE\[16\]，即16个字节，当前只有4个字节，因此需要在版本号数据后面补0，得到56302E39000000000000000000000000。因此，数据区合并后为0056302E39000000000000000000000000。
  
  | **字段** | **数据类型**   | **描述及要求**                        |
  |:---|:---|:---|
  | 结果码    | BYTE       | "0X00"处理成功                       |
  | 当前版本号  | BYTE\[16\] | 当前版本号，由ASCII字符组成，位数不足时，后补"0X00"。 |
     
  
将查询版本信息的消息流组合起来得到：FFFE 01 13 0000 0011 0056302E39000000000000000000000000。前面讲到，还要将消息流进行CRC16算法计算得到校验码为8DE3。因此，物联网平台向设备查询版本号信息，设备向平台返回的消息流为FFFE01138DE300110056302E39000000000000000000000000。
#### 下载新版本软件包通知
根据PCP协议约定的交互流程，查询完版本号后，物联网平台下发指令让设备下载新版本的软件包。
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000001921427685.png)
**物联网平台发送消息**
根据[PCP消息结构的定义]可以得出，物联网平台向设备下发下载新版本软件包通知时，各消息字段的填写如下。
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：此处为新版本通知，查询[消息码]表可以知道新版本通知为20，转换为十六进制为14。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的消息字段可以得出，数据区长度为22个字节，转换为十六进制为：0016。
- 数据区：根据数据区的定义可知。
  - 目标版本号：由16个字节组成，假设升级的目标版本号为v1.0版本，转换为十六进制并在后面14个字节补充0后得到：56312E30000000000000000000000000。
  
  - 升级包分片大小：由2个字节组成，单位为byte，用户上传软件包时可以手动输入升级包分片大小，如果不设置默认为500byte，大小为32\~500之间。假设为500byte，转换为十六进制后为：01F4。
  
  - 升级包分片总数：由2个字节组成，由软件包大小除以每个分片的大小并向上取整获得。假设软件包大小为500byte，则分片数量为1，转换为十六进制后为：0001。
  
  - 检验码：由2个字节组成，目前已废弃，固定为：0000。
    
    | **字段**  | **数据类型**   | **描述及要求**                        |
    |:---|:---|:---|
    | 目的版本号   | BYTE\[16\] | 目的版本号，由ASCII字符组成，位数不足时，后补"0X00"。 |
    | 升级包分片大小 | WORD       | 每个分片的大小                          |
    | 升级包分片总数 | WORD       | 升级包分片总数                          |
    | 升级包校验码  | WORD       | 固定为：0000                         |
       
    
  
  
  将下载新版本软件包通知的消息流组合起来得到：FFFE 01 14 0000 0016 56312E30000000000000000000000000 01F4 0001 0000。前面说了，还要将消息流进行CRC16算法计算得到校验码为02F7。因此，物联网平台向设备通知下载新版本软件包的信息，物联网平台向设备发送的消息流为FFFE011402F7001656312E3000000000000000000000000001F400010000。
  **设备返回的应答消息**
  设备收到下载新版本软件包通知后，设备向物联网平台返回应答消息，是否允许设备进行升级，各消息字段的填写如下。
  - 起始标识固定为：FFFE。
  
  - 版本号固定为：01。
  
  - 消息码：与请求的消息码一致，为14。
  
  - 校验码：CRC16计算前先用0000替代。
  
  - 数据区长度：根据数据区的字段的数据类型得出数据区长度为1个字节，转换为十六进制为：0001。
  
  - 数据区：设备根据自身的情况对平台下发的新版本通知进行响应，本示例以设备应答"允许升级"为例进行介绍，得出数据区为：00。其它应答消息请根据应答消息字段进行适配。
    
    | **字段** | **数据类型** | **描述及要求**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
    |:---|:---|:---|
    | 结果码    | BYTE     | "0X00"允许升级 "0X01"设备使用中 "0X02"信号质量差 "0X03"已经是最新版本 "0X04"电量不足 "0X05"剩余空间不足 "0X09"内存不足 "0X7F"内部异常 |
       
    
  
  
  将设备给物联网平台的应答消息流组合起来得到：FFFE 01 14 0000 0001 00。前面说了，还要将消息流进行CRC16算法计算得到校验码为D768。因此，设备向平台返回的应答消息流为FFFE0114D768000100。
  
 
#### 下载升级包
根据PCP协议约定的交互流程，物联网平台通知设备有新的软件版本时，设备向物联网平台请求下载软件包，按照分片的序号进行下载。
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000001875508336.png)
**设备发送的请求消息**
根据[PCP消息结构的定义]可以得出，设备向物联网平台发送的请求软件包分片的第一条消息，各消息字段的填写如下。
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：查询[消息码]表可知请求升级包的消息码为21，转换为十六进制为：15。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段的数据类型得出数据区长度为18个字节，转换为十六进制为：0012。
- 数据区：目标版本号为平台下发的新版本通知版本号，即v1.0，转换为十六进制为56312E30000000000000000000000000，分片序号为第0个分片，即0000。
  
  | **字段** | **数据类型**   | **描述及要求**                                                                              |
  |:---|:---|:---|
  | 目的版本号  | BYTE\[16\] | 目的版本号，由ASCII字符组成，位数不足时，后补"0X00"。                                                       |
  | 分片序号   | WORD       | 表示请求获取的分片序号，从0开始计算，分片的总数为软件包大小除以每个分片的大小并向上取整获得。设备可以保存已经收到的分片，下次直接从缺失的分片开始请求，达到断点续传的效果。 |
     
  
设备向物联网平台发送请求软件包分片的第一条消息为：FFFE 01 15 0000 0012 56312E30000000000000000000000000 0000（CRC16校验前），经CRC16计算得到校验码为：5618。则替换校验码后设备发送的第一条请求分片消息为：FFFE01155618001256312E300000000000000000000000000000。
其它分片请求的消息流只需要替换分片序号后，重新计算并替换CRC16校验码即可，此处就不再展开。
**物联网平台的应答消息**
物联网平台收到设备的请求软件包分片消息后，将会给设备下发分片的数据。物联网平台向设备响应的第一条请求分片的消息，各消息字段的填写如下。
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致：15。
- 校验码：CRC16计算前先用0000替代。
- 数据区：先讲数据区再讲数据区长度。结果码：00，分片序号：第0个分片：0000，分片数据：跟软件包定义的内容有关，我们假设软件包内容为HELLO, IoT SOTA!，经ASCII码转换为十六进制为：48454C4C4F2C20496F5420534F544121，共16字节。用户上传软件包时手动输入升级包分片大小为500byte，即最大长度为500字节。这种情况下，无需在数据的后面补充0。
- 数据区长度：根据数据区的字段定义得出该数据长度为19，转换为十六进制为：0013。
  
  | **字段** | **数据类型**  | **描述及要求**                                                                                                                                                                                                                                                                                                       |
  |:---|:---|:---|
  | 结果码    | BYTE      | 0X00处理成功。 0X80升级任务不存在。 0X81指定的分片不存在。 |
  | 分片序号   | WORD      | 表示返回的分片序号。                                                                                                                                                                                                                                                                                                      |
  | 分片数据   | BYTE\[n\] | 分片的内容，n为实际的分片大小。如果结果码不为0，则不带此字段。                                                                                                                                                                                                                                                                                |
     
  
物联网平台向设备发送的第一个软件包分片消息为：FFFE 01 15 0000 0013 00 0000 48454C4C4F2C20496F5420534F544121（CRC16校验前），经CRC16计算得到校验码为：E107。则替换校验码后物联网平台向设备发送的第一个软件包分片消息为：FFFE0115E107001300000048454C4C4F2C20496F5420534F544121。
其它软件包分片的消息流只需要替换分片序号和分片数据后，重新计算并替换CRC16校验码即可，此处就不再展开。
#### 上报下载结果
根据PCP协议约定的交互流程，设备接收完所有分片数据并组装完软件包后，需要向物联网平台上报软件包的下载结果。
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000001921587333.png)
**设备发送的请求消息**
根据[PCP消息结构的定义]可以得出，设备向物联网平台发送的上报软件包下载结果消息，各个消息字段的填写如下：
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致，为16。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段的数据类型得出数据区长度为1个字节，转换为十六进制为：0001。
- 数据区：上报软件包的下载结果，比如下载成功，设备侧上报00。
  
  | **字段** | **数据类型** | **描述及要求**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  |:---|:---|:---|
  | 下载状态   | BYTE     | 0X00下载成功。 0X05剩余空间不足。 0X06下载超时。 0X07升级包校验失败。 0X08升级包类型不支持。 |
     
  
设备向物联网平台发送升级包下载结果的消息为：FFFE 01 16 0000 0001 00（CRC16校验前），经CRC16计算得到校验码为：850E。则替换校验码后设备发送的升级包下载结果的消息为：FFFE0116850E000100。
**物联网平台的应答消息**
物联网平台收到设备上报的软件包下载结果后，将会向设备返回应答消息，各个消息字段的填写如下。
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致：16。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段定义得出该数据长度为1个字节，转换为十六进制为：0001。
- 数据区：处理成功，则返回00，处理失败返回80。本示例以返回00处理成功为例进行说明。
  
  | **字段** | **数据类型** | **描述及要求**                                                                                                                                                    |
  |:---|:---|:---|
  | 结果码    | BYTE     | 0X00处理成功。 0X80升级任务不存在。 |
     
  
物联网平台向设备应答的消息为：FFFE 01 16 0000 0001 00 （CRC16校验前），经CRC16计算得到校验码为：850E。则替换校验码后物联网平台向设备应答的消息为：FFFE0116850E000100。
#### 执行软件升级
根据PCP协议约定的交互流程，物联网平台收到设备发送的软件包下载结果通知后，需要通知设备进行升级操作。
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000001875668224.png)
**物联网平台发送的请求消息**
根据[PCP消息结构的定义]可以得出，物联网平台向设备发送执行软件升级消息，各个消息字段的填写如下：
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致，为17。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段的数据类型得出无数据区，即为0字节，转换为十六进制为：0000。
- 数据区：无数据区，无需携带该字段。
  
  | **字段** | **数据类型** | **描述及要求** |
  |:---|:---|:---|
  | 无数据区                        |||
     
  
物联网平台向设备下发的执行软件升级的消息为：FFFE 01 17 0000 0000（CRC16校验前），经CRC16计算得到校验码为：CF90。则替换校验码后物联网平台向设备发送的消息为：FFFE0117CF900000。
**设备发送的应答消息**
设备收到物联网平台下发的执行升级消息后，将对收到消息后的执行动作进行应答，各消息字段的填写如下。
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致：17。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段定义得出该数据长度为1个字节，转换为十六进制为：0001。
- 数据区：处理成功，则返回00，其它处理结果请参考数据区定义。本示例以返回00处理成功为例进行说明。
  
  | **字段** | **数据类型** | **描述及要求**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
  |:---|:---|:---|
  | 结果码    | BYTE     | 0X00处理成功。 0X01设备使用中。 0X04电量不足。 0X05剩余空间不足。 0X09内存不足。 |
     
  
设备向物联网平台应答的消息为：FFFE 01 17 0000 0001 00 （CRC16校验前），经CRC16计算得到校验码为：B725。则替换校验码后设备返回的响应消息为：FFFE0117B725000100 。
#### 上报升级结果
根据PCP协议约定的交互流程，设备在执行完软件升级后，将会向物联网平台上报升级的结果。
![](https://support.huaweicloud.com/devg-iothub/figure/zh-cn_image_0000001921427689.png)
**设备发送的请求消息**
根据[PCP消息结构的定义]可以得出，设备向物联网平台上报升级结果，各个消息字段的填写如下：
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致，为18。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段的数据类型得出数据区长度为17字节，转换为十六进制为：0011。
- 数据区：结果码，以上报升级成功为例，结果码为00。当前版本号：升级完成后的版本号，与物联网平台下发的软件版本一致，即v1.0，转换为十六进制为：56312E30000000000000000000000000。
  
  | **字段** | **数据类型**   | **描述及要求**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
  |:---|:---|:---|
  | 结果码    | BYTE       | 0X00升级成功。 0X01设备使用中。 0X04电量不足。 0X05剩余空间不足。 0X09内存不足。 0X0A安装升级包失败。 0X7F内部异常。 |
  | 当前版本号  | BYTE\[16\] | 设备当前版本号。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
     
  
设备向物联网平台上报升级结果的消息为：FFFE 01 18 0000 0011 0056312E30000000000000000000000000（CRC16校验前），经CRC16计算得到校验码为：C7D2。则替换校验码后设备向物联网平台上报升级结果码流为：FFFE0118C7D200110056312E30000000000000000000000000。
**物联网平台发送的应答消息**
物联网平台收到设备上报的升级结果消息后，将对设备进行应答，各个消息字段的填写如下。
- 起始标识固定为：FFFE。
- 版本号固定为：01。
- 消息码：与请求的消息码一致：18。
- 校验码：CRC16计算前先用0000替代。
- 数据区长度：根据数据区的字段定义得出该数据长度为1个字节，转换为十六进制为：0001。
- 数据区：处理成功，则返回00，升级任务不存在80。本示例以返回00处理成功为例进行说明。
  
  | **字段** | **数据类型** | **描述及要求**                                                                                                                                                      |
  |:---|:---|:---|
  | 结果码    | BYTE     | 0X00处理成功。 0X80升级任务不存在。 |
     
  
物联网平台向设备的应答消息为：FFFE 01 18 0000 0001 00 （CRC16校验前），经CRC16计算得到校验码为：AFA1。则替换校验码后物联网平台返回的应答消息为：FFFE0118AFA1000100 。
 #### CRC16算法代码样例
基于JAVA的CRC16算法样例：
```
public class CRC16 {
    /*
     * CCITT标准CRC16(1021)余数表 CRC16-CCITT ISO HDLC, ITU X.25, x16+x12+x5+1 多项式
     * 高位在先时生成多项式 Gm=0x11021 低位在先时生成多项式，Gm=0x8408 本例采用高位在先
     */
    private static int[] crc16_ccitt_table = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
            0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252,
            0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
            0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509,
            0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
            0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7,
            0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
            0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e,
            0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
            0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4,
            0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
            0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3,
            0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
            0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589,
            0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
            0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0,
            0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
            0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e,
            0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
            0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45,
            0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
            0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 };
    /**
     *
     * @param reg_init
     *            CRC校验时初值
     * @param message
     *            校验值
     * @return
     */
    private static int do_crc(int reg_init, byte[] message) {
        int crc_reg = reg_init;
        for (int i = 0; i < message.length; i++) {
            crc_reg = (crc_reg >> 8) ^ crc16_ccitt_table[(crc_reg ^ message[i]) & 0xff];
        }
        return crc_reg;
    }
    /**
     * 根据数据生成CRC校验码
     *
     * @param message
     *            byte数据
     *
     * @return int 返校验码
     */
    public static int do_crc(byte[] message) {
        // 计算CRC校验时初值从0x0000开始。
        int crc_reg = 0x0000;
        return do_crc(crc_reg, message);
    }
}
```
基于C的CRC16算法样例：
```
/**
* CCITT标准CRC16(1021)余数表 CRC16-CCITT ISO HDLC, ITU X.25, x16+x12+x5+1 多项式
* 高位在先时生成多项式 Gm=0x11021 低位在先时生成多项式，Gm=0x8408 本例采用高位在先
*/
const unsigned short crc16_table[256] = {
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
int do_crc(int reg_init, byte* data, int length)
{
    int cnt;
    int crc_reg = reg_init;
    for (cnt = 0; cnt < length; cnt++)
    {
        crc_reg = (crc_reg >> 8) ^ crc16_table[(crc_reg ^ *(data++)) & 0xFF];
    }
    return crc_reg;
}
int main(int argc, char **argv) 
{
    //FFFE011300000000用byte数组表示：
    byte message[8] = {0xFF,0xFE,0x01,0x13,0x00,0x00,0x00,0x00};
    // 计算CRC校验时初值从0x0000开始
    int a = do_crc(0x0000, message, 8);
    printf("a ==> %x\n", a);
}
```
#### 相关FAQ
[OTA升级相关问题](https://support.huaweicloud.com/iothub_faq/iot_faq_01001.html)
#### 相关最佳实践
[MQTT协议设备OTA固件升级](https://support.huaweicloud.com/bestpractice-iothub/iot_bp_0039.html)
