merge new qcloud sdk

1. qcloud has a great revolution, the protocol has been changed to implement data template, so the old TencentCloud_SDK developed by us will not work fine now(mqtt still works, but data template will not works fine for recently created product/devices).

2. I merge the official qlcoud sdk(include both the iot-hub and iot-explorer sdk) into the componet/conectivity to support new protocol of data template

3. iot-hub sdk, supply the fundamental iot protocol(like mqtt coap, etc.)
iot-explorer sdk, supply the high level service like data template based on mqtt

4. To know how it works, see qcloud_iot_explorer_sdk_data_template、qcloud_iot_hub_sdk_mqtt example(keil project in board\TencentOS_tiny_EVB_MX_Plus\KEIL\qcloud_iot_explorer_sdk_data_template and  board\TencentOS_tiny_EVB_MX_Plus\KEIL\qcloud_iot_hub_sdk_mqtt)
This commit is contained in:
daishengdong
2019-11-14 15:09:00 +08:00
parent 5d86548c23
commit 943db74fc7
705 changed files with 297267 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
# C-SDK API函数及可变参数说明
设备端 C-SDK 供用户调用的API函数声明常量以及可变参数定义等头文件位于include目录下面本文档主要对该目录下面的可变参数以及API函数进行说明。
## 可变参数配置
C-SDK 的使用可以根据具体场景需求,配置相应的参数,满足实际业务的运行。可变接入参数包括:
1. MQTT 阻塞调用(包括连接, 订阅, 发布等)的超时时间, 单位: 毫秒。 建议 5000 毫秒
2. MQTT 协议发送消息和接受消息的 buffer 大小默认是 2048 字节目前云端一条MQTT消息最大长度为 16 KB
3. COAP 协议发送消息和接受消息的 buffer 大小默认是 512 字节目前云端一条COAP消息最大长度为 1 KB
4. MQTT 心跳消息发送周期, 最大值为690秒单位: 毫秒
5. 重连最大等待时间,单位:毫秒。设备断线重连时,若失败则等待时间会翻倍,当超过该最大等待时间则退出重连
修改 include/qcloud_iot_export_variables.h 文件如下宏定义可以改变对应接入参数的配置。
修改完需要重新编译 SDK
```
/* default MQTT/CoAP timeout value when connect/pub/sub (unit: ms) */
#define QCLOUD_IOT_MQTT_COMMAND_TIMEOUT (5 * 1000)
/* default MQTT keep alive interval (unit: ms) */
#define QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL (240 * 1000)
/* default MQTT Tx buffer size, MAX: 16*1024 */
#define QCLOUD_IOT_MQTT_TX_BUF_LEN (2048)
/* default MQTT Rx buffer size, MAX: 16*1024 */
#define QCLOUD_IOT_MQTT_RX_BUF_LEN (2048)
/* default COAP Tx buffer size, MAX: 1*1024 */
#define COAP_SENDMSG_MAX_BUFLEN (512)
/* default COAP Rx buffer size, MAX: 1*1024 */
#define COAP_RECVMSG_MAX_BUFLEN (512)
/* MAX MQTT reconnect interval (unit: ms) */
#define MAX_RECONNECT_WAIT_INTERVAL (60 * 1000)
```
## API 函数说明
以下是 C-SDK v3.1.0版本提供的主要功能和对应 API 接口说明用于客户编写业务逻辑更加详细的说明如接口参数及返回值可查看SDK代码 include/exports/qcloud_iot_export_*.h 等头文件中的注释
### 1. MQTT 接口
| 序号 | 函数名 | 说明 |
| ---- | -------------------- | ----------------------------------------------- |
| 1 | IOT_MQTT_Construct | 构造 MQTTClient 并连接 MQTT 云端服务 |
| 2 | IOT_MQTT_Destroy | 关闭 MQTT 连接并销毁 MQTTClient |
| 3 | IOT_MQTT_Yield | 在当前线程上下文中,进行 MQTT 报文读取,消息处理,超时请求,心跳包及重连状态管理等任务 |
| 4 | IOT_MQTT_Publish | 发布 MQTT 消息 |
| 5 | IOT_MQTT_Subscribe | 订阅 MQTT 主题 |
| 6 | IOT_MQTT_Unsubscribe | 取消订阅已订阅的 MQTT 主题 |
| 7 | IOT_MQTT_IsConnected | 查看当前 MQTT 是否已连接 |
| 8 | IOT_MQTT_GetErrCode | 获取IOT_MQTT_Construct失败的错误码 |
- 多线程环境使用说明
SDK对于MQTT接口在多线程环境下的使用有如下注意事项
```
1. 不允许多线程调用IOT_MQTT_YieldIOT_MQTT_Construct以及IOT_MQTT_Destroy
2. 可以多线程调用IOT_MQTT_PublishIOT_MQTT_Subscribe及IOT_MQTT_Unsubscribe
3. IOT_MQTT_Yield 作为从socket读取并处理MQTT报文的函数应保证一定的执行时间避免被长时间挂起或抢占
```
### 2. 设备影子接口
关于设备影子功能介绍,可以参考[设备影子详情](https://cloud.tencent.com/document/product/634/11918)
| 序号 | 函数名 | 说明 |
| ---- | -------------------------------------------------- | ---------------------------------------------- |
| 1 | IOT_Shadow_Construct | 构造设备影子客户端 ShadowClient并连接 MQTT 云端服务 |
| 2 | IOT_Shadow_Publish | 影子客户端发布 MQTT 消息 |
| 3 | IOT_Shadow_Subscribe | 影子客户端订阅 MQTT 主题 |
| 4 | IOT_Shadow_Unsubscribe | 影子客户端取消订阅已订阅的 MQTT 主题 |
| 5 | IOT_Shadow_IsConnected | 查看当前影子客户端的 MQTT 是否已连接 |
| 6 | IOT_Shadow_Destroy | 关闭 Shadow MQTT 连接并销毁 ShadowClient |
| 7 | IOT_Shadow_Yield | 在当前线程上下文中,进行 MQTT 报文读取,消息处理,超时请求,心跳包及重连状态管理等任务 |
| 8 | IOT_Shadow_Update | 异步更新设备影子文档 |
| 9 | IOT_Shadow_Update_Sync | 同步方式更新设备影子文档 |
| 10 | IOT_Shadow_Get | 异步方式获取设备影子文档 |
| 11 | IOT_Shadow_Get_Sync | 同步方式获取设备影子文档 |
| 12 | IOT_Shadow_Register_Property | 注册当前设备的设备属性 |
| 13 | IOT_Shadow_UnRegister_Property | 删除已经注册过的设备属性 |
| 14 | IOT_Shadow_JSON_ConstructReport | 在JSON文档中添加reported字段不覆盖更新 |
| 15 | IOT_Shadow_JSON_Construct_OverwriteReport | 在JSON文档中添加reported字段覆盖更新 |
| 16 | IOT_Shadow_JSON_ConstructReportAndDesireAllNull | 在JSON文档中添加reported字段同时清空desired字段 |
| 17 | IOT_Shadow_JSON_ConstructDesireAllNull | 在JSON文档中添加 "desired": null 字段 |
### 3. CoAP 接口
| 序号 | 函数名 | 说明 |
| ---- | ---------------------------- | ------------------------------------------------- |
| 1 | IOT_COAP_Construct | 构造 CoAPClient 并完成 CoAP 连接 |
| 2 | IOT_COAP_Destroy | 关闭 CoAP 连接并销毁 CoAPClient |
| 3 | IOT_COAP_Yield | 在当前线程上下文中,进行 CoAP 报文读取和消息处理等任务 |
| 4 | IOT_COAP_SendMessage | 发布 CoAP 消息 |
| 5 | IOT_COAP_GetMessageId | 获取 COAP Response 消息 msgId |
| 6 | IOT_COAP_GetMessagePayload | 获取 COAP Response 消息内容 |
| 7 | IOT_COAP_GetMessageCode | 获取 COAP Response 消息错误码 |
### 4. OTA 接口
关于 OTA 固件下载功能介绍,可以参考[设备固件升级](https://cloud.tencent.com/document/product/634/14674)
| 序号 | 函数名 | 说明 |
| ---- | ---------------------------- | ------------------------------------------------- |
| 1 | IOT_OTA_Init | 初始化 OTA 模块,客户端在调用此接口之前需要先进行 MQTT/COAP 的初始化 |
| 2 | IOT_OTA_Destroy | 释放 OTA 模块相关的资源 |
| 3 | IOT_OTA_ReportVersion | 向 OTA 服务器报告本地固件版本信息 |
| 4 | IOT_OTA_IsFetching | 检查是否处于下载固件的状态 |
| 5 | IOT_OTA_IsFetchFinish | 检查固件是否已经下载完成 |
| 6 | IOT_OTA_FetchYield | 从具有特定超时值的远程服务器获取固件 |
| 7 | IOT_OTA_Ioctl | 获取指定的 OTA 信息 |
| 8 | IOT_OTA_GetLastError | 获取最后一个错误代码 |
| 9 | IOT_OTA_StartDownload | 根据获取到的固件更新地址以及本地固件信息偏移是否断点续传与固件服务器建立http连接 |
| 10 | IOT_OTA_UpdateClientMd5 | 断点续传前计算本地固件的MD5 |
| 11 | IOT_OTA_ReportUpgradeBegin | 当进行固件升级前,向服务器上报即将升级的状态 |
| 12 | IOT_OTA_ReportUpgradeSuccess | 当固件升级成功之后,向服务器上报升级成功的状态 |
| 13 | IOT_OTA_ReportUpgradeFail | 当固件升级失败之后,向服务器上报升级失败的状态 |
### 5. 日志接口
设备日志上报云端功能的详细说明可以参考SDK docs目录下物联网通信平台文档设备日志上报功能部分
| 序号 | 函数名 | 说明 |
| ---- | -------------------------- | --------------------------------------------- |
| 1 | IOT_Log_Set_Level | 设置 SDK 日志的打印等级 |
| 2 | IOT_Log_Get_Level | 返回 SDK 日志打印的等级 |
| 3 | IOT_Log_Set_MessageHandler | 设置日志回调函数,重定向 SDK 日志于其它输出方式 |
| 4 | IOT_Log_Init_Uploader | 开启 SDK 日志上报云端的功能并初始化资源 |
| 5 | IOT_Log_Fini_Uploader | 停止 SDK 日志上报云端功能并释放资源 |
| 6 | IOT_Log_Upload | 将 SDK 运行日志上报到云端 |
| 7 | IOT_Log_Set_Upload_Level | 设置 SDK 日志的上报等级 |
| 8 | IOT_Log_Get_Upload_Level | 返回 SDK 日志上报的等级 |
| 9 | Log_d/i/w/e | 按级别打印添加 SDK 日志的接口 |
### 6. 系统时间接口
| 序号 | 函数名 | 说明 |
| ---- | ---------------------------- | ------------------------------------------------- |
| 1 | IOT_Get_SysTime | 获取 IoT hub 后台系统时间,目前仅支持 MQTT 通道对时功能 |
### 7. 网关功能接口
关于网关功能介绍可以参考SDK docs目录下物联网通信平台文档网关产品部分
| 序号 | 函数名 | 说明 |
| ---- | ---------------------------- | ------------------------------------------------- |
| 1 | IOT_Gateway_Construct | 构造 Gateway client 并完成 MQTT 连接 |
| 2 | IOT_Gateway_Destroy | 关闭 MQTT 连接并销毁 Gateway client |
| 3 | IOT_Gateway_Subdev_Online | 子设备上线 |
| 4 | IOT_Gateway_Subdev_Offline | 子设备下线 |
| 3 | IOT_Gateway_Yield | 在当前线程上下文中,进行 MQTT 报文读取,消息处理,超时请求,心跳包及重连状态管理等任务 |
| 4 | IOT_Gateway_Publish | 发布 MQTT 消息 |
| 5 | IOT_Gateway_Subscribe | 订阅 MQTT 主题 |
| 6 | IOT_Gateway_Unsubscribe | 取消订阅已订阅的 MQTT 主题 |

View File

@@ -0,0 +1,189 @@
# C-SDK 编译方式及配置选项说明
本文档对C-SDK 的编译方式和编译配置选项进行说明,并介绍了 Linux和Windows 开发环境下面的编译环境搭建以及编译示例。
## C-SDK 编译方式说明
C-SDK 支持三种编译方式
#### 1. cmake 方式
推荐使用cmake作为跨平台的编译工具支持在Linux和Windows开发环境下进行编译。
cmake方式采用CMakeLists.txt作为编译配置选项输入文件
#### 2. Makefile 方式
对不支持cmake的环境使用Makefile直接编译的方式该方式与SDK v3.0.3及之前的版本保持一致采用make.settings作为编译配置选项输入文件修改完成后执行make即可
#### 3. 代码抽取方式
该方式可根据需求选择功能,将相关代码抽取到一个单独的文件夹,文件夹里面的代码层次目录简洁,方便用户拷贝集成到自己的开发环境。
该方式需要依赖cmake工具在CMakeLists.txt中配置相关功能模块的开关并将EXTRACT_SRC置为ONLinux环境运行以下命令
```
mkdir build
cd build
cmake ..
```
即可在output/qcloud_iot_c_sdk中找到相关代码文件目录层次如下
```
qcloud_iot_c_sdk
├── include
│   ├── config.h
│   ├── exports
├── platform
└── sdk_src
└── internal_inc
```
include目录为SDK供用户使用的API及可变参数其中config.h为根据编译选项生成的编译宏。API具体介绍请参考**C-SDK_API及可变参数说明**。
platform目录为平台相关的代码可根据设备的具体情况进行修改适配。具体的函数说明请参考文档**C-SDK_Porting跨平台移植概述**
sdk_src为SDK的核心逻辑及协议相关代码一般不需要修改其中internal_inc为SDK内部使用的头文件。
用户可将qcloud_iot_c_sdk拷贝到其目标平台的编译开发环境并根据具体情况修改编译选项。
## C-SDK 编译选项说明
#### 1. 编译配置选项
以下配置选项大部分都适用于cmake和make.setting。cmake中的ON值对应于make.setting的yOFF对应于n。
| 名称 | cmake值 | 说明 |
| :------------------------------- | ------------- | ------------------------------------------------------------ |
| BUILD_TYPE | release/debug | release不启用IOT_DEBUG信息编译输出到release目录下<br />debug启用IOT_DEBUG信息编译输出到debug目录下 |
| EXTRACT_SRC | ON/OFF | 代码抽取功能开关仅对使用cmake有效 |
| COMPILE_TOOLS | gcc | 支持gcc和msvc也可以是交叉编译器比如arm-none-linux-gnueabi-gcc |
| PLATFORM | linux | 包括linux/windows/freertos/nonos |
| FEATURE_MQTT_COMM_ENABLED | ON/OFF | MQTT通道总开关 |
| FEATURE_MQTT_DEVICE_SHADOW | ON/OFF | 设备影子总开关 |
| FEATURE_COAP_COMM_ENABLED | ON/OFF | CoAP通道总开关 |
| FEATURE_GATEWAY_ENABLED | ON/OFF | 网关功能总开关 |
| FEATURE_OTA_COMM_ENABLED | ON/OFF | OTA固件升级总开关 |
| FEATURE_OTA_SIGNAL_CHANNEL | MQTT/COAP | OTA信令通道类型 |
| FEATURE_AUTH_MODE | KEY/CERT | 接入认证方式 |
| FEATURE_AUTH_WITH_NOTLS | ON/OFF | OFF: TLS使能, ON: TLS关闭 |
| FEATURE_DEV_DYN_REG_ENABLED | ON/OFF | 设备动态注册开关 |
| FEATURE_LOG_UPLOAD_ENABLED | ON/OFF | 日志上报开关 |
| FEATURE_EVENT_POST_ENABLED | ON/OFF | 事件上报开关 |
| FEATURE_DEBUG_DEV_INFO_USED | ON/OFF | 设备信息获取来源开关 |
| FEATURE_SYSTEM_COMM_ENABLED | ON/OFF | 获取后台时间开关 |
| FEATURE_AT_TCP_ENABLED | ON/OFF | AT模组TCP功能开关 |
| FEATURE_AT_UART_RECV_IRQ | ON/OFF | AT模组中断接受功能开关 |
| FEATURE_AT_OS_USED | ON/OFF | AT模组多线程功能开关 |
| FEATURE_AT_DEBUG | ON/OFF | AT模组调试功能开关 |
| FEATURE_MULTITHREAD_TEST_ENABLED | ON/OFF | 是否编译Linux多线程测试例程 |
配置选项之间存在依赖关系,当依赖选项的值为有效值时,部分配置选项才有效,主要如下:
| 名称 | 依赖选项 | 有效值 |
| :------------------------------- | ------------------------------------------------------- | ------------ |
| FEATURE_MQTT_DEVICE_SHADOW | FEATURE_MQTT_COMM_ENABLED | ON |
| FEATURE_GATEWAY_ENABLED | FEATURE_MQTT_COMM_ENABLED | ON |
| FEATURE_OTA_SIGNAL_CHANNEL(MQTT) | FEATURE_OTA_COMM_ENABLED<br />FEATURE_MQTT_COMM_ENABLED | ON<br />ON |
| FEATURE_OTA_SIGNAL_CHANNEL(COAP) | FEATURE_OTA_COMM_ENABLED<br />FEATURE_COAP_COMM_ENABLED | ON<br />ON |
| FEATURE_AUTH_WITH_NOTLS | FEATURE_AUTH_MODE | KEY |
| FEATURE_AT_UART_RECV_IRQ | FEATURE_AT_TCP_ENABLED | ON |
| FEATURE_AT_OS_USED | FEATURE_AT_TCP_ENABLED | ON |
| FEATURE_AT_DEBUG | FEATURE_AT_TCP_ENABLED | ON |
#### 2. 设备信息选项
在腾讯云物联控制台创建设备之后需要将设备信息ProductID/DeviceName/DeviceSecret/Cert/Key文件配置在SDK中才能正确运行。在开发阶段SDK 提供两种方式存储设备信息:
1. 存放在代码中编译选项DEBUG_DEV_INFO_USED = ON则在`platform/os/xxx/HAL_Device_xxx.c`中修改设备信息,在无文件系统的平台下可以使用这种方式。
2. 存放在配置文件中编译选项DEBUG_DEV_INFO_USED = OFF则在`device_info.json`文件修改设备信息此方式下更改设备信息不需重新编译SDK在Linux/Windows平台下开发推荐使用这种方式。
## C-SDK 编译环境
### Linux(Ubuntu)环境
本文使用Ubuntu的版本为14.04或16.04
1. 必要软件安装
```
$ sudo apt-get install -y build-essential make git gcc cmake
```
SDK需要cmake版本在3.5以上默认安装的cmake版本较低可以参考如下链接进行cmake特定版本的下载与安装
下载链接https://cmake.org/download/
安装参考https://gitlab.kitware.com/cmake/cmake
2. 配置修改
修改CMakeLists.txt确保以下选项存在(以密钥认证设备为例)
```
set(BUILD_TYPE "release")
set(COMPILE_TOOLS "gcc")
set(PLATFORM "linux")
set(FEATURE_MQTT_COMM_ENABLED ON)
set(FEATURE_AUTH_MODE "KEY")
set(FEATURE_AUTH_WITH_NOTLS OFF)
set(FEATURE_DEBUG_DEV_INFO_USED OFF)
```
3. 执行脚本编译
完整编译库和示例
```
./cmake_build.sh
```
输出的库文件,头文件及示例在`output/release`文件夹中。
在一次完整编译之后,若只需要编译示例,则执行
```
./cmake_build.sh samples
```
4. 填写设备信息
将在腾讯云物联网平台创建的设备的设备信息(以**密钥认证设备**为例)填写到device_info.json中
```
"auth_mode":"KEY",
"productId":"S3EUVBRJLB",
"deviceName":"test_device",
"key_deviceinfo":{
"deviceSecret":"vX6PQqazsGsMyf5SMfs6OA6y"
}
```
5. 运行示例
示例输出位于`output/release/bin`文件夹中比如运行data_template_sample示例输入`./output/release/bin/data_template_sample`即可。
### Windows环境
#### 获取和安装Visio Studio 2019开发环境
请访问[Visual Studio下载网站](https://visualstudio.microsoft.com/zh-hans/downloads/)下载并安装Visio Studio 2019本文档下载安装的是16.2版本 Community。
![](https://main.qcloudimg.com/raw/730f793e3166db859682cdbfd0c7181f.jpg)
然后选择**使用C++的桌面开发**,并确保勾选**用于Windows的C++ CMAKE工具**
![](https://main.qcloudimg.com/raw/89a63cb6ae5231a66b17e80acac37267.jpg)
#### 编译并运行
1. 运行visual studio选择**打开本地文件夹**并选择下载的C SDK目录。
![](https://main.qcloudimg.com/raw/f0c65e7c5ce13ca13b967c178c0449c6.jpg)
2. [修改用户信息]()
3. 双击打开根目录的CMakeLists.txt并确认编译工具链中设置的平台为**windows**和编译工具为**MSVC**(其他配置选项请参考[cmake编译配置与代码抽取]())。
![](https://main.qcloudimg.com/raw/8a16723698646a2dca5ab08a57927304.jpg)
```cmake
# 编译工具链
#set(COMPILE_TOOLS "gcc")
#set(PLATFORM "linux")
set(COMPILE_TOOLS "MSVC")
set(PLATFORM "windows")
```
4. visual studio会自动生成cmake缓存请等待cmake缓存生成完毕。
![](https://main.qcloudimg.com/raw/633bf217afc2d52e92618a90bd7d9da0.jpg)
5. 缓存生成完毕后,点击**生成->全部生成**。
![](https://main.qcloudimg.com/raw/f85d2435c49a802eedd87b751408ecce.jpg)
6. 选择相应的示例运行,示例应与用户信息相对应。
![](https://main.qcloudimg.com/raw/a0f2bacc0d31d2da9d327d5c855655a3.jpg)

View File

@@ -0,0 +1,106 @@
## C-SDK跨平台移植
本文档介绍如何将设备端 C-SDK 移植到目标硬件平台。C-SDK 采用模块化设计,分离核心协议服务与硬件抽象层,在进行跨平台移植时,一般只需要对硬件抽象层进行修改适配就可以。
## C-SDK 架构
#### 架构图
![framework](https://main.qcloudimg.com/raw/76fc3f15c4c91ea6cf7e496f25d5d572.jpg)
#### 架构说明
SDK分四层设计从上至下分别为平台服务层、核心协议层、网络层、硬件抽象层。
- 服务层
在网络协议层之上实现了包括设备接入鉴权设备影子数据模板网关动态注册日志上报和OTA等功能并提供相关API接口给用户使用关于服务层API说明请参考文档[C-SDK_API及可变参数说明]()
- 协议层
设备端和IoT平台交互的网络协议包括MQTT/COAP/HTTP
- 网络层
实现基于TLS/SSL(TLS/DTLS)方式POSIX_socket(TCP/UDP)方式和AT_socket方式的网络协议栈不同服务可根据需要使用不同的协议栈接口函数。
- 硬件抽象层
实现对不同硬件平台的底层操作的抽象封装需要针对具体的软硬件平台开展移植分为必须实现和可选实现两部分HAL层接口。
## 硬件抽象层移植
HAL层主要有几大块的移植分别是OS相关的、网络及TLS相关的、时间及打印相关的、设备信息相关的。
SDK在 **platform/os** 目录示例了Linux、Windows、FreeRTOS及nonOS四个场景的硬件抽象层实现可以参考最相近的目录展开目标平台的移植。
#### OS相关接口
| 序号 | 函数名 | 说明 |
| ---- | ---------------------- | ------------------------------------------ |
| 1 | HAL_Malloc | 动态申请内存块 |
| 2 | HAL_Free | 释放内存块 |
| 3 | HAL_ThreadCreate | 线程创建 |
| 4 | HAL_ThreadDestroy | 线程销毁 |
| 5 | HAL_MutexCreate | 创建互斥锁 |
| 6 | HAL_MutexDestroy | 销毁互斥锁 |
| 7 | HAL_MutexLock | mutex 加锁 |
| 8 | HAL_MutexUnlock | mutex 解锁 |
| 9 | HAL_SemaphoreCreate | 创建信号量 |
| 10 | HAL_SemaphoreDestroy | 销毁信号量 |
| 11 | HAL_SemaphoreWait | 等待信号量 |
| 12 | HAL_SemaphorePost | 释放信号量 |
| 13 | HAL_SleepMs | 休眠 |
#### 网络及TLS相关的HAL接口
网络相关接口提供二选一的适配移植。对于具备网络通讯能力并且本身集成TCP/IP网络协议栈的设备需要实现BSD_socket的网络HAL接口使用TLS/SSL加密通讯的还需要实现TLS相关的HAL接口。而对于[MCU+通用TCP_AT模组]()的设备则可以选择SDK提供的AT_Socket框架并实现相关的AT模组接口。
##### 基于BSD_socket的HAL接口
其中TCP/UDP相关接口基于POSIX socket函数实现。TLS相关接口依赖于 **mbedtls** 库,移植之前必须确保系统上有可用的**mbedtls**库。如果采用其他TLS/SSL库可参考**platform/tls/mbedtls**相关实现进行移植适配。
UDP/DTLS 相关的函数仅在使能 **COAP** 通讯的时候才需要移植。
| 序号 | 函数名 | 说明 |
| ---- | ---------------------- | ------------------------------------------ |
| 1 | HAL_TCP_Connect | 建立 TCP 连接 |
| 2 | HAL_TCP_Disconnect | 断开 TCP 连接 |
| 3 | HAL_TCP_Write | TCP 写 |
| 4 | HAL_TCP_Read | TCP 读 |
| 5 | HAL_TLS_Connect | 建立 TLS 连接 |
| 6 | HAL_TLS_Disconnect | 断开 TLS 连接 |
| 7 | HAL_TLS_Write | TLS 写 |
| 8 | HAL_TLS_Read | TLS 读 |
| 9 | HAL_UDP_Connect | 建立 TCP 连接 |
| 10 | HAL_UDP_Disconnect | 断开 TCP 连接 |
| 11 | HAL_UDP_Write | UDP 写 |
| 12 | HAL_UDP_Read | UPD 读 |
| 13 | HAL_DTLS_Connect | 建立 DTLS 连接 |
| 14 | HAL_DTLS_Disconnect | 断开 DTLS 连接 |
| 15 | HAL_DTLS_Write | DTLS 写 |
| 16 | HAL_DTLS_Read | DTLS 读 |
##### 基于AT_socket的HAL接口
通过使能编译宏**AT_TCP_ENABLED**选择AT_socket, 则SDK会调用 network_at_tcp.c 的at_socket接口at_socket层不需要移植需要实现AT串口驱动及AT模组驱动AT模组驱动只需要实现AT框架中at_device的驱动结构体 *at_device_op_t* 的驱动接口即可可以参照at_device目录下的已支持的模组。AT串口驱动需要实现串口的中断接收然后在中断服务程序中调用回调函数 *at_client_uart_rx_isr_cb* 即可,可以参考 HAL_AT_UART_freertos.c 实现目标平台的移植。
| 序号 | 函数名 | 说明 |
| ---- | ---------------------- | ------------------------------------------ |
| 1 | HAL_AT_Uart_Init |初始化 AT串口 |
| 2 | HAL_AT_Uart_Deinit | 去初始化 AT串口 |
| 3 | HAL_AT_Uart_Send | AT串口发送数据 |
| 4 | HAL_AT_UART_IRQHandler | AT串口接收中断服务程序 |
#### 时间及打印相关的HAL接口
| 序号 | 函数名 | 说明 |
| ---- | ---------------------- | ------------------------------------------ |
| 1 | HAL_Printf | 将格式化的数据写入标准输出流中 |
| 2 | HAL_Snprintf | 将格式化的数据写入字符串 |
| 3 | HAL_UptimeMs | 检索自系统启动以来已运行的毫秒数 |
| 4 | HAL_DelayMs | 阻塞延时,单位毫秒 |
#### 设备信息相关的HAL接口
接入IoT平台需要在平台创建产品和设备信息同时需要将产品及设备信息保存在设备侧的非易失存储介质。可以参考 platform/os/linux/HAL_Device_linux.c示例实现。
| 序号 | 函数名 | 说明 |
| ---- | ---------------------- | ------------------------------------------ |
| 1 | HAL_GetDevInfo | 设备信息读取 |
| 2 | HAL_SetDevInfo | 设备信息保存 |

View File

@@ -0,0 +1,133 @@
## 概述
腾讯云物联网平台为每个创建的产品分配唯一标识 ProductID用户可以自定义 DeviceName 标识设备,用产品标识 + 设备标识 + 设备证书/密钥来验证设备的合法性。用户在创建产品时需要选择设备认证方式,在设备接入时需要根据指定的方式上报产品、设备信息与对应的密钥信息,认证通过后才能连接物联网通信平台。由于不同用户的设备端资源、安全等级要求都不同,平台提供了多种认证方案,以满足不同的使用场景。
物联网平台提供以下三种认证方案:
- 证书认证(设备级):为每台设备分配证书 + 私钥,使用非对称加密认证接入,用户需要为每台设备烧录不同的配置信息。
- 密钥认证(设备级):为每台设备分配设备密钥,使用对称加密认证接入,用户需要为每台设备烧录不同的配置信息。
- 动态注册认证(产品级):为同一产品下的所有设备分配统一密钥,设备通过注册请求获取设备证书/密钥后认证接入用户可以为同一批设备烧录相同的配置信息。IoT Explorer平台暂不支持动态注册认证。
三种方案在易用性、安全性和对设备资源要求上各有优劣,您可以根据自己的业务场景综合评估选择。方案对比如下:
| 特性 | 证书认证 |密钥认证| 动态注册认证|
|--------|--------|--------|--------|
| 设备烧录信息 | ProductId、DeviceName、<br>设备证书、设备私钥| ProductId、DeviceName、设备密钥 |ProductId、DeviceName、ProductSecret|
| 是否需要提前创建设备 | 必须| 必须 |支持根据注册请求中携带的 DeviceName 自动创建|
| 安全性 | 高 | 一般 | 一般 |
| 使用限制 | 单产品下最多创建20万设备| 单产品下最多创建20万设备 | 单产品下最多创建20万设备用户可自定义通过注册请求自动创建的设备数上限|
| 设备资源要求 | 较高,需要支持 TLS| 较低 |较低,支持 AES 即可|
## 设备身份信息
- 证书设备要通过平台的安全认证,必须具备四元组信息:产品 IDProductId、设备名DeviceName、设备证书文件DeviceCert、设备私钥文件DevicePrivateKey其中证书文件和私钥文件由平台生成且一一对应。
- 密钥设备要通过平台的安全认证,必须具备三元组信息:产品 IDProductId、设备名DeviceName、设备密钥DeviceSecret其中设备密钥由平台生成。
## 设备身份信息烧录
- 创建产品后,在物联网开发平台 [控制台](https://console.cloud.tencent.com/iotexplorer) 或者通过 [云 API](https://cloud.tencent.com/document/product/1081/37178) 创建设备,并获取对应的设备信息,将上述的四元组或者三元组信息,在设备生产的特定环节,烧录到非易失介质中,设备 SDK 运行时读取存放的设备信息,进行设备认证。
- SDK提供了设备信息读写的HAL接口必须实现。可以参考linux平台HAL_Device_linux.c中设备信息读写的实现。
- 设备信息HAL接口
| HAL_API | 说明 |
| -----------------------------------| ---------------------------------- |
| HAL_SetDevInfo | 设备信息写入 |
| HAL_GetDevInfo | 设备信息读取 |
## 开发阶段设备信息配置
创建设备之后需要将设备信息ProductID/DeviceName/DeviceSecret/Cert/Key文件配置在SDK中才能正确运行示例。在开发阶段SDK 提供两种方式存储设备信息:
1. 存放在代码中编译选项DEBUG_DEV_INFO_USED = ON则在`platform/os/xxx/HAL_Device_xxx.c`中修改设备信息,在无文件系统的平台下可以使用这种方式。
```
/* product Id */
static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID";
/* device name */
static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEV_NAME";
#ifdef DEV_DYN_REG_ENABLED
/* product secret for device dynamic Registration */
static char sg_product_secret[MAX_SIZE_OF_PRODUCT_SECRET + 1] = "YOUR_PRODUCT_SECRET";
#endif
#ifdef AUTH_MODE_CERT
/* public cert file name of certificate device */
static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt";
/* private key file name of certificate device */
static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key";
#else
/* device secret of PSK device */
static char sg_device_secret[MAX_SIZE_OF_DEVICE_SECRET + 1] = "YOUR_IOT_PSK";
#endif
```
2. 存放在配置文件中编译选项DEBUG_DEV_INFO_USED = OFF则在`device_info.json`文件修改设备信息此方式下更改设备信息不需重新编译SDK在Linux/Windows平台下开发推荐使用这种方式。
```
{
"auth_mode":"KEY/CERT",
"productId":"PRODUCT_ID",
"productSecret":"YOUR_PRODUCT_SECRET",
"deviceName":"YOUR_DEV_NAME",
"key_deviceinfo":{
"deviceSecret":"YOUR_IOT_PSK"
},
"cert_deviceinfo":{
"devCertFile":"YOUR_DEVICE_CERT_FILE_NAME",
"devPrivateKeyFile":"YOUR_DEVICE_PRIVATE_KEY_FILE_NAME"
},
"subDev":{
"sub_productId":"YOUR_SUBDEV_PRODUCT_ID",
"sub_devName":"YOUR_SUBDEV_DEVICE_NAME"
}
}
```
## 应用示例
- 初始化连接参数
```
static DeviceInfo sg_devInfo;
static int _setup_connect_init_params(MQTTInitParams* initParams)
{
int ret;
ret = HAL_GetDevInfo((void *)&sg_devInfo);
if(QCLOUD_RET_SUCCESS != ret){
return ret;
}
initParams->device_name = sg_devInfo.device_name;
initParams->product_id = sg_devInfo.product_id;
......
}
```
- 密钥设备鉴权参数生成
```
static int _serialize_connect_packet(unsigned char *buf, size_t buf_len, MQTTConnectParams *options, uint32_t *serialized_len) {
......
......
int username_len = strlen(options->client_id) + strlen(QCLOUD_IOT_DEVICE_SDK_APPID) + MAX_CONN_ID_LEN + cur_timesec_len + 4;
options->username = (char*)HAL_Malloc(username_len);
get_next_conn_id(options->conn_id);
HAL_Snprintf(options->username, username_len, "%s;%s;%s;%ld", options->client_id, QCLOUD_IOT_DEVICE_SDK_APPID, options->conn_id, cur_timesec);
#if defined(AUTH_WITH_NOTLS) && defined(AUTH_MODE_KEY)
if (options->device_secret != NULL && options->username != NULL) {
char sign[41] = {0};
utils_hmac_sha1(options->username, strlen(options->username), sign, options->device_secret, options->device_secret_len);
options->password = (char*) HAL_Malloc (51);
if (options->password == NULL) IOT_FUNC_EXIT_RC(QCLOUD_ERR_INVAL);
HAL_Snprintf(options->password, 51, "%s;hmacsha1", sign);
}
#endif
......
}
```

View File

@@ -0,0 +1,29 @@
# 设备联网类型说明
本文对连接腾讯云物联网平台(下文以 IoT Explorer 为例)的设备类型进行说明并阐明各设备类型如何移植C-SDK。
## IoT设备联网类型
IoT设备首先得具备接入网络的能力接入网络必须要有TCP/IP协议栈从TCP/IP协议栈承载的载体区分IoT设备分为如下三类:
**类型一**: TCP/IP协议栈跑在主芯片上主芯片的处理能力和资源较丰富譬如路由器本文称作 资源丰富类 IoT设备。
![soc](https://main.qcloudimg.com/raw/b8b8c257ff2a0862fccee025ac361883.jpg)
**类型二**: TCP/IP协议栈跑在通信模组上主芯片处理能力和资源特别有限譬如STM32F103系列本文称作 资源受限类 IoT设备。
![mcu+module](https://main.qcloudimg.com/raw/aa148085175ebc615c4bc6fa3e483188.jpg)
**类型三**: TCP/IP协议栈跑在网关上设备本身并不能直接接入网络通过有线(485/CAN等)或无线(Ble/ZigBee等)的方式和网关交互,网关(设备类型一或设备类型二)再将数据转发到服务端,这类设备本文称作区域通信类设备。
![lan](https://main.qcloudimg.com/raw/31fa38d9eb941fc48041ae18ca1860f6.jpg)
## 不同联网类型的设备接入方式
### 资源丰富类设备接入
C-SDK可以在 Linux 和 Windows 环境直接编译并运行示例,请参照[C-SDK_Build编译环境及配置选项说明]()说明。针对常见的FreeRTOS+lwIP的场景我们也提供了HAL层的示例实现。具体参见[FreeRTOS+lwIP平台移植说明]()。
### 资源受限类设备接入
资源受限类设备借助于通信模组实现网络访问即MCU+模组方式。模组一般是蜂窝模组(2/3/4/5G)或者WIFI模组市面可选的模组非常之多各家的AT指令也各不一样为此我们提供两种方式实现平台接入。
- 一种是基于SDK提供的AT_Socket框架基于模组的通用TCP指令参照at_device目录下的已支持的模组实现AT_Device驱动的结构体**at_device_op_t**实现对应的驱动接口即可,具体参见[MCU+通用TCP_AT模组移植]()。
- 另一种方式是我们和主流的模组厂商做了深度合作将SDK的核心协议已移植到模组中模组对外封装统一的腾讯云AT指令同时我们对MCU提供实现和定制模组交互的SDK具体参见[MCU+腾讯云定制AT模组]()。
### 区域通信类设备接入
对于区域通信类设备网关需要实现SDK的移植SDK针对网关提供对应的协议逻辑代理子设备上线、下线及协议数据交互网关实现和子设备通信方式和数据格式可根据场景定义网关将子设备数据及平台下行数据做响应转换后实现上传下达。网关设备归属于类型一或类型二设备可以对应参照实现SDK移植。

View File

@@ -0,0 +1,69 @@
# 文档说明
本文档介绍如何将腾讯云物联 C-SDK 移植到**FreeRTOS+lwIP** 平台。
## FreeRTOS移植简介
FreeRTOS作为一个微内核系统主要提供任务创建及调度和任务间通信等OS核心机制在不同设备平台还需要搭配多个软件组件包括C运行库如newlib或者ARM CMSIS库和TCP/IP网络协议栈如lwIP才能形成完整的嵌入式运行平台。同时各个设备平台的编译开发环境也各不相同因此在移植C-SDK的时候需要根据不同设备的具体情况进行适配。
SDK 在**platform/os/freertos**里面提供了一个基于 **FreeRTOS+lwIP+newlib** 的参考实现该实现已经在乐鑫ESP8266平台上验证测试过。
## 从腾讯云物联 C-SDK 中抽取相关代码
因为基于RTOS系统的平台编译方式各不相同一般无法直接使用SDK 的cmake或者make编译因此SDK提供了代码抽取功能可根据需要将相关代码抽取到一个单独的文件夹文件夹里面的代码层次目录简洁方便用户拷贝集成到自己的开发环境。
首先修改 CMakeLists.txt 中配置为freertos平台并开启代码抽取功能
```
set(BUILD_TYPE "release")
set(PLATFORM "freertos")
set(EXTRACT_SRC ON)
set(FEATURE_AT_TCP_ENABLED OFF)
```
在Linux环境运行以下命令
```
mkdir build
cd build
cmake ..
```
即可在output/qcloud_iot_c_sdk中找到相关代码文件目录层次如下
```
qcloud_iot_c_sdk
├── include
│   ├── config.h
│   ├── exports
├── platform
└── sdk_src
└── internal_inc
```
include目录为SDK供用户使用的API及可变参数其中config.h为根据编译选项生成的编译宏。API具体介绍请参考**C-SDK_API及可变参数说明**。
platform目录为平台相关的代码可根据设备的具体情况进行修改适配。具体的函数说明请参考文档**C-SDK_Porting跨平台移植概述**
sdk_src为SDK的核心逻辑及协议相关代码一般不需要修改其中internal_inc为SDK内部使用的头文件。
用户可将qcloud_iot_c_sdk拷贝到其目标平台的编译开发环境并根据具体情况修改编译选项。
## 乐鑫ESP8266 RTOS平台移植示例
在Linux开发环境基于乐鑫ESP8266 RTOS平台搭建一个工程示例
### 1. 获取 ESP8266_RTOS_SDK 并创建工程
请参考[ESP8266_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK) 获取RTOS_SDK 和交叉编译器,并创建一个项目工程
### 2. 拷贝SDK代码
将上面抽取的qcloud_iot_c_sdk目录拷贝到components/qcloud_iot下面
在components/qcloud_iot下面新建一个编译配置文件component.mk内容如下
```
#
# Component Makefile
#
COMPONENT_ADD_INCLUDEDIRS := \
qcloud_iot_c_sdk/include \
qcloud_iot_c_sdk/include/exports \
qcloud_iot_c_sdk/sdk_src/internal_inc
COMPONENT_SRCDIRS := \
qcloud_iot_c_sdk/sdk_src \
qcloud_iot_c_sdk/platform
```
这样就可以将qcloud_iot_c_sdk作为一个组件进行编译了之后在用户代码里面就可以调用物联 C-SDK的接口进行连接和收发消息。

View File

@@ -0,0 +1,213 @@
# 物联网开发平台快速入门
物联网开发平台**IoT Explorer**是基于 MQTT 基础能力上,对数据协议的进一步抽象封装,形成[数据模板协议](https://cloud.tencent.com/document/product/1081/34916?!preview&!editLang=zh)。平台基于数据模板的协议,提供丰富的数据展示、调试及应用开发等技术资源,将应用端和设备的开发模板化,加速产品开发进程。
本文档将讲述如何在物联网开发平台控制台申请设备,创建模板,并结合 C-SDK 快速体验设备基于数据模板的数据收发、事件上报及设备调试。
## 一. 控制台创建设备
#### 1. 注册/登录腾讯云账号
访问[腾讯云登录页面](https://cloud.tencent.com/login?s_url=https%3A%2F%2Fcloud.tencent.com%2F), 点击[立即注册](https://cloud.tencent.com/register?s_url=https%3A%2F%2Fcloud.tencent.com%2F), 免费获取腾讯云账号,若您已有账号,可直接登录。
#### 2. 访问物联网开发控制台
登录后点击右上角控制台,进入控制台后,鼠标悬停在云产品上,弹出层叠菜单,点击物联网开发平台。
或者直接访问[物联网开发平台控制台](https://console.cloud.tencent.com/iotexplorer)
#### 3. 创建产品和设备
3.1 创建项目
![](https://main.qcloudimg.com/raw/50dd24cfa44fbb063d4337eb94ae5d0f.jpg)
3.2.创建并选择和产品比较相近的模板产品,参阅[产品定义](https://cloud.tencent.com/document/product/1081/34739?!preview&!editLang=zh)。
![](https://main.qcloudimg.com/raw/c8bd19dee90765762bd6c1f98bd0dd2c.jpg)
![](https://main.qcloudimg.com/raw/4b9fe8f5df7a20ebbab1f0e3693ded8a.jpg)
3.3 定义产品的数据和事件模板,参阅[数据模板创建](https://cloud.tencent.com/document/product/1081/34739?!preview&!editLang=zh#.E6.95.B0.E6.8D.AE.E6.A8.A1.E6.9D.BF),数据模板的说明参见[数据模板协议](https://cloud.tencent.com/document/product/1081/34916?!preview&!editLang=zh)。
![](https://main.qcloudimg.com/raw/17ef8daac4da6f9775ea02bddf988ca2.jpg)
3.4 完成产品创建和数据模板定义后,创建设备,则每一个创建的设备都具备这个产品下的数据模板属性,如下图示。
![](https://main.qcloudimg.com/raw/937698b945dfd2c4f34bffd40ff5165d.jpg)
3.5 查询产品和设备信息
![](https://main.qcloudimg.com/raw/13972a011bb5382d00d73545534af91a.jpg)
![](https://main.qcloudimg.com/raw/17ef8daac4da6f9775ea02bddf988ca2.jpg)
3.6 导出数据模板json文件并通过脚本工具生成数据模板的配置文件
![](https://main.qcloudimg.com/raw/0951d7c3f540ca716442e08651a0efa5.jpg)
将下载的json文件拷贝到tools目录执行./codegen.py -c xx/config.json -d ../targetdir/ 命令,则会根据json文件在target目录生成所定义产品的数据模板及事件的配置文件
```
./codegen.py -c light.json -d ../samples/data_template/
加载 light.json 文件成功
文件 ../samples/data_template/data_config.c 生成成功
文件 ../samples/data_template/events_config.c 生成成功
```
## 二. 编译示例程序
详细的编译方式请参考**编译及配置选项说明文档**,本文基于 Linux 环境介绍示例编译运行(以**密钥认证设备**为例)。
#### 1. 填入设备信息
将上面步骤在腾讯云物联网平台创建的设备的设备信息填写到device_info.json中
```
"auth_mode":"KEY",
"productId":"5S6AQZ6IDE",
"deviceName":"dev01",
"key_deviceinfo":{
"deviceSecret":"vX6PQqazsGsMyf5SMfs6OA6y"
}
```
#### 2. 基于数据模板的业务逻辑开发
数据模板示例data_template_sample.c已实现数据、事件收发及响应的通用处理逻辑。但是具体的数据处理的业务逻辑需要用户自己根据业务逻辑添加上下行业务逻辑添加的入口函数分别为deal_up_stream_user_logic 、deal_down_stream_user_logic如果有字符串或json类型的数据模板用户需要在函数update_self_define_value中完成数据的解析其他数据类型会根据模板定义自动更新可以参考基于场景的示例light_data_template_sample.c添加业务处理逻辑。
下行业务逻辑实现:
```
/* user's own down-stream code */
void deal_down_stream_user_logic(ProductDataDefine * pData)
{
Log_d("someting about your own product logic wait to be done");
}
```
上行业务逻辑实现:
```
/* demo for up-stream code */
int deal_up_stream_user_logic(DeviceProperty *pReportDataList[], int *pCount)
{
int i, j;
for (i = 0, j = 0; i < TOTAL_PROPERTY_COUNT; i++) {
if(eCHANGED == sg_DataTemplate[i].state) {
pReportDataList[j++] = &(sg_DataTemplate[i].data_property);
sg_DataTemplate[i].state = eNOCHANGE;
}
}
*pCount = j;
return (*pCount > 0)?QCLOUD_RET_SUCCESS:QCLOUD_ERR_FAILURE;
}
```
#### 3. 编译 SDK
首先修改CMakeLists.txt确保以下选项存在
```
set(BUILD_TYPE "release")
set(COMPILE_TOOLS "gcc")
set(PLATFORM "linux")
set(FEATURE_MQTT_COMM_ENABLED ON)
set(FEATURE_AUTH_MODE "KEY")
set(FEATURE_AUTH_WITH_NOTLS OFF)
set(FEATURE_DEBUG_DEV_INFO_USED OFF)
```
完整编译库和示例
```
./cmake_build.sh
```
输出的库文件,头文件及示例在`output/release`文件夹中。
在一次完整编译之后,若只需要编译示例,则执行
```
./cmake_build.sh samples
```
## 三. 执行示例程序
#### 执行 data_template_sample 示例程序
数据模板示例实现通用的数据模板和事件处理的框架,数据上下行和事件上报的日志如下:
```
./output/release/bin/data_template_sample
INF|2019-09-18 15:11:54|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: 5S6AQZ6IDE, Device_Name: dev01
DBG|2019-09-18 15:11:54|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure...
DBG|2019-09-18 15:11:54|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake...
DBG|2019-09-18 15:11:54|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /5S6AQZ6IDE.wx-mqtt.tencentdevices.com/8883...
INF|2019-09-18 15:11:55|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /5S6AQZ6IDE.wx-mqtt.tencentdevices.com/8883...
INF|2019-09-18 15:11:55|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: r7891 success
DBG|2019-09-18 15:11:55|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$template/operation/result/5S6AQZ6IDE/dev01|packet_id=4412
DBG|2019-09-18 15:11:55|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=4412
INF|2019-09-18 15:11:55|data_template_sample.c|event_handler(124): subscribe success, packet-id=4412
INF|2019-09-18 15:11:55|shadow_client.c|IOT_Shadow_Construct(172): Sync device data successfully
INF|2019-09-18 15:11:55|data_template_sample.c|main(319): Cloud Device Construct Success
DBG|2019-09-18 15:11:55|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$thing/down/event/5S6AQZ6IDE/dev01|packet_id=4413
INF|2019-09-18 15:11:55|data_template_sample.c|_register_data_template_property(270): data template property=time registered.
INF|2019-09-18 15:11:55|data_template_sample.c|_register_data_template_property(270): data template property=float registered.
INF|2019-09-18 15:11:55|data_template_sample.c|_register_data_template_property(270): data template property=light_switch registered.
INF|2019-09-18 15:11:55|data_template_sample.c|_register_data_template_property(270): data template property=color registered.
INF|2019-09-18 15:11:55|data_template_sample.c|_register_data_template_property(270): data template property=brightness registered.
INF|2019-09-18 15:11:55|data_template_sample.c|_register_data_template_property(270): data template property=name registered.
INF|2019-09-18 15:11:55|data_template_sample.c|main(340): Register data template propertys Success
DBG|2019-09-18 15:11:55|shadow_client.c|IOT_Shadow_Get(383): GET Request Document: {"clientToken":"explorer-5S6AQZ6IDE-0"}
DBG|2019-09-18 15:11:55|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=4414|topicName=$template/operation/5S6AQZ6IDE/dev01|payload={"type":"get", "clientToken":"explorer-5S6AQZ6IDE-0"}
INF|2019-09-18 15:11:55|data_template_sample.c|event_handler(138): publish success, packet-id=4414
DBG|2019-09-18 15:11:55|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=4413
INF|2019-09-18 15:11:55|data_template_sample.c|event_handler(124): subscribe success, packet-id=4413
DBG|2019-09-18 15:11:55|shadow_client_manager.c|_on_operation_result_handler(278): type:get
DBG|2019-09-18 15:11:55|shadow_client.c|_update_ack_cb(114): requestAck=0
DBG|2019-09-18 15:11:55|shadow_client.c|_update_ack_cb(117): Received Json Document={"clientToken":"explorer-5S6AQZ6IDE-0","payload":{"state":{"reported":{"battery":35,"brightness":55,"color":0,"id":"19","name":"dev01","power_switch":0}},"timestamp":1568776522035,"version":401},"result":0,"timestamp":1568790715,"type":"get"}
DBG|2019-09-18 15:11:56|data_template_sample.c|main(389): No delta msg received...
DBG|2019-09-18 15:11:56|data_template_sample.c|main(409): no data need to be reported
DBG|2019-09-18 15:11:56|mqtt_client_publish.c|qcloud_iot_mqtt_publish(337): publish packetID=0|topicName=$thing/up/event/5S6AQZ6IDE/dev01|payload={"method":"events_post", "clientToken":"5S6AQZ6IDE-1", "events":[{"eventId":"all_function", "type":"alert", "timestamp":1568790716000, "params":{"bool":0,"int":0,"str":"","float":0.000000,"enum1":0,"time":0}},{"eventId":"status_report", "type":"info", "timestamp":1568790716000, "params":{"status":0,"message":""}},{"eventId":"hardware_fault", "type":"fault", "timestamp":1568790716000, "params":{"name":"","error_code":0}}]}
INF|2019-09-18 15:11:59|qcloud_iot_event.c|_on_event_reply_callback(96): Receive Message With topicName:$thing/down/event/5S6AQZ6IDE/dev01, payload:{"method":"events_reply","clientToken":"5S6AQZ6IDE-1","code":404,"status":"hardware_fault not defined","data":{}}
DBG|2019-09-18 15:11:59|qcloud_iot_event.c|_on_event_reply_callback(115): eventToken:5S6AQZ6IDE-1 code:404 status:hardware_fault not defined
DBG|2019-09-18 15:11:59|data_template_sample.c|event_post_cb(68): Reply:{"method":"events_reply","clientToken":"5S6AQZ6IDE-1","code":404,"status":"hardware_fault not defined","data":{}}
DBG|2019-09-18 15:11:59|qcloud_iot_event.c|_release_reply_request(78): eventToken[5S6AQZ6IDE-1] released
```
#### 执行 light_data_template_sample 示例程序
智能灯示例是基于数据数据模板的场景示例,基于此示例说明控制台和设备端控制交互及日志查询
```
./output/release/bin/light_data_template_sample
INF|2019-09-18 15:14:08|device.c|iot_device_info_set(67): SDK_Ver: 3.1.0, Product_ID: 5S6AQZ6IDE, Device_Name: dev01
DBG|2019-09-18 15:14:08|HAL_TLS_mbedtls.c|HAL_TLS_Connect(204): Setting up the SSL/TLS structure...
DBG|2019-09-18 15:14:08|HAL_TLS_mbedtls.c|HAL_TLS_Connect(246): Performing the SSL/TLS handshake...
DBG|2019-09-18 15:14:08|HAL_TLS_mbedtls.c|HAL_TLS_Connect(247): Connecting to /5S6AQZ6IDE.wx-mqtt.tencentdevices.com/8883...
INF|2019-09-18 15:14:08|HAL_TLS_mbedtls.c|HAL_TLS_Connect(269): connected with /5S6AQZ6IDE.wx-mqtt.tencentdevices.com/8883...
INF|2019-09-18 15:14:09|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: JYqyP success
DBG|2019-09-18 15:14:09|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$template/operation/result/5S6AQZ6IDE/dev01|packet_id=22146
DBG|2019-09-18 15:14:09|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=22146
INF|2019-09-18 15:14:09|light_data_template_sample.c|event_handler(235): subscribe success, packet-id=22146
INF|2019-09-18 15:14:09|shadow_client.c|IOT_Shadow_Construct(172): Sync device data successfully
INF|2019-09-18 15:14:09|light_data_template_sample.c|main(510): Cloud Device Construct Success
DBG|2019-09-18 15:14:09|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(138): topicName=$thing/down/event/5S6AQZ6IDE/dev01|packet_id=22147
INF|2019-09-18 15:14:09|light_data_template_sample.c|_register_data_template_property(385): data template property=power_switch registered.
INF|2019-09-18 15:14:09|light_data_template_sample.c|_register_data_template_property(385): data template property=color registered.
INF|2019-09-18 15:14:09|light_data_template_sample.c|_register_data_template_property(385): data template property=brightness registered.
INF|2019-09-18 15:14:09|light_data_template_sample.c|_register_data_template_property(385): data template property=name registered.
INF|2019-09-18 15:14:09|light_data_template_sample.c|main(531): Register data template propertys Success
DBG|2019-09-18 15:14:09|shadow_client.c|IOT_Shadow_Get(383): GET Request Document: {"clientToken":"explorer-5S6AQZ6IDE-0"}
DBG|2019-09-18 15:14:09|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=22148|topicName=$template/operation/5S6AQZ6IDE/dev01|payload={"type":"get", "clientToken":"explorer-5S6AQZ6IDE-0"}
INF|2019-09-18 15:14:09|light_data_template_sample.c|event_handler(249): publish success, packet-id=22148
DBG|2019-09-18 15:14:09|shadow_client.c|_shadow_event_handler(63): shadow subscribe success, packet-id=22147
INF|2019-09-18 15:14:09|light_data_template_sample.c|event_handler(235): subscribe success, packet-id=22147
DBG|2019-09-18 15:14:09|shadow_client_manager.c|_on_operation_result_handler(278): type:get
DBG|2019-09-18 15:14:09|shadow_client.c|_update_ack_cb(114): requestAck=0
DBG|2019-09-18 15:14:09|shadow_client.c|_update_ack_cb(117): Received Json Document={"clientToken":"explorer-5S6AQZ6IDE-0","payload":{"state":{"reported":{"battery":35,"brightness":55,"color":0,"id":"19","name":"dev01","power_switch":0}},"timestamp":1568776522035,"version":401},"result":0,"timestamp":1568790849,"type":"get"}
DBG|2019-09-18 15:14:09|light_data_template_sample.c|main(602): no data need to be reported
DBG|2019-09-18 15:14:09|light_data_template_sample.c|main(609): cycle report:{"state":{"reported":{"power_switch":0,"color":0,"brightness":0,"name":"dev01"}}, "clientToken":"explorer-5S6AQZ6IDE-1"}
DBG|2019-09-18 15:14:09|shadow_client.c|IOT_Shadow_Update(317): UPDATE Request Document: {"state":{"reported":{"power_switch":0,"color":0,"brightness":0,"name":"dev01"}}, "clientToken":"explorer-5S6AQZ6IDE-1"}
DBG|2019-09-18 15:14:09|mqtt_client_publish.c|qcloud_iot_mqtt_publish(329): publish topic seq=22149|topicName=$template/operation/5S6AQZ6IDE/dev01|payload={"type":"update", "state":{"reported":{"power_switch":0,"color":0,"brightness":0,"name":"dev01"}}, "clientToken":"explorer-5S6AQZ6IDE-1"}
INF|2019-09-18 15:14:09|light_data_template_sample.c|main(613): cycle reporte success
INF|2019-09-18 15:14:10|light_data_template_sample.c|event_handler(249): publish success, packet-id=22149
DBG|2019-09-18 15:14:10|shadow_client_manager.c|_on_operation_result_handler(278): type:update
INF|2019-09-18 15:14:10|light_data_template_sample.c|OnShadowUpdateCallback(370): recv shadow update response, response ack: 0
```
## 四. 设备调试
1. 进入设备调试:
![](https://main.qcloudimg.com/raw/1f2ac1d6cac186394ac1a1da6c22749c.jpg)
2. 修改目标数据下发设备
![](https://main.qcloudimg.com/raw/911a09872f03a91d1d530537e51147f1.jpg)
3.设备响应及日志输出
![](https://main.qcloudimg.com/raw/c45d35d9abe116408efc2656b55127b7.jpg)
4. 控制台查看设备当前状态
![](https://main.qcloudimg.com/raw/236b8bf3c88b1c532714b730d0993a79.jpg)
5. 控制台查看设备通信日志
![](https://main.qcloudimg.com/raw/10e911975030f2840b9af03a079aec1d.jpg)
6. 控制台查看设备事件上报
![](https://main.qcloudimg.com/raw/d3878541b502619158ec206fc2ae2391.jpg)

View File

@@ -0,0 +1,16 @@
## 简介
腾讯云物联网提供了专用的 [腾讯云IoT AT指令集](https://github.com/tencentyun/qcloud-iot-sdk-tencent-at-based/blob/master/docs/%E8%85%BE%E8%AE%AF%E4%BA%91IoT%20AT%E6%8C%87%E4%BB%A4%E9%9B%86-V3.1.3.pdf)如果通讯模组实现了该指令集则设备接入和通讯更为简单所需代码量更少针对这种场景请参考面向腾讯云定制AT模组专用的 [MCU AT SDK](https://github.com/tencentyun/qcloud-iot-sdk-tencent-at-based.git)
目前腾讯云和主流的模组厂商进行了深度合作将SDK的核心协议已移植到模组中模组对外封装统一的腾讯云AT指令。已支持腾讯云定制AT指令的模组列表如下
| 序号 | 模组商 | 模组型号 | 通信制式 | 固件版本 |
| -------| ------------| -------------------|------------------|----------------|
| 1 | 中移 | M5311 | NB-IoT | M5311_LV_MOD_BOM_R002_1901232019_0906 |
| 2 | 中移 | M6315 | 2G | CMIOT_M6315_20180901_V10_EXT_20190827_152209 |
| 3 | 中移 | M8321 | 4G | QCloud_AT_v3.0.1_4G_Cellular 20190909_171245 |
| 4 | 有方 | N10 | 2G | N10_I_1187_PQS63010_TC_V002C |
| 5 | 有方 | N21 | NB-IoT | N21_RDD0CM_TC_V006A |
| 6 | 有方 | N720 | 4G | N720_EAB0CMF_BZ_V003A_T1 |
| 7 | 移柯 | L206 | 2G | L206Dv01.04b04.04 |
| 8 | 乐鑫 | ESP8266 | WIFI | QCloud_AT_ESP_WiFi_v1.1.0 |

View File

@@ -0,0 +1,49 @@
## 简介
对于不具备网络通讯能力的MCU一般采用MCU+通讯模组的方式通讯模组包括WiFi/2G/4G/NB-IoT一般提供了基于串口的AT指令协议供MCU进行网络通讯。针对这种场景C-SDK 封装了AT-socket网络层网络层之上的核心协议和服务层无须移植。本文阐述针对 MCU(FreeRTOS)+通用TCP AT模组的目标环境如何移植C-SDK 并接入腾讯云物联网平台以IoT Explorer为例
## 系统框图
![mcu+module](https://main.qcloudimg.com/raw/aa148085175ebc615c4bc6fa3e483188.jpg)
## 移植步骤
![port_flow](https://main.qcloudimg.com/raw/3717052f47405e66a754f2f8594c6c84.jpg)
### 1. 下载最新版本设备端 [C-SDK](https://github.com/tencentyun/qcloud-iot-sdk-embedded-c)。
### 2. SDK功能配置及代码抽取
- 使用通用TCP模组编译配置选项配置如下:
| 名称 | 配置 | 说明 |
| :------------------------------- | ------------- | ------------------------------------------------------------ |
| BUILD_TYPE | debug/release,根据需要设置 |
| EXTRACT_SRC | ON | 使能代码抽取 |
| COMPILE_TOOLS | gcc/MSVC | 根据需要设置IDE情况不关注 |
| PLATFORM | linux/windows | 根据需要设置IDE情况不关注 |
| FEATURE_OTA_COMM_ENABLED | ON/OFF | 根据需要设置 |
| FEATURE_AUTH_MODE | KEY | 资源受限设备认证方式建议选秘钥认证 |
| FEATURE_AUTH_WITH_NOTLS | ON/OFF | 根据需要是否使能TLS |
| FEATURE_EVENT_POST_ENABLED | ON/OFF | 根据需要是否使能事件上报 |
| FEATURE_AT_TCP_ENABLED | ON | AT模组TCP功能开关 |
| FEATURE_AT_UART_RECV_IRQ | ON | AT模组中断接受功能开关 |
| FEATURE_AT_OS_USED | ON | AT模组多线程功能开关 |
| FEATURE_AT_DEBUG | OFF | 默认关闭AT模组调试功能有调试需要再打开|
- 参考文档[C-SDK_Build编译环境及配置选项说明]()抽取代码
- 将抽取的代码目录作为通信组件放在类似 RTOS、FATFS 的第三方组件的同级目录,系统代码框架大体如下:
![](https://main.qcloudimg.com/raw/5e3da49ac27e57d72fd6f6a70bb98547.jpg)
### 3. 数据模板模板代码生成
对于IoT_Explorer产品可以参考[IoT_Explorer/Data_template数据模板代码生成]()
对于IoT_Hub产品可跳过这一步
### 4. HAL 层移植
参见[C-SDK_Porting跨平台移植概述]()
对于网络相关的HAL接口通过上面的编译选项已选择SDK提供的AT_Socket框架SDK会调用 network_at_tcp.c 的at_socket接口at_socket层不需要移植需要实现AT串口驱动及AT模组驱动AT模组驱动只需要实现AT框架中at_device的驱动结构体 *at_device_op_t* 的驱动接口即可可以参照at_device目录下的已支持的模组。目前SDK针对物联网使用较广的WiFi模组ESP8266提供了底层接口实现供移植到其他通讯模组时作为参考。
### 5. 业务逻辑开发
对于IoT_Explorer产品可以参考[IoT_Explorer/Data_template数据模板应用开发]()实现具体业务场景下的业务逻辑开发。
对于IoT_Hub产品可以参考IoT_Hub目录下的例程。

View File

@@ -0,0 +1,51 @@
## 简介
对于不具备网络通讯能力的MCU一般采用MCU+通讯模组的方式通讯模组包括WiFi/2G/4G/NB-IoT一般提供了基于串口的AT指令协议供MCU进行网络通讯。针对这种场景C-SDK 封装了AT-socket网络层网络层之上的核心协议和服务层无须移植。本文阐述针对 MCU(无OS)+通用TCP AT模组的目标环境如何移植C-SDK 并接入腾讯云物联网平台以IoT Explorer为例
相较于有RTOS场景at_socket网络接收数据的处理会有差异应用层需要周期性的调用**IOT_MQTT_Yield**来接收服务端下行数据错过接收窗口则会存在数据丢失的情况所以在业务逻辑较为复杂的场景建议使用RTOS通过配置 FEATURE_AT_OS_USED = OFF选择无OS方式。
## 系统框图
![mcu+module](https://main.qcloudimg.com/raw/aa148085175ebc615c4bc6fa3e483188.jpg)
## 移植步骤
![port_flow](https://main.qcloudimg.com/raw/3717052f47405e66a754f2f8594c6c84.jpg)
### 1. 下载最新版本设备端 [C-SDK](https://github.com/tencentyun/qcloud-iot-sdk-embedded-c)。
### 2. SDK功能配置及代码抽取
- 无RTOS使用通用TCP模组编译配置选项配置如下:
| 名称 | 配置 | 说明 |
| :------------------------------- | ------------- | ------------------------------------------------------------ |
| BUILD_TYPE | debug/release,根据需要设置 |
| EXTRACT_SRC | ON | 使能代码抽取 |
| COMPILE_TOOLS | gcc/MSVC | 根据需要设置IDE情况不关注 |
| PLATFORM | linux/windows | 根据需要设置IDE情况不关注 |
| FEATURE_OTA_COMM_ENABLED | ON/OFF | 根据需要设置 |
| FEATURE_AUTH_MODE | KEY | 资源受限设备认证方式建议选秘钥认证 |
| FEATURE_AUTH_WITH_NOTLS | ON/OFF | 根据需要是否使能TLS |
| FEATURE_EVENT_POST_ENABLED | ON/OFF | 根据需要是否使能事件上报 |
| FEATURE_AT_TCP_ENABLED | ON | 使能at_socket组件 |
| FEATURE_AT_UART_RECV_IRQ | ON | 使能AT串口中断接收 |
| FEATURE_AT_OS_USED | OFF | at_socket组件无RTOS环境使用 |
| FEATURE_AT_DEBUG | OFF | 默认关闭AT模组调试功能有调试需要再打开|
- 参考文档[C-SDK_Build编译环境及配置选项说明]()抽取代码
- 将抽取的代码目录作为通信组件放在类似 RTOS、FATFS 的第三方组件的同级目录,系统代码框架大体如下:
![](https://main.qcloudimg.com/raw/5e3da49ac27e57d72fd6f6a70bb98547.jpg)
### 3. 数据模板模板代码生成
对于IoT_Explorer产品可以参考[IoT_Explorer/Data_template数据模板代码生成]()
对于IoT_Hub产品可跳过这一步
### 4. HAL 层移植
参见[C-SDK_Porting跨平台移植概述]()
对于网络相关的HAL接口通过上面的编译选项已选择SDK提供的AT_Socket框架SDK会调用 network_at_tcp.c 的at_socket接口at_socket层不需要移植需要实现AT串口驱动及AT模组驱动AT模组驱动只需要实现AT框架中at_device的驱动结构体 *at_device_op_t* 的驱动接口即可可以参照at_device目录下的已支持的模组。AT串口驱动需要实现串口的中断接收然后在中断服务程序中调用回调函数 *at_client_uart_rx_isr_cb* 即可,可以参考 HAL_OS_nonos.c 实现目标平台的移植。
### 5. 业务逻辑开发
对于IoT_Explorer产品可以参考[IoT_Explorer/Data_template数据模板应用开发]()实现具体业务场景下的业务逻辑开发。
对于IoT_Hub产品可以参考IoT_Hub目录下的例程。

View File

@@ -0,0 +1,19 @@
## 简介
本文介绍基于物联开发平台 IoT Explorer 创建的数据模板如何生成模板代码。
## 数据模板创建
参阅[产品定义](https://cloud.tencent.com/document/product/1081/34739?!preview&!editLang=zh#.E6.95.B0.E6.8D.AE.E6.A8.A1.E6.9D.BF)创建数据模板
## 数据模板描述文件导出
数据模板描述文件是一个 JSON 格式的文件描述了产品定义的属性、事件及其他信息在平台导出此json文件如下图示:
![](https://main.qcloudimg.com/raw/0951d7c3f540ca716442e08651a0efa5.jpg)
## 数据模板模板代码生成
将下载的json文件拷贝到tools目录执行./codegen.py -c xx/config.json -d ../targetdir/ 命令,则会根据json文件在target目录生成所定义产品的数据模板及事件的配置文件,将这个生成的配置文件拷贝到data_template_sample.c的同级目录data_template_sample.c示例了通用的数据模板处理框架可以基于此框架添加业务逻辑。智能灯示例light_data_template_sample.c即是基于此框架的场景示例。
```
./codegen.py -c light.json -d ../samples/data_template/
加载 light.json 文件成功
文件 ../samples/data_template/data_config.c 生成成功
文件 ../samples/data_template/events_config.c 生成成功
```

View File

@@ -0,0 +1,99 @@
## 数据模板业务逻辑开发
数据模板示例data_template_sample.c已实现数据、事件收发及响应的通用处理框架。可以基于此示例开发业务逻辑上下行业务逻辑添加的入口函数分别为 deal_up_stream_user_logic 、deal_down_stream_user_logic。可以参考智能灯的场景示例 light_data_template_sample.c 添加业务处理逻辑。
### 下行业务逻辑实现
- 服务端下行的数据SDK已按数据模板协议完成了json数据的解析。ProductDataDefine是第三步中根据在平台定义的产品数据模板生成的模板结构体由定义的各属性构成成员变量。入参pData所指向的属性数据从服务端下行数据中SDK已经按数据模板协议完成了属性数据的解析用户在下行逻辑处理的函数里边可以直接使用解析好的数据添加业务逻辑即可。
- 用户根据数据模板数据pData进行相应的业务逻辑处理。
```
/*用户需要实现的下行数据的业务逻辑,pData除字符串变量已实现用户定义的所有其他变量值解析赋值待用户实现业务逻辑*/
static void deal_down_stream_user_logic(void *client, ProductDataDefine * pData)
{
Log_d("someting about your own product logic wait to be done");
}
```
- 示例用法:
```
/*智能灯属性数据模板*/
typedef struct _ProductDataDefine {
TYPE_DEF_TEMPLATE_BOOL m_light_switch;
TYPE_DEF_TEMPLATE_ENUM m_color;
TYPE_DEF_TEMPLATE_INT m_brightness;
TYPE_DEF_TEMPLATE_STRING m_name[MAX_STR_NAME_LEN+1];
} ProductDataDefine;
/*示例灯光控制处理逻辑*/
static void deal_down_stream_user_logic(void *client,ProductDataDefine *light)
{
int i;
const char * ansi_color = NULL;
const char * ansi_color_name = NULL;
char brightness_bar[] = "||||||||||||||||||||";
int brightness_bar_len = strlen(brightness_bar);
/*灯光颜色*/
switch(light->m_color) {
case eCOLOR_RED:
ansi_color = ANSI_COLOR_RED;
ansi_color_name = " RED ";
break;
case eCOLOR_GREEN:
ansi_color = ANSI_COLOR_GREEN;
ansi_color_name = "GREEN";
break;
case eCOLOR_BLUE:
ansi_color = ANSI_COLOR_BLUE;
ansi_color_name = " BLUE";
break;
default:
ansi_color = ANSI_COLOR_YELLOW;
ansi_color_name = "UNKNOWN";
break;
}
/* 灯光亮度显示条 */
brightness_bar_len = (light->m_brightness >= 100)?brightness_bar_len:(int)((light->m_brightness * brightness_bar_len)/100);
for (i = brightness_bar_len; i < strlen(brightness_bar); i++) {
brightness_bar[i] = '-';
}
if(light->m_light_switch){
/* 灯光开启式,按照控制参数展示 */
HAL_Printf( "%s[ lighting ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,\
ansi_color,ansi_color_name,brightness_bar,light->m_name);
}else{
/* 灯光关闭展示 */
HAL_Printf( ANSI_COLOR_YELLOW"[ light is off ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,\
ansi_color_name,brightness_bar,light->m_name);
}
}
### 上行业务逻辑实现
- 设备端根据业务场景需要,对设备端数据属性采取一定策略进行监测处理,用户可以在***deal_up_stream_user_logic***中将需要上报的属性更新给入参pReportDataList属性上报列表及需要上报的属性个数数据模板的示例处理框架在***IOT_Template_JSON_ConstructReportArray***中会将属性数据列表处理为数据模板的协议格式,***IOT_Template_Report***将数据发送给服务端。
```
/*用户需要实现的上行数据的业务逻辑,此处仅供示例*/
static int deal_up_stream_user_logic(DeviceProperty *pReportDataList[], int *pCount)
{
int i, j;
/*监测是否需要更新本地数据*/
_local_property_refresh();
/*将变化的属性更新到上报列表*/
for (i = 0, j = 0; i < TOTAL_PROPERTY_COUNT; i++) {
if(eCHANGED == sg_DataTemplate[i].state) {
pReportDataList[j++] = &(sg_DataTemplate[i].data_property);
sg_DataTemplate[i].state = eNOCHANGE;
}
}
*pCount = j;
return (*pCount > 0)?QCLOUD_RET_SUCCESS:QCLOUD_ERR_FAILURE;
}
```