# 智慧路灯设备SDK与平台通信（C）
#### 概述
本章节基于C代码演示设备通过MQTTS/MQTT协议接入华为云物联网平台，通过[设备侧MQTT/MQTTS接口](https://support.huaweicloud.com/api-iothub/iot_06_v5_3002.html)实现南向"数据上报"、"命令下发"的功能，通过应用侧的示例代码接收北向服务端订阅的消息示例。以智慧路灯为例，设备将光照强度等信息上报到IoT平台，应用服务器再接收从平台推送来的设备数据。
#### 前提条件
Linux操作系统，且已安装好GCC（建议4.8及以上版本）。
#### 上传产品模型
产品模型是用来描述设备能力的文件，通过JSON的格式定义了设备的基本属性、上报数据和下发命令的消息格式。定义产品模型，即在物联网平台构建一款设备的抽象模型，使平台理解该款设备的功能。
1. 访问[设备接入服务](https://www.huaweicloud.com/product/iothub.html)，单击"管理控制台"进入设备接入控制台。选择您的实例，单击实例卡片进入。
2. 选择左侧导航栏的"产品"，单击左侧"创建产品"。 
   图1产品-创建产品   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000002358714305.png "点击放大")
   
   
3. 在弹出的窗口中，内容根据实际情况自定义填写。 
   图2创建产品-MQTT   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001981306829.png "点击放大")
   
   
4. 下载[模型文件](https://obs-pipeline.obs.cn-north-4.myhuaweicloud.com/sdkDeploy/SmartStreetLight_2b118c0c-2aab-4e2f-9f83-589e067875a5_271f5bbb-827e-4a22-aabf-fa74f5ed3f23.zip)，该模型文件已开发完毕（由[开发产品模型](https://support.huaweicloud.com/qs-iothub/iot_05_00121.html#ZH-CN_TOPIC_0000002029733341__section5351105211251)开发完毕的产品模型导出）。详细开发过程指导请参考[在线开发产品模型](https://support.huaweicloud.com/devg-iothub/iot_02_0005.html)。
5. 创建成功后，单击刚创建的产品，然后单击上传模型文件（无需解压，并且压缩包的名称不能有括号），上传刚下载的模型文件。 
   图3上传产品模型-MQTT   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001981471833.png "点击放大")
   
   
 
#### 创建设备
1. 选择设备接入服务左侧导航栏的"设备 \> 所有设备"，单击"注册设备"。 
   图4所有设备-注册设备   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001981487325.png "点击放大")
   
   
2. 在弹出的窗口中，可以参考图中的内容填写（产品需要选择刚刚创建的产品，密钥不填写，则由平台自动生成，这里是由平台自动生成）然后单击"确定"。 
   图5单设备注册-test   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001981487357.png "点击放大")
   
   
3. 设备创建成功后，需要保存设备ID和密钥（后续设备连接的时候需要用到）。 
   图6设备-注册设备成功   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001981487333.png "点击放大")
   
   
 
#### 导入代码样例
1. 下载[quickStart(C)](https://obs-pipeline.obs.cn-north-4.myhuaweicloud.com/sdkDeploy/quickStart/quickStartC.zip)样例。
2. 将代码复制到Linux运行环境中。代码文件层级如下图。
   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001085817091.png "点击放大")
   
   **代码目录简述：**
   - **src** **：** **源码目录**
     mqtt_c_demo：demo核心源码；
     util/string_util.c：工具资源文件；
     
   
   - **conf：** **证书目录**
     rootcert.pem：设备校验平台身份的证书，用于设备侧接入物联网平台登录鉴权使用；
     
   
   - **include: 头文件目录**
     base目录：存放依赖的paho头文件
     openssl目录：存放依赖的openssl头文件
     util目录：存放依赖的工具资源头文件
     
   
   - **lib：依赖库文件**
     libcrypto.so\*/libssl.so\*: openssl库文件
     libpaho-mqtt3as.so\*: paho库文件
     
   
   - **Makefile** **：Makefile文件**
   
   
   
   
 
#### 编译库文件
- 编译openssl库。
  1. 下载openssl，上传到linux编译机任意目录下，并使用如下命令解压：
     ```
     tar -zxvf openssl-1.1.1d.tar.gz
     ```
     
  
  2. 配置生成makefile文件。
     1. 执行以下命令进入openssl源码目录。
        ```
        cd openssl-1.1.1d
        ```
        
     
     2. 创建openssl编译后的目录（本文以/home/test为例）。
        ```
        mkdir /home/test
        ```
        
     
     3. 创建openssl编译后的目录。
        ```
        mkdir /home/test/openssl
        ```
        
     
     4. 创建配置文件目录。
        ```
        mkdir /home/test/openssl/ssl
        ```
        
     
     5. 运行如下配置命令。
        ```
        ./config shared --prefix=/home/test/openssl --openssldir=/home/test/openssl/ssl
        ```
        其中"prefix"是安装目录，"openssldir"是配置文件目录，"shared"作用是生成动态链接库（即.so库） 。
        如果编译有问题，配置命令加上no-asm（表示不使用汇编代码）。
        ./config no-asm shared --prefix=/home/test/openssl --openssldir=/home/test/openssl/ssl
        ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001085910799.png "点击放大")
        
      
  
  3. 编译出库。
     1. 在openssl源码目录下，运行make depend命令。
        ```
        make depend
        ```
        
     
     2. 再运行make命令进行编译。
        ```
        make
        ```
        
     
     3. 安装openssl。
        ```
        make install
        ```
        在配置的openssl安装目录下home/test/openssl找到lib目录，有生成的库文件：
        "libcrypto.so.1.1"、"libssl.so.1.1"和软链接"libcrypto.so"、"libssl.so"，请将这些文件复制到quickStart(C)的lib文件夹下（同时将/home/test/openssl/include/openssl里的内容复制到quickStart(C)的include/openssl下）。
        ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000002572182130.png)
        **注**：有的编译工具是32位的，如果在64位的linux机器上使用，这时只要将Makefile中的-m64都删除，再进行编译即可。
        
      
   
