本章主要描述,在驱动开发中如何进行驱动编码。

驱动与设备信息配置

进行驱动编码前,需要了解Link IoT Edge的设备信息配置和驱动信息配置相关内容。

驱动信息配置

驱动信息配置在阿里云物联网平台进行配置。部署边缘实例时,驱动配置信息会被部署到边缘网关,其内容以json格式存储在Link IoT Edge配置中心,可以通过leda_get_driver_info接口获取。

驱动信息配置有如下三种配置格式:
  • 键值对配置
    {
       "kv":[
            {
                "key":"ip",
                "value":"127.0.0.1",
                "note":"ip地址"
            },
            {
                "key":"port",
                "value":"54321",
                "note":"port端口"
            }
        ]
    }
    格式参数说明如下:
    参数名称 说明
    kv 驱动配置的格式为键值对配置。
    key 键名称。
    value 值内容。
    note 键值注释。
  • JSON格式
    {
        "json":{
            "ip":"127.0.0.1",
            "port":54321
        }
    }
    格式参数说明如下:
    参数名称 说明
    json 驱动配置的格式为JSON格式配置。配置内容为自定义内容。
  • 配置文件
    {
        "fileList":[
            {
                "path":"device_config.json"
            }
        ]
    }
    格式参数说明如下:
    参数名称 说明
    fileList 驱动配置格式为配置文件列表。
    path 配置文件路径。配置文件在驱动当前目录中。
设备信息配置

设备信息配置在阿里云物联网平台控制台配置。部署边缘实例时,设备信息配置会被部署到边缘网关,其内容以json格式存储,可以通过leda_get_device_info接口获取。

设备信息配置格式定义:
{
    "deviceList": [{
        "custom": {
             "ip":"127.0.0.1", 
             "port":22322
        }, // 设备自定义配置
        "productKey": "xxxxxxxxxxx", // 产品ProductKey,在创建产品时生成
        "deviceName": "demo_led",    // 设备DeviceName,在创建设备时生成
    }]
}
设备信息配置参数说明:
配置名称 配置解释
deviceList 当前驱动下所有已进行设备配置的设备列表。
custom 设备自定义配置。
productKey 设备所在产品唯一标识符。
deviceName 设备名称。

操作步骤

  1. 初始化驱动资源。调用leda_init接口完成资源初始化。
    int main(int argc, char** argv)
    {
        ...
    
        /* init driver */
        if (LE_SUCCESS != (ret = leda_init(WORKER_THREAD_NUMS)))
        {
            log_e(TAG_NAME_LED_DRIVER, "leda_init failed\n");
            return ret;
        }
    
        ...
    
      return LE_SUCCESS;
    }
  2. 解析驱动配置,完成设备上线。通过leda_get_device_info_size接口和leda_get_device_info接口获取设备配置,按照驱动配置格式解析,根据解析后的驱动配置连接设备并调用leda_register_and_online_by_device_name接口完成设备注册上线到阿里云物联网平台
    驱动信息配置格式定义请参见本文上方驱动与设备信息配置内容。
    static int online_devices()
    {
      ...
    
        /* 获取驱动设备配置 */
        size = leda_get_device_info_size();
        if (size >0)
        {
            device_config = (char*)malloc(size);
            if (NULL == device_config)
            {
                log_e(TAG_DEMO_LED, "allocate memory failed\n");
                return LE_ERROR_INVAILD_PARAM;
            }
    
            if (LE_SUCCESS != (ret = leda_get_device_info(device_config, size)))
            {
                log_e(TAG_DEMO_LED, "get device config failed\n");
                return ret;
            }
        }
    
        /* 解析驱动设备配置 */
        devices = cJSON_Parse(device_config);
        if (NULL == devices)
        {
            log_e(TAG_DEMO_LED, "device config parser failed\n");
            return LE_ERROR_INVAILD_PARAM;
        }
    
        cJSON_ArrayForEach(item, devices)
        {
            if (cJSON_Object == item->type)
            {
                /* 解析配置内容 */
                result      = cJSON_GetObjectItem(item, "productKey");
                productKey  = result->valuestring;
    
                result      = cJSON_GetObjectItem(item, "deviceName");
                deviceName  = result->valuestring;
    
                result      = cJSON_GetObjectItem(item, "custom");
                if (NULL != result)
                {
                    log_i(TAG_DEMO_LED, "custom content: %s\n", cJSON_Print(result));
                }
    
                /* 注册并上线设备 */
                device_cb.get_properties_cb            = get_properties_callback_cb;
                device_cb.set_properties_cb            = set_properties_callback_cb;
                device_cb.call_service_cb              = call_service_callback_cb;
                device_cb.service_output_max_count     = 5;
    
                dev_handle = leda_register_and_online_by_device_name(productKey, deviceName, &device_cb, NULL);
                if (dev_handle < 0)
                {
                    log_e(TAG_DEMO_LED, "product:%s device:%s register failed\n", productKey, deviceName);
                    continue;
                }
    
                g_dev_handle = dev_handle;
                log_i(TAG_DEMO_LED, "product:%s device:%s register success\n", productKey, deviceName);
            }
        }
    
      ...
    
        return LE_SUCCESS;
    }
  3. 将收到的设备数据转换为阿里云IoT物模型格式并上报到物联网平台,调用leda_report_properties接口上报设备属性数据,调用leda_report_event接口上报设备事件。
    说明 此处使用虚拟设备,直接构造物模型格式的数据进行上报。
    /* 上报数据 */
    while (1)
    {
        /* 上报属性 */
        leda_device_data_t dev_proper_data[1] = 
        {
            {
                .type  = LEDA_TYPE_INT,
                .key   = {"temperature"},
                .value = {0}
            }
        };
        sprintf(dev_proper_data[0].value, "%d", g_dev_temperature);
        leda_report_properties(g_dev_handle, dev_proper_data, 1);
    
        /* 上报事件 */
        if (g_dev_temperature > 50)
        {
            leda_device_data_t dev_event_data[1] = 
            {
                {
                    .type  = LEDA_TYPE_INT,
                    .key   = {"temperature"},
                    .value = {0}
                }
            };
            sprintf(dev_event_data[0].value, "%d", g_dev_temperature);
            leda_report_event(g_dev_handle, "high_temperature", dev_event_data, 1);
        }
    
        sleep(5);
    }
  4. 处理云端服务请求。实现服务请求的三个回调函数如下所示。
    • get接口: 处理获取设备属性的请求。
    • set接口: 处理设置设备属性的请求。
    • service接口:处理调用设备自定义方法的请求。
    说明 本示例使用get_properties_callback_cbset_properties_callback_cbcall_service_callback_cb三个回调函数实现服务请求。
    static int get_properties_callback_cb(device_handle_t device_handle, 
                                   leda_device_data_t properties[], 
                                   int properties_count, 
                                   void *usr_data)
    {
        ...
    
        return ret;
    }
    
    static int set_properties_callback_cb(device_handle_t device_handle, 
                                   const leda_device_data_t properties[], 
                                   int properties_count, 
                                   void *usr_data)
    {
        ...
    
        return ret;
    }
    
    static int call_service_callback_cb(device_handle_t device_handle, 
                                   const char *service_name, 
                                   const leda_device_data_t data[], 
                                   int data_count, 
                                   leda_device_data_t output_data[], 
                                   void *usr_data)
    {
        ...
    
        return ret;
    }
说明 本示例的完整工程源码请参见Github源码库LED设备驱动

至此,您已完成驱动编码过程。