Skip to content

Contributed by wxlinus, curated by Ai-Thinker

CLion Dev (2): Connecting the M61 Board to Alibaba Cloud IoT

With the previous content we can already connect to the Alibaba Cloud IoT Platform. Now let's learn how to use the thing model feature of the Alibaba Cloud IoT Platform. The thing model is the data model defined by the Alibaba Cloud IoT Platform for a product, used to describe the product's functions.

For details on adding and creating thing model content, refer to the official documentation: Defining thing model properties, events and services - IoT Platform - Alibaba Cloud Help Center (aliyun.com) Below we'll talk about how to use the thing model to light the LED on the M61 board.

LED definition

c
/*
* RGB LED pin definitions
*/
#define LED3_R 12
#define LED3_G 14
#define LED3_B 15

Operation Steps

1
Create the related thing model on the Alibaba Cloud IoT Platform

Log in to the Alibaba Cloud IoT Platform console and define the product features (properties, events and services) on the Thing Model tab of the product details page, then publish them.

Alink JSON data format and topics for thing model properties, events and services

2
Device-side development

Thing model property reporting: the cloud changes the device state based on the reported data (commented out for now, because a high reporting frequency prints too many logs and makes debugging difficult).

The reported data corresponds to the matching thing model property on the cloud. For example, LightSwitch changes the thing model data with that identifier to 0: {"LightSwitch": 0}.

3
Write the property-setting parsing code

The cloud sends property-setting commands to the device by calling SetDeviceProperty / SetDevicesProperty. The related parsing code mainly checks for messages received from the cloud, parses them, and turns the LED on or off:

static void rgb_led_dm_set(char *data) {
    if (data == NULL) {
        LOG_E("data is no's json");
    }
    cJSON *root = cJSON_Parse(data);
    if (root == NULL) {
        LOG_E("root is null");
    }
    cJSON *led_r = cJSON_GetObjectItem(root, "LED_R");
    if (led_r != NULL) {
        if (led_r->valueint == 0) {
            led_off(LED3_R);
        } else {
            led_on(LED3_R);
        }
    }
    cJSON *led_g = cJSON_GetObjectItem(root, "LED_G");
    if (led_g != NULL) {
        if (led_g->valueint == 0) {
            led_off(LED3_G);
        } else {
            led_on(LED3_G);
        }
    }
    cJSON *led_b = cJSON_GetObjectItem(root, "LED_B");
    if (led_b != NULL) {
        if (led_b->valueint == 0) {
            led_off(LED3_B);
        } else {
            led_on(LED3_B);
        }
    }
    cJSON_Delete(root);
}
4
Verifying the state

Open the debug page in the cloud and set a property:

You can see the device received the corresponding message, and the LED on the board lights up too:

5
Summary and initialization code

The thing model has many more features, such as collecting temperature and humidity sensor data and reporting it to the cloud; they are all similar, just create the corresponding thing models. Based on the thing model we can also do data forwarding, data storage, cloud product forwarding and web visualization.

The device-side thing model function callbacks are implemented by the following function (this time it’s the property-setting function: it receives data, parses it, determines the corresponding state, and then turns the LED on or off). The thing model APIs are integrated into linksdk as a component:

The initialization code mainly involves the functions starting with dm in the MQTT initialization; the complete code is shown below.

c
uint8_t user_mqtt_init(void) {
    int32_t res = STATE_SUCCESS;
    //security credential struct; if TLS is used, configure parameters such as the CA certificate in this struct
    aiot_sysdep_network_cred_t cred;
    uint8_t protocol_version = 0;
    //configure the SDK's underlying dependencies
    aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
    //configure the SDK's log output
    aiot_state_set_logcb(demo_state_logcb);
    //create the SDK's security credential for establishing a TLS connection
    memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t));
    //use the RSA certificate to verify the MQTT server
    cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA;
    //maximum fragment length is 16K; other options are 4K, 2K, 1K, 0.5K
    cred.max_tls_fragment = 16384;
    //when establishing a TLS connection, support Server Name Indicator
    cred.sni_enabled = 1;
    //the RSA root certificate used to verify the MQTT server
    cred.x509_server_cert = ali_ca_cert;
    //the length of the RSA root certificate used to verify the MQTT server
    cred.x509_server_cert_len = strlen(ali_ca_cert);
    //create an MQTT client instance and initialize default parameters internally
    mqtt_handle = aiot_mqtt_init();
    if (mqtt_handle == NULL) {
        LOG_E("aiot_mqtt_init failed\n");
        return -1;
    }
    // configure the MQTT protocol version
    protocol_version = AIOT_MQTT_VERSION_5_0;
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_VERSION, (void *) &protocol_version);
    // configure the MQTT server address
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *) mqtt_host);
    // configure the MQTT server port
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *) &port);
    // configure the device productKey
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY, (void *) product_key);
    // configure the device deviceName
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME, (void *) device_name);
    // configure the device deviceSecret
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET, (void *) device_secret);
    // configure the security credential for the network connection, already created above
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *) &cred);
    // configure the MQTT default message receive callback
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_RECV_HANDLER, (void *) demo_mqtt_default_recv_handler);
    // configure the MQTT event callback
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER, (void *) demo_mqtt_event_handler);
    // to use the MQTT 5.0 assigned clientId feature, set use_assigned_clientid to 1
    uint8_t use_assigned_clientid = 0;
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_ASSIGNED_CLIENTID, (void *) (&use_assigned_clientid));
    //initialize the thing model
    user_dm_init();
    // create the connection property set and add user properties
    mqtt_properties_t *conn_props = aiot_mqtt_props_init();
    mqtt_property_t user_prop = {
        .id = MQTT_PROP_ID_USER_PROPERTY,
        .value.str_pair.key.len = strlen("demo_key"),
        .value.str_pair.key.value = (uint8_t *) "demo_key",
        .value.str_pair.value.len = strlen("demo_value"),
        .value.str_pair.value.value = (uint8_t *) "demo_value",
    };
    aiot_mqtt_props_add(conn_props, &user_prop);
    // connect to the server using MQTT 5.0
    res = aiot_mqtt_connect_v5(mqtt_handle, NULL, NULL);
    aiot_mqtt_props_deinit(&conn_props);
    if (res < STATE_SUCCESS) {
        //connection attempt failed; destroy the MQTT instance and reclaim resources
        aiot_dm_deinit(&dm_handle);
        aiot_mqtt_deinit(&mqtt_handle);
        LOG_E("aiot_mqtt_connect failed: -0x%04X\n\r\n", -res);
        LOG_E("please check variables like mqtt_host, produt_key, device_name, device_secret in demo\r\n");
        return -1;
    }

//create a separate task to run aiot_mqtt_process; it automatically sends heartbeat keep-alive and resends unacknowledged QoS1 messages
g_mqtt_process_task_running = 1;
xTaskCreate(demo_mqtt_process_task, "aiot_mqtt_process", 1024 * 2, NULL, 3, g_mqtt_process_task);

// create a separate task to run aiot_mqtt_recv; it loops receiving MQTT messages from the server and automatically reconnects on disconnection
g_mqtt_recv_task_running = 1;
xTaskCreate(demo_mqtt_recv_task, "aiot_mqtt_recv", 1024 * 2, NULL, 3, g_mqtt_recv_task);
//notify that the MQTT connection succeeded
user_state_send_notify(STATE_MQTT_CONNECTED_OK, 0);
return 0;
}

The related code is already on Gitee: m61sdk: Ai-Thinker m61 module SDK porting project (gitee.com)

Have questions?

For other questions, please visit the unified discussion area: Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23