- 编译paho库文件。
  1. 下载[paho.mqtt.c源码](https://github.com/eclipse/paho.mqtt.c/archive/v1.3.2.tar.gz)。
  
  2. 解压后上传到Linux编译机。
  
  3. 修改makefile。
     1. 通过如下命令进行编辑Makefile。
        ```
        vim Makefile
        ```
        
     
     2. 显示行数。
        ```
        :set nu
        ```
        
     
     3. 在129行之后添加下面两行（自定义的openssl的头文件和库文件）。
        ```
        CFLAGS += -I/home/test/openssl/include
        LDFLAGS += -L/home/test/openssl/lib -lrt
        ```
        ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001085517205.png "点击放大")
        
     
     4. 把195行、197行、199行、201行都改成对应的地址。 ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001085517207.png "点击放大")
        
      
  
  4. 编译。
     1. 执行清空命令。
        ```
        make clean
        ```
        
     
     2. 执行编译命令。
        ```
        make
        ```
        
      
  
  5. 编译完成后，可以在build/output目录下看到编译成功的库。 ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000002620765697.png)
     
  
  6. 复制paho库文件。 当前SDK仅用到了libpaho-mqtt3as，请将"libpaho-mqtt3as.so"和"libpaho-mqtt3as.so.1"文件复制到quickStart(C)的lib文件夹下。（同时回到paho源代码路径，进入src目录，将MQTTAsync.h、MQTTClient.h、MQTTClientPersistence.h、MQTTProperties.h、MQTTReasonCodes.h、MQTTSubscribeOpts.h复制到quickStart(C)的include/base文件夹下）。
     
   
 
#### 建立连接
设备或网关在接入物联网平台时首先需要和平台建立连接，从而将设备或网关与平台进行关联。开发者通过传入设备信息，将设备或网关连接到物联网平台。
1. 设置参数，只需修改username和password。 
   ```
   char *uri = "ssl://iot-mqtts.cn-north-4.myhuaweicloud.com:8883";
   int port = 8883;
   char *username = "yourDeviceId"; //设备ID，在平台注册设备成功后返回
   char *password = "yourSecret";  //密钥，在平台注册设备成功后返回
   ```
   注意：MQTTS为8883端口接入，如果使用MQTT协议接入，url为：tcp://iot-mqtts.cn-north-4.myhuaweicloud.com:1883， port为1883。
   
   
2. 连接。 
   1. 执行make进行编译。如果是32位的操作系统，请删除Makefile中的"-m64"。
   
   2. 执行export LD_LIBRARY_PATH=./lib/加载库文件。
   
   3. 运行./MQTT_Demo.o。
   
   
   
   
3. 连接成功后，打印"connect success"，同时在控制台可看到设备已在线。 
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001085910803.png "点击放大")
   图7设备列表-设备在线   
   ![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001950367902.png "点击放大")
   
   
   
#### 属性上报
属性上报是指设备主动向平台上报自己的属性（该示例代码已实现自动定时上报功能，可参考下一节在iot平台查看设备上报的数据内容），更多信息请参考[MQTT协议属性上报](https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html)。
```
//publish data
char *payload = "{\"services\":[{\"service_id\":\"BasicData\",\"properties\":{\"luminance\":32},\"event_time\":NULL}]}";
```
- 消息体payload组装格式为JSON，其中service_id要与产品模型中的定义对应，properties是设备的属性；
- luminance表示光照强度；
- event_time为可选项，为设备采集数据UTC时间，不填写默认使用系统时间。
设备上报属性成功后，demo控制台中会打印"publish success"字样。
同时在设备详情页面查看到上报的属性。
图8查看上报数据-luminance   
![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001950370350.png "点击放大")
#### 接收下发命令
订阅了命令Topic后，可以在控制台下发同步命令。详情请参考[MQTT设备同步命令下发](https://support.huaweicloud.com/usermanual-iothub/iot_01_0339.html#section4)。
命令下发后，demo中接收到命令：
![](https://support.huaweicloud.com/qs-iothub/figure/zh-cn_image_0000001117633601.png "点击放大")
#### 通过云端获取设备上报的数据
当数据到达平台后，应用服务器可以使用AMQP来接收推送消息。具体可参考[通过云端获取设备上报的数据](https://support.huaweicloud.com/qs-iothub/iot_05_00122.html#ZH-CN_TOPIC_0000001085782661__zh-cn_topic_0267714242_section2262187122718)。
#### 更多
更详细开发指导请参考[设备侧SDK](https://support.huaweicloud.com/sdkreference-iothub/iot_02_0178.html)接入或更多其他语言的[demo接入](https://support.huaweicloud.com/devg-iothub/iot_02_2200.html)。
