This topic describes how to integrate a Link SDK into a TCP-based wide area network (WAN) module.

Note In this topic, the sample code is written based on Link SDK v3.0.1.

Link SDKs of IoT Platform are used to connect devices to IoT Platform, verify devices, and enable data communication. When you integrate a Link SDK into a communication module, you can obtain the following benefits:

  • A device manufacturer can run only the AT commands of a module on a device to connect the device to IoT Platform without the need to focus on how the microcontroller unit (MCU) of the device establish the connection to IoT Platform. The workloads of the MCU remain unchanged.
  • The Alibaba Cloud Partner Network page displays certified module models, buy links, and development guides. If you are a device manufacturer or service provider, you can use certified communication modules to connect your devices to IoT Platform.
The following figure shows the process of connecting a device that contains a communication module into which a Link SDK is integrated to IoT Platform.iot

The following section describes the process of configuring a device as a device manufacturer.

  • Purchase a module into which a Link SDK is integrated.
  • Run AT commands on the MCU to connect the device to IoT Platform, and send data to or receive data from IoT Platform.
  • Deploy a cloud service in the IoT Platform to manage the device.

A module provider must perform the following steps on a module:

  • Integrate a Link SDK into the module as expected.
  • Provide the AT commands that the MCU can run to connect the device to IoT Platform.

The following section describes how to integrate the MQTT feature of a Link SDK into a module. If a module provider integrates more features of a Link SDK, a device manufacturer develops less features. We recommend that module providers integrate as many features of a Link SDK as they can, such as over-the-air (OTA)-related features and Thing Specification Language (TSL) model-related features.

Operations in the IoT Platform console

To check whether a Link SDK that is integrated into a module works as expected, you must connect a test device to IoT Platform. You must create a product in the IoT Platform console and then create a device in the product to obtain the identity information about the device.

  1. Log on to the IoT Platform console. If you log on to the console as a module provider, you must create an Alibaba Cloud account. You can create an Alibaba Cloud account free of charge.
  2. After you log on to the IoT Platform, follow the steps that are described in the Create a product topic to create a product. On the product details page, you can obtain the ProductKey and ProductSecret of the product.
  3. Create a test device. On the device details page, you can obtain the DeviceName and DeviceSecret of the device.

Process of integrating a Link SDK

When a module provider integrates a Link SDK into a module, the process includes multiple stages, as shown in the following figure.

debug

Configure a Link SDK and extract the code

Configure the Link SDK

A Link SDK provides a large number of features. The following section describes how to configure the features that are required in this example.

Run a configuration command

  • Linux

    Go to the root directory of the Link SDK and run the following command:

    make menuconfig
                
  • Windows

    Go to the root directory of the Link SDK and run the following command:

    config.bat

Use one of the preceding methods to start the configuration tool of the Link SDK. The following figure shows the GUI of the tool.

Enable the required features

On the GUI, press the Space key to select or clear a feature and press the Up Arrow or Down Arrow key on the keypad to switch between different options. If you want to obtain the information about an option, press an arrow key to move the cursor to the option and press the H key. In this case, the information that indicates the purpose of the option and the system actions that are performed after you select or clear the option is displayed.

  • If the compilation environment includes the stdint.h header file, select the following option.

    PLATFORM_HAS_STDINT

  • If an embedded operating system runs in your environment, select the following option.

    PLATFORM_HAS_OS

  • If a module supports TCP instead of Message Queuing Telemetry Transport (MQTT), you must enable the following options:
    • FEATURE_MQTT_COMM_ENABLED: provides the MQTT API of the Alibaba SDK to enable communication between devices and IoT Platform.
    • FEATURE_MQTT_DEFAULT_IMPL: provides the MQTT Client implementation predefined in the Alibaba SDK. You must write code to create and establish TCP connections, and deliver data over the TCP connections based on the MQTT Client implementation.
    • FEATURE_MQTT_DIRECT: provides IoT Platform endpoints to which devices can connect.

