# linkedge-thing-access-sdk-c
**Repository Path**: aliyun/linkedge-thing-access-sdk-c
## Basic Information
- **Project Name**: linkedge-thing-access-sdk-c
- **Description**: Link IoT Edge提供的设备接入驱动开发SDK,帮助用户在Link IoT Edge上快速开发自定义协议设备接入驱动。
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-05-08
- **Last Updated**: 2025-08-15
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[中文](README.md)|[English](README-en.md)
# `设备接入SDK版本更新注意事项:`
1. 设备接入SDK在[v1.0.0](https://github.com/aliyun/linkedge-thing-access-sdk-c/releases)版本进行重构,部分接口不兼容老版本接口,即使用v1.0.0之前版本SDK开发的驱动,可能导致无法直接使用v1.0.0版本升级;
2. 使用v1.0.0版本SDK开发的驱动支持[Link IoT Edge版本](https://help.aliyun.com/document_detail/120995.html?spm=a2c4g.11186623.6.553.1ffe4224dxnjxT)1.8.1至最新版本;
3. 使用v1.0.0之前版本开发的驱动支持[Link IoT Edge版本](https://help.aliyun.com/document_detail/120995.html?spm=a2c4g.11186623.6.553.1ffe4224dxnjxT)1.8.1至最新版本,但不建议使用该版本SDK继续开发新驱动;
# Link IoT Edge设备接入SDK C语言版
本项目提供设备接入SDK(C语言版),方便开发者在[Link IoT Edge](https://help.aliyun.com/product/69083.html?spm=a2c4g.11186623.6.540.7c1b705eoBIMFA)上编写设备接入驱动。
## 编译环境
建议使用 Ubuntu 16.04 (x86_64) 或 CentOS 7.0 (x86_64) 进行开发。如果当前系统与这两个系统不一致,建议使用虚拟机安装这两个系统,虚拟机可以使用免费虚拟机软件[VirtualBox](https://www.virtualbox.org/)
`注`:不建议使用 DockerHub 中的相应镜像
### Ubuntu 16.04 (x86_64)
镜像可以从这里[下载](http://releases.ubuntu.com/xenial/ubuntu-16.04.6-desktop-amd64.iso),关于不同版本的介绍见[链接](http://releases.ubuntu.com/xenial/)
### CentOS 7.0 (x86_64)
镜像可以从这里[下载](http://vault.centos.org/7.0.1406/isos/x86_64/CentOS-7.0-1406-x86_64-DVD.iso),关于不同版本的介绍见[链接](https://wiki.centos.org/Download)
## 编译依赖
### 依赖工具
本工程需要的编译工具版本保证和表格中列举版本一致或更高版本,否则将编译可能会失败
Tool | Version |
---------------|---------|
gcc | 4.8.5+ |
make | 3.82+ |
ld | 2.17+ |
cmake | 3.11.1+ |
autoconf | 2.69+ |
libtool | 2.4.6+ |
zip | 3.0+ |
### 依赖组件
本工程依赖库的版本要保证和表格中列举版本一致或更高版本,否则将编译可能会失败,工程deps文件下夹下有依赖组件的源码
Componet | Version |
---------------|---------|
cjson | 1.5.5+ |
expat | 2.2.0+ |
dbus | 1.2.1+ |
## 快速开始 - demo
`demo_led`示例演示将设备接入Link IoT Edge的过程。
### demo编译
#### 标准编译(X86平台)
``` sh
$git clone git@github.com:aliyun/linkedge-thing-access-sdk-c.git
$cd linkedge-thing-access-sdk-c
$make prepare #预编译生成外部依赖库
$make && make install #生成leda_sdk_c和demo
```
#### 交叉编译(ARM平台)
第一步,编辑build-cross-compile.sh脚本,填写编译目标结构和编译工具链信息
``` sh
# 编译目标Arch选择
export HOST=x86_64
export ARCH=arm-linux-gnueabihf
export TARGET=${ARCH}
# 在CROSS_ROOT填写交叉编译工具链目录位置
export CROSS_ROOT=
export CROSS_COMPILE=${CROSS_ROOT}/bin/arm-linux-gnueabihf-
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
export LD=${CROSS_COMPILE}ld
export AR=${CROSS_COMPILE}ar
export RANLIB=${CROSS_COMPILE}ranlib
export STRIP=${CROSS_COMPILE}strip
```
第二步,执行build-cross-compile.sh脚本
``` sh
$./build-cross-compile.sh #生成leda_sdk_c和demo
```
### demo演示
1. 进入工程build/bin/demo/demo_led目录。
2. 找到led_driver.zip压缩包。
3. 进入Link IoT Edge控制台,**分组管理**,**驱动管理**,**新建驱动**。
4. 语言类型选择*c*,CPU架构根据编译环境进行选择。
5. 驱动名称设置为`led_driver`,并上传前面准备好的zip包。
6. 创建一个产品,名称为`demo_led`。该产品包含一个`temperature`属性(int32类型)和一个`high_temperature`事件(int32类型和一个int32类型名为`temperature`的输入参数)。
7. 创建一个名为`demo_led`的上述产品的设备。
8. 创建一个新的分组,并将Link IoT Edge网关设备加入到分组。
9. 进入设备驱动配置页,添加`led_driver`驱动。
10. 将`demo_led`设备分配到`led_driver`驱动。
11. 进入消息路由页,使用如下配置添加*消息路由*:
* 消息来源:`demo_led`设备
* TopicFilter:属性
* 消息目标:IoT Hub
12. 部署分组。`demo_led`设备将每隔5秒上报属性到云端,可在Link IoT Edge控制台设备运行状态页面查看。
## 开发文档
完整驱动开发流程见[开发文档](https://help.aliyun.com/document_detail/104444.html?spm=a2c4g.11186623.6.562.7aaa8f08JPJf2d)
## API参考手册
- **[get_properties_callback](#get_properties_callback)**
- **[set_properties_callback](#set_properties_callbackr)**
- **[call_service_callback](#call_service_callback)**
- **[leda_report_properties](#leda_report_properties)**
- **[leda_report_event](#leda_report_event)**
- **[leda_online](#leda_online)**
- **[leda_offline](#leda_offline)**
- **[leda_register_and_online_by_device_name](#leda_register_and_online_by_device_name)**
- **[leda_register_and_online_by_local_name](#leda_register_and_online_by_local_name)**
- **[leda_init](#leda_init)**
- **[leda_exit](#leda_exit)**
- **[leda_get_driver_info_size](#leda_get_driver_info_size)**
- **[leda_get_driver_info](#leda_get_driver_info)**
- **[leda_get_device_info_size](#leda_get_device_info_size)**
- **[leda_get_device_info](#leda_get_device_info)**
- **[leda_get_config_size](#leda_get_config_size)**
- **[leda_get_config](#leda_get_config)**
- **[config_changed_callback](#config_changed_callback)**
- **[leda_register_config_changed_callback](#leda_register_config_changed_callback)**
- **[leda_get_tsl_size](#leda_get_tsl_size)**
- **[leda_get_tsl](#leda_get_tsl)**
- **[leda_get_tsl_ext_info_size](#leda_get_tsl_ext_info_size)**
- **[leda_get_tsl_ext_info](#leda_get_tsl_ext_info)**
- **[leda_get_device_handle](#leda_get_device_handle)**
---
``` c
/*
* 获取属性(对应设备产品物模型属性定义)的回调函数, 需驱动开发者实现获取属性业务逻辑
*
* LinkEdge 需要获取某个设备的属性时, SDK 会调用该接口间接获取到数据并封装成固定格式后回传给 LinkEdge.
* 开发者需要根据设备id和属性名找到设备, 将获取到的属性值按照@device_data_t格式填充.
*
* @dev_handle: LinkEdge 需要获取属性的具体某个设备.
* @properties: 属性值键值结构, 驱动开发者需要将根据属性名称获取到的属性值更新到properties中.
* @properties_count: 属性个数.
* @usr_data: 注册设备时, 用户传递的私有数据.
* 所有属性均获取成功则返回LE_SUCCESS, 其他则返回错误码(参考le_error.h错误码宏定义).
* */
typedef int (*get_properties_callback)(device_handle_t dev_handle,
leda_device_data_t properties[],
int properties_count,
void *usr_data);
```
---
``` c
/*
* 设置属性(对应设备产品物模型属性定义)的回调函数, 需驱动开发者实现设置属性业务逻辑
*
* LinkEdge 需要设置某个设备的属性时, SDK 会调用该接口将具体的属性值传递给应用程序, 开发者需要在本回调
* 函数里将属性设置到设备.
*
* @dev_handle: LinkEdge 需要设置属性的具体某个设备.
* @properties: LinkEdge 需要设置的设备的属性名称和值.
* @properties_count: 属性个数.
* @usr_data: 注册设备时, 用户传递的私有数据.
*
* 若获取成功则返回LE_SUCCESS, 失败则返回错误码(参考le_error.h错误码宏定义).
* */
typedef int (*set_properties_callback)(device_handle_t dev_handle,
const leda_device_data_t properties[],
int properties_count,
void *usr_data);
```
---
``` c
/*
* 服务(对应设备产品物模型服务定义)调用的回调函数, 需要驱动开发者实现服务对应业务逻辑
*
* LinkEdge 需要调用某个设备的服务时, SDK 会调用该接口将具体的服务参数传递给应用程序, 开发者需要在本回调
* 函数里调用具体的服务, 并将服务返回值按照@device_data_t格式填充到output_data.
*
* @dev_handle: LinkEdge 需要调用服务的具体某个设备.
* @service_name: LinkEdge 需要调用的设备的具体某个服务名, 名称与设备产品物模型一致.
* @data: LinkEdge 需要调用的设备的具体某个服务参数, 参数与设备产品物模型保持一致.
* @data_count: LinkEdge 需要调用的设备的具体某个服务参数个数.
* @output_data: 开发者需要将服务调用的返回值, 按照设备产品物模型规定的服务格式返回到output中.
* @usr_data: 注册设备时, 用户传递的私有数据.
*
* 若获取成功则返回LE_SUCCESS, 失败则返回错误码(参考le_error.h错误码宏定义).
* */
typedef int (*call_service_callback)(device_handle_t dev_handle,
const char *service_name,
const leda_device_data_t data[],
int data_count,
leda_device_data_t output_data[],
void *usr_data);
```
---
``` c
/*
* 上报属性, 设备具有的属性在设备能力描述在设备产品物模型规定.
*
* 上报属性, 可以上报一个, 也可以多个一起上报.
*
* dev_handle: 设备在linkedge本地唯一标识.
* properties: @leda_device_data_t, 属性数组.
* properties_count: 本次上报属性个数.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*
*/
int leda_report_properties(device_handle_t dev_handle, const leda_device_data_t properties[], int properties_count);
```
---
``` c
/*
* 上报事件, 设备具有的事件上报能力在设备产品物模型有规定.
*
*
* dev_handle: 设备在linkedge本地唯一标识.
* event_name: 事件名称.
* data: @leda_device_data_t, 事件参数数组.
* data_count: 事件参数数组长度.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*
*/
int leda_report_event(device_handle_t dev_handle, const char *event_name, const leda_device_data_t data[], int data_count);
```
---
``` c
/*
* 上线设备, 设备只有上线后, 才能被 LinkEdge 识别.
*
* dev_handle: 设备在linkedge本地唯一标识.
*
* 阻塞接口,成功返回LE_SUCCESS, 失败返回错误码.
*/
int leda_online(device_handle_t dev_handle);
```
---
``` c
/*
* 下线设备, 假如设备工作在不正常的状态或设备退出前, 可以先下线设备, 这样LinkEdge就不会继续下发消息到设备侧.
*
* dev_handle: 设备在linkedge本地唯一标识.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*
*/
int leda_offline(device_handle_t dev_handle);
```
---
``` c
/*
* 通过已在阿里云物联网平台创建的设备device_name, 注册并上线设备, 申请设备唯一标识符.
*
* 若需要注册多个设备, 则多次调用该接口即可.
*
* product_key: 在阿里云物联网平台创建的产品pk.
* device_name: 在阿里云物联网平台创建的dn.
* device_cb: 请求调用设备回调函数结构体,详细描述见@leda_device_callback.
* usr_data: 设备注册时传入私有数据, 在回调中会传给设备.
*
* 阻塞接口, 返回值设备在linkedge本地唯一标识, >= 0表示有效, < 0 表示无效.
*
*/
device_handle_t leda_register_and_online_by_device_name(const char *product_key, const char *device_name, leda_device_callback_t *device_cb, void *usr_data);
```
---
``` c
/*
* 通过本地自定义设备名称, 注册并上线设备, 申请设备唯一标识符.
*
* 若需要注册多个设备, 则多次调用该接口即可.
*
* product_key: 在阿里云物联网平台创建的产品pk.
* local_name: 由设备特征值组成的唯一描述信息, 必须保证同一个product_key时,每个设备名称不同.
* device_cb: 请求调用设备回调函数结构体,详细描述见@leda_device_callback.
* usr_data: 设备注册时传入私有数据, 在回调中会传给设备.
*
* 阻塞接口, 返回值设备在linkedge本地唯一标识, >= 0表示有效, < 0 表示无效.
*
* 注: 在同一pk条件设备注册, 不允许本接口和leda_register_and_online_by_device_name接口同时使用,
* 即每一个pk设备注册必须使用同一接口, 否则设备注册会发生不可控行为.
*/
device_handle_t leda_register_and_online_by_local_name(const char *product_key, const char *local_name, leda_device_callback_t *device_cb, void *usr_data);
```
---
``` c
/*
* 驱动模块初始化, 模块内部会创建工作线程池, 异步执行阿里云物联网平台下发的设备操作请求, 工作线程数目通过worker_thread_nums配置.
*
* worker_thread_nums : 线程池工作线程数, 该数值根据注册设备数量设置.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*/
int leda_init(int worker_thread_nums);
```
---
``` c
/*
* 驱动模块退出.
*
* 模块退出前, 释放资源.
*
* 阻塞接口.
*/
void leda_exit(void);
```
---
``` c
/*
* 获取驱动信息长度.
*
* 阻塞接口, 成功返回驱动信息长度, 失败返回0.
*/
int leda_get_driver_info_size(void);
```
---
``` c
/*
* 获取驱动信息(在物联网平台配置的驱动配置).
*
* driver_info: 驱动信息, 需要提前申请好内存传入.
* size: 驱动信息长度, leda_get_driver_info_size, 如果传入driver_info比实际配置内容长度短, 会返回LE_ERROR_INVAILD_PARAM.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*
* 配置格式:
{
"json":{
"ip":"127.0.0.1",
"port":54321
},
"kv":[
{
"key":"ip",
"value":"127.0.0.1",
"note":"ip地址"
},
{
"key":"port",
"value":"54321",
"note":"port端口"
}
],
"fileList":[
{
"path":"device_config.json"
}
]
}
*/
int leda_get_driver_info(char *driver_info, int size);
```
---
``` c
/*
* 获取设备信息长度.
*
* 阻塞接口, 成功返回设备信息长度, 失败返回0.
*/
int leda_get_device_info_size(void);
```
---
``` c
/*
* 获取设备信息(在物联网平台配置的设备配置).
*
* device_info: 设备信息, 需要提前申请好内存传入.
* size: 设备信息长度, 该长度通过leda_get_device_info_size接口获取, 如果传入device_info比实际配置内容长度短, 会返回LE_ERROR_INVAILD_PARAM.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*
* 配置格式:
[
{
"custom":{
"port":12345,
"ip":"127.0.0.1"
},
"deviceName":"device1",
"productKey":"a1ccxxeypky"
}
]
*/
int leda_get_device_info(char *device_info, int size);
```
---
``` c
/*
* 获取驱动配置信息长度.
*
* 阻塞接口, 成功返回config长度, 失败返回0.
*/
int leda_get_config_size(void);
```
---
``` c
/*
* 获取驱动配置信息.
*
* config: 配置信息, 需要提前申请好内存传入.
* size: config长度, 该长度通过leda_get_config_size接口获取, 如果传入config比实际配置内容长度短, 会返回LE_ERROR_INVAILD_PARAM.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*/
int leda_get_config(char *config, int size);
```
---
``` c
/*
* 驱动配置变更回调接口.
*
* config: 配置信息.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*/
typedef int (*config_changed_callback)(const char *config);
```
---
``` c
/*
* 订阅驱动配置变更监听回调.
*
* config_cb: 配置变更通知回调接口.
*
* 阻塞接口, 成功返回LE_SUCCESS,失败返回错误码.
*/
int leda_register_config_changed_callback(config_changed_callback config_cb);
```
---
``` c
/*
* 获取指定产品ProductKey对应物模型内容长度.
*
* product_key: 产品ProductKey.
*
* 阻塞接口, 成功返回product_key对应物模型内容长度, 失败返回0.
*/
int leda_get_tsl_size(const char *product_key);
```
---
``` c
/*
* 获取指定产品ProductKey对应物模型内容.
*
* product_key: 产品ProductKey.
* tsl: 物模型内容, 需要提前申请好内存传入.
* size: 物模型内容长度, 该长度通过leda_get_tsl_size接口获取, 如果传入tsl比实际物模型内容长度短, 会返回LE_ERROR_INVAILD_PARAM.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*/
int leda_get_tsl(const char *product_key, char *tsl, int size);
```
---
``` c
/*
* 获取指定产品ProductKey对应物模型扩展信息内容长度.
*
* product_key: 产品ProductKey.
*
* 阻塞接口, 成功返回product_key对应物模型扩展信息内容长度, 失败返回0.
*/
int leda_get_tsl_ext_info_size(const char *product_key);
```
---
``` c
/*
* 获取指定产品ProductKey对应物模型扩展信息内容.
*
* product_key: 产品ProductKey.
* tsl_ext_info: 物模型扩展信息, 需要提前申请好内存传入.
* size: 物模型扩展信息长度, 该长度通过leda_get_tsl_ext_info_size接口获取, 如果传入tsl_ext_info比实际物模型扩展信息内容长度短, 会返回LE_ERROR_INVAILD_PARAM.
*
* 阻塞接口, 成功返回LE_SUCCESS, 失败返回错误码.
*/
int leda_get_tsl_ext_info(const char *product_key, char *tsl_ext_info, int size);
```
---
``` c
/*
* 获取设备句柄.
*
* product_key: 产品pk.
* device_name: 设备名称.
*
* 阻塞接口, 成功返回device_handle_t, 失败返回小于0数值.
*/
device_handle_t leda_get_device_handle(const char *product_key, const char *device_name);
```