Driver encoding

Updated at:

This topic describes how to encode a driver by following the IoT Edge encoding specifications and procedures.

Driver and device configuration

Before you encode a driver, you must understand the device and driver configuration for Link IoT Edge.

Driver configuration

You can configure the driver on the Alibaba Cloud IoT Platform. When you deploy an edge instance, the driver configuration is deployed to the edge gateway. The configuration is stored in JSON format in the Link IoT Edge configuration center and can be retrieved by calling the leda_get_driver_info API.

The driver can be configured in the following three formats:
  • Key-value pair configuration
    {
       "kv":[
            {
                "key":"ip",
                "value":"127.0.0.1",
                "note":"IP address"
            },
            {
                "key":"port",
                "value":"54321",
                "note":"port"
            }
        ]
    }
    The following table describes the parameters.
    Parameter NameDescription
    kvThe driver configuration is in key-value pair format.
    keyThe key name.
    valueThe value.
    noteThe comment for the key-value pair.
  • JSON format
    {
        "json":{
            "ip":"127.0.0.1",
            "port":54321
        }
    }
    The following table describes the parameters.
    ParameterDescription
    jsonThe driver configuration is in JSON format. The content is custom.
  • Configuration file
    {
        "fileList":[
            {
                "path":"device_config.json"
            }
        ]
    }
    The following table describes the parameters.
    ParameterDescription
    fileListThe driver configuration is a list of configuration files.
    pathThe path of the configuration file. The file is in the current directory of the driver.
Device configuration

You can configure the device in the Alibaba Cloud IoT Platform console. When you deploy an edge instance, the device configuration is deployed to the edge gateway. The configuration is stored in JSON format and can be retrieved by calling the leda_get_device_info API.

The device is configured in the following format:
{
    "deviceList": [{
        "custom": {
             "ip":"127.0.0.1", 
             "port":22322
        }, // Custom device configuration
        "productKey": "xxxxxxxxxxx", // The ProductKey of the product, generated when the product is created.
        "deviceName": "demo_led",    // The DeviceName of the device, set when the device is created.
    }]
}
The following table describes the device configuration parameters.
ConfigurationConfiguration Description
deviceListA list of all devices that are configured for the current driver.
customCustom device configuration.
productKeyThe unique identifier of the product to which the device belongs.
deviceNameThe device name.

Procedure

  1. Call the leda_init API to initialize the driver resources.
    int main(int argc, char** argv)
    {
        ...
    
        /* Initialize the 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. Parse the driver configuration and bring the device online. Call the leda_get_driver_info API to retrieve the driver configuration. Parse the device connection information and connect to the device. After the device is connected, call the leda_get_device_info API to retrieve and parse the device configuration. Validate the device features based on the parsed information. After validation, call the leda_register_and_online_by_device_name API to register the device and bring it online on the Alibaba Cloud IoT Platform.
    For more information about the driver configuration format, see Driver and device configuration.
    static int online_devices()
    {
      ...
    
        /* Get the driver and device configurations. */
        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;
            }
        }
    
        /* Parse the driver and device configurations. */
        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)
            {
                /* Parse the configuration content. */
                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));
                }
    
                /* Register the device and bring it online. */
                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. Transform the received device data into the Alibaba Cloud IoT Thing Specification Language (TSL) model format and report the data to IoT Platform. Call the leda_report_properties API to report device property data and the leda_report_event API to report device events.
    Note This example uses a virtual device and directly constructs data in the TSL model format for reporting.
    /* Report data. */
    while (1)
    {
        /* Report properties. */
        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);
    
        /* Report events. */
        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. Process service requests from the cloud using the following three callback functions.
    • get API: Processes requests to retrieve device properties.
    • set API: Processes requests to set device properties.
    • service API: Processes requests to call custom device methods.
    Note This example uses the get_properties_callback_cb, set_properties_callback_cb, and call_service_callback_cb callback functions to implement service requests.
    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;
    }
Note For the complete source code of this example, see the LED device driver in the GitHub repository.

This completes the driver encoding procedure.