We recommend that you select the FEATURE_SUPPORT_TLS option. You can select the option to encrypt data that is transmitted between devices and IoT Platform. In this example, this option is not selected to reduce configuration workloads.

You do not need to enable other features.

Extract the source code of the selected features

In the root directory of the Link SDK, run the extract.sh file or run the extract.bat file if you use Windows. The code of the selected features is copied to the output directory.

Integrate the code files of the Link SDK into the compilation environment

Copy the code files that you obtained in the previous step from the output directory to your project directory. Then, modify your compilation environment or development tool to integrate the code files into the compilation environment.

You must integrate the code files of the eng/dev_sign, eng/infra, eng/mqtt, and eng/wrappers directories.

Implement hardware abstraction layer (HAL) functions

Link SDKs are designed to run in different operating systems or on MCUs that do not support operating systems. Operations that are related to operating systems are defined as HAL functions that must be implemented. The OS varies based on the communication module. TCP-related operations that you want to perform on a communication module are also defined as HAL functions that you must implement.

All HAL functions are stored in the output/eng/wrappers/wrapper.c file.

OS-related HAL functions

The following table describes the HAL functions that you must implement.

** **FunctionDescription
1HAL_MallocOccupies a block of available memory and returns the start address of the block based on the specified memory length. The function corresponds to the malloc() function in the C standard library.
2HAL_FreeReleases a block of memory space that is indicated by the specified pointer. The function corresponds to the free() function in the C standard library.
3HAL_PrintfPrints text to a terminal based on the specified string format. The function corresponds to the printf() function in the C standard library. If a better debugging method is available in your debugging environment, you do not need to implement the function.
4HAL_SnprintfPrints text to a specified block of memory in the cache instead of a terminal. The function is similar to the printf() function.
5HAL_UptimeMsReturns a uint64_t value. The value indicates the number of milliseconds that elapsed between the current time and the time when the device was started.
6HAL_SleepMsHibernates for a period of time based on the specified number of milliseconds. For example, if you specify 10, the related program hibernates for 10 milliseconds.

The wrappers/os directory of the compressed SDK package includes examples on how to implement HAL functions. If specific examples meet the requirements of your operating system, you can use the examples. If no eligible examples exist, you must implement HAL functions based on your business scenario.

HAL functions that you can implement

If no operating system runs on the module or the MQTT API of the Link SDK is not called by multiple threads, you do not need to modify the definitions of the following functions in the wrapper.c file. If an operating system runs on the module and the MQTT API of the Link SDK is called by multiple threads, you must implement the following functions.

** **FunctionDescription
1HAL_MutexCreateCreates a mutex. The returned value can be sent to HAL_MutexLock/Unlock.
2HAL_MutexDestroyDeletes a mutex. The mutex is specified by a request parameter.
3HAL_MutexLockApplies for a mutex. If the mutex is being used by a thread, the function thread remains in hibernation. Otherwise, the application process continues.
4HAL_MutexUnlockRelease a mutex. The threads that hibernate to wait for the mutex obtain the mutex and continues the subsequent operations.
5HAL_SemaphoreCreateCreates a semaphore. The returned value can be sent to HAL_SemaphorePost/Wait.
6HAL_SemaphoreDestroyDeletes a semaphore. The semaphore is specified by a request parameter.
7HAL_SemaphorePostIncrements the value of a specified semaphore and cancels the wait operations of other threads.
8HAL_SemaphoreWaitIncrements the value of a specified semaphore and performs the wait operation.
9HAL_ThreadCreateCreates a thread based on the values that you specified for the request parameters.

TCP-related HAL functions

MQTT connections are established over TCP. A module provider must implement the following TCP-related HAL functions.

