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
/*
* RGB LED pin definitions
*/
#define LED3_R 12
#define LED3_G 14
#define LED3_B 15Operation Steps
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

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}.

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);
}
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:

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.
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