Sequence numberFunctionDescription
1HAL_TCP_EstablishEstablishes a TCP connection. The host request parameter specifies a domain name. You must convert the domain name to an IP address. The returned value is the socket number of the TCP connection.
2HAL_TCP_DestroyCloses a TCP connection. You must specify the returned value of the HAL_TCP_Establish function as the value of the request parameter of the HAL_TCP_Destroy function. If the HAL_TCP_Destroy function returns 0, the call is successful.
3HAL_TCP_WriteSends data over a TCP connection. A timeout period is defined for the function. The function returns a value regardless of whether the specified data is fully sent within the timeout period. If the TCP connection is closed when data is being sent, the function returns a negative number.
4HAL_TCP_ReadReads data within a specified period of time and returns the data. You can specify the maximum length of data that the function can read in a request parameter. If the length of data that the function has read over a TCP connection reaches the maximum length, the function returns the data.

Product-related HAL functions

The following HAL functions are called to obtain the identity verification information about a product. A device manufacturer must provide instructions on how to burn the identity information about a device to the device, obtain the information by using the following HAL functions, and then specify the information in the Link SDK.

Sequence numberFunctionDescription
1HAL_GetProductKeyObtains the ProductKey of a device. The ProductKey is used to identify the product model of the device.
2HAL_GetDeviceNameObtains the DeviceName of a device. The DeviceName is used to uniquely identify the device.
3HAL_GetDeviceSecretObtains the DeviceSecret of a device. The DeviceSecret is used to identify the key of the device.

When you configure a product in actual business scenarios, the preceding data items must be sent by AT commands of a device manufacturer to the module. When a module provider debugs a test device, the provider can obtain the ProductKey, DeviceName, and DeviceSecret of the test device by calling the preceding functions.

Implement product features based on the sample code

A module provider can debug features based on the eng/examples/mqtt_example.c file in the output directory. A device manufacturer can copy the file to its own project and modify the file to use a feature.

The sample code in the file is used to connect a device to IoT Platform, subscribe to a topic, and then send data to the topic. In this case, IoT Platform sends the data that is submitted by the device to the devices that subscribe to the topic. The following figure describes how the sample code works.

You must change the default permission on the topic from Subscribe to Publish and Subscribe in the IoT Platform console.

The sample code starts from the main() function. In the definition of the main() function, the product-related HAL functions are called to obtain the identity information about the product, as shown in the following code.

int main(int argc, char *argv[])
{
    void                   *pclient = NULL;
    int                     res = 0;
    int                     loop_cnt = 0;
    iotx_mqtt_param_t       mqtt_params;

    HAL_GetProductKey(DEMO_PRODUCT_KEY);
    HAL_GetDeviceName(DEMO_DEVICE_NAME);
    HAL_GetDeviceSecret(DEMO_DEVICE_SECRET);

    EXAMPLE_TRACE("mqtt example");
            

  • The preceding HAL functions that start with HAL_Get are called to obtain the certificate information about the device. A module provider can specify the certificate information about a test device.

The following code shows how to configure MQTT connection parameters based on your business requirements.

/* Initialize MQTT parameter */
    memset(&mqtt_params, 0x0, sizeof(mqtt_params));
    mqtt_params.port = sign_mqtt.port;
    mqtt_params.host = sign_mqtt.hostname;
    mqtt_params.client_id = sign_mqtt.clientid;
    mqtt_params.username = sign_mqtt.username;
    mqtt_params.password = sign_mqtt.password;
    mqtt_params.request_timeout_ms = 2000;
    mqtt_params.clean_session = 0;
    mqtt_params.keepalive_interval_ms = 60000;
    mqtt_params.read_buf_size = 1024;
    mqtt_params.write_buf_size = 1024;
    mqtt_params.handle_event.h_fp = example_event_handle;
    mqtt_params.handle_event.pcontext = NULL;
    pclient = IOT_MQTT_Construct(&mqtt_params);
            

Call the IOT_MQTT_Construct() function of the Link SDK to connect the device to IoT Platform. If the function returns a non-null value, the connection to IoT Platform is established. Then, call the example_subscribe function to subscribe to a topic.

res = example_subscribe(pclient);
            
The following figure shows the content of the example_subscribe function.

  • A device manufacturer must subscribe to a topic and implement a processing function based on the design of its products.
  • In the preceding sample code, the code in the first orange rectangle specifies that a topic is in the /$ProductKey/$DeviceName format. When you create a product in the IoT Platform console, the system automatically creates a topic in the preceding format.
  • The code in the second orange rectangle specifies the information about the topic.
  • The code in the second orange rectangle specifies how to subscribe to the topic and a function that is called to process the data that is received from the topic.

The following code shows how to use the publish feature of MQTT to submit business packets to IoT Platform.

 while (1) {
        if (0 == loop_cnt % 20) {
            example_publish(pclient);
        }

        IOT_MQTT_Yield(pclient, 200);

        loop_cnt += 1;
    }
            

  • The preceding sample code sends a fixed message to IoT Platform on a regular basis. We recommend that a device manufacturer submits only the required data to IoT Platform based on the features of its own products.
  • To prevent invalid data from being sent to IoT Platform on a regular basis, you can delete the example_publish(pclient) statement in the main() function.
  • The IOT_MQTT_Yield function of the Link SDK is called to receive data from an MQTT broker. The value 200 indicates that the function must wait for a period of 200 milliseconds before the function receives data. If you have a large number of messages or high requirements for latency, you can specify a smaller value.
The following figure shows the content of the example_publish function.

In the preceding figure, the code in the first orange rectangle specifies the content of the message that you want to send. The code in the second orange rectangle calls a function of the Link SDK to send the message to a specified topic.

Upload a module provider ID and module model

If a module provider wants to verify a module in IoT Platform, the module provider must submit the module provider ID and the model of the module. This way, IoT Platform can obtain the number of devices that are connected to IoT Platform by module provider ID or module model.

Before you integrate a Link SDK, contact Alibaba Cloud to obtain a module provider ID and module model based by sending a message based on the following template. For more information, visit Contact us.

Subject: Use a Link SDK to connect a device - Apply for module or chip model

After a module is connected to IoT Platform, copy the following code to your environment and run the function in the code to submit the information. The pid parameter specifies the ID of a module provider and the mid parameter specifies the ID of a module model.

#define PID_STRING_LEN_MAX          32  /* The maximum length of the value of the pid parameter. The value is a string.*/
#define MID_STRING_LEN_MAX          32  /* The maximum length of the value of the mid parameter. The value is a string.*/


int example_report_pid_mid(void *pclient, const char *product_key, const char *device_name, const char *pid, const char *mid)
{
    int res = 0;
    iotx_mqtt_topic_info_t topic_msg;

    const char topic_frag1[] = "/sys/";
    const char topic_frag2[] = "/thing/deviceinfo/update";
    char topic[sizeof(topic_frag1) + sizeof(topic_frag2) + IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN] = {0};

    const char payload_frag1[] = "{\"id\":\"0\",\"version\":\"1.0\",\"params\":[{\"attrKey\":\"SYS_MODULE_ID\",\"attrValue\":\"";
    const char payload_frag2[] = "\",\"domain\":\"SYSTEM\"},{\"attrKey\":\"SYS_PARTNER_ID\",\"attrValue\":\"";
    const char payload_frag3[] = "\",\"domain\":\"SYSTEM\"}],\"method\": \"thing.deviceinfo.update\"}";
    char payload[sizeof(payload_frag1) + sizeof(payload_frag2) + sizeof(payload_frag3) + PID_STRING_LEN_MAX + MID_STRING_LEN_MAX] = {0};

    if (strlen(pid) > PID_STRING_LEN_MAX || strlen(mid) > MID_STRING_LEN_MAX) {
        return -1;
    }

    /* Combine strings to create an MQTT topic. */
    memcpy(topic, topic_frag1, strlen(topic_frag1));
    memcpy(topic + strlen(topic), product_key, strlen(product_key));
    memcpy(topic + strlen(topic), "/", 1);
    memcpy(topic + strlen(topic), device_name, strlen(device_name));
    memcpy(topic + strlen(topic), topic_frag2, strlen(topic_frag2));

    /* Combine strings to create the payload of the MQTT topic. The payload includes the values of the pid and mid parameters. */
    memcpy(payload, payload_frag1, strlen(payload_frag1));
    memcpy(payload + strlen(payload), mid, strlen(mid));
    memcpy(payload + strlen(payload), payload_frag2, strlen(payload_frag2));
    memcpy(payload + strlen(payload), pid, strlen(pid));
    memcpy(payload + strlen(payload), payload_frag3, strlen(payload_frag3));

    topic_msg.qos = IOTX_MQTT_QOS0;
    topic_msg.retain = 0;
    topic_msg.dup = 0;
    topic_msg.payload = (void *)payload;
    topic_msg.payload_len = strlen(payload);

    /* Call the MQTT IOT_MQTT_Publish to send a message that include the values of the pid and mid parameters.*/
    res = IOT_MQTT_Publish(pclient, topic, &topic_msg);
    if (res < 0) {
        return -1;
    }

    return 0;
}

            

Debug features

The following screenshots are provided based on the result after you modify and run the mqtt_example.c file.

Check whether a device is connected to IoT Platform

By default, a device is granted the Subscribe permission on the /${productKey}/${deviceName}/get topic. To prevent messages from being dropped after the messages are sent to IoT Platform, we recommend that you change the permission on the topic to Subscribe and Publish. This way, the sample program can run as expected without failures.

The following figure shows the output after you run the sample code. The output is printed by the HAL_Printf function to a serial port. A program that is compiled from the sample code obtains the output and displays the output. The information in an orange rectangle indicates that the device is connected to IoT Platform.

Checks whether data is sent by a device to IoT Platform

Log on to the IoT Platform console with your Alibaba Cloud account, go to the details page of the device to check whether a message is received from the device, as shown in the following figure.

The preceding figure shows the topic to which a message is sent. The content of the message is not displayed.

Check whether data is received by a device from IoT Platform

On the Downstream Analysis tab, you can view the messages that are sent to the device, as shown in the following figure.
You can also check whether data is received from IoT Platform on the device side. The following figure shows the output after you run the sample code. The output indicates that data is received from IoT Platform.

Implement AT commands

A module provide does not provide a development environment that can be used to perform custom development on a module. Instead, the module provider connects an external MCU and the business logic of a product runs on the MCU. In this case, the module provider must provide AT commands that can be called by the MCU. In most cases, modules support only TCP. API operations that can be performed configure MQTT connections, establish connections, close connection, subscribe to messages, and publish messages must be provided.

The following table describes the recommended AT commands. A module provider can combine multiple AT commands into one AT command or split an AT command into multiple AT commands. A module provider can define a custom format for AT commands.

CommandDescription
Specify identity information for a deviceSpecify ProductKey, ProductSecret, DeviceName, and DeviceSecret for a device.
Specify IoT Platform endpointsIoT Platform is available in multiple regions, such as the Chinese mainland, US, and Japan. You can specify the information about an IoT Platform endpoint to which an MCU can connect.
Establish an MQTT connectionEstablish a connection to an Alibaba Cloud MQTT broker. You can run the AT command to specify an MQTT clean session, keepalive interval, and request timeout period.
Close an MQTT connectionClose an MQTT connection to IoT Platform.
Subscribe to a topicSubscribe to a topic to receive messages
Unsubscribe from a topicUnsubscribe from a topic to stop receiving messages
Send data to a topicSend data to a topic

When an MCU runs AT commands to send the identity information about a device to a module, we recommend that you specify the information as the values of global variables. This way, the HAL_GetProductKey, HAL_GetDeviceName, and HAL_GetDeviceSecret can return the global variables and you do no need to modify the sample code.