Cette rubrique explique comment appeler les opérations API du Link SDK for C pour connecter des appareils basés sur Message Queuing Telemetry Transport (MQTT) 5.0 à IoT Platform et activer la messagerie. Cet exemple utilise le fichier de code d'exemple ./demos/mqtt_v5_basic_demo.c.
Informations générales
Pour plus d'informations sur les connexions d'appareils via MQTT 5.0, consultez la rubrique Vue d'ensemble.
Étape 1 : Initialiser le SDK
-
Ajoutez les fichiers d'en-tête.
#include "aiot_state_api.h" #include "aiot_sysdep_api.h" #include "aiot_mqtt_api.h" -
Ajoutez la dépendance sous-jacente et configurez la sortie des journaux.
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb); -
Appelez l'opération aiot_mqtt_init pour créer une instance de client MQTT et initialiser les paramètres par défaut.
mqtt_handle = aiot_mqtt_init(); if (mqtt_handle == NULL) { printf("aiot_mqtt_init failed\n"); return -1; }
Étape 2 : Configurer les fonctionnalités requises
Appelez l'opération aiot_mqtt_setopt pour configurer les éléments suivants. Pour plus d'informations sur les paramètres de cette opération, consultez aiot_mqtt_option_t.
-
Configurez les paramètres de connexion.
-
Exemple de code :
char *product_key = "a18wP******"; char *device_name = "LightSwitch"; char *device_secret = "uwMTmVAMnGGHaAkqmeDY6cHxxB******"; char *mqtt_host = "iot-06z00ax1o******.mqtt.iothub.aliyuncs.com"; ... ... /* Specify the version of MQTT. */ protocol_version = AIOT_MQTT_VERSION_5_0; aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_VERSION, (void *)&protocol_version); /* Specify the endpoint of the MQTT broker. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *)url); /* Specify the port of the MQTT broker. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *)&port); /* Specify the ProductKey of the product to which the device belongs. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY, (void *)product_key); /* Specify the DeviceName of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME, (void *)device_name); /* Specify the DeviceSecret of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET, (void *)device_secret); /* Specify the security credential of the connection. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred); /* If you want to use the Assigned Client Identifier feature of MQTT 5.0, set the use_assigned_clientid parameter to 1.*/ uint8_t use_assigned_clientid = 0; aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_ASSIGNED_CLIENTID, (void *)(&use_assigned_clientid)); -
Paramètres :
Paramètre
Exemple
Description
mqtt_host
iot-06z00ax1o.mqtt.iothub.aliyuncs.com
Endpoint auquel connecter l'appareil.
Pour consulter l'endpoint d'une instance Enterprise Edition ou d'une instance publique de la nouvelle version, accédez au panneau Development Configurations de la page Instance Details dans la console IoT Platform.
Si vous utilisez une instance publique de la version précédente, l'endpoint suit le format
${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com.
Pour plus d'informations sur les instances publiques (nouvelle et ancienne versions), les instances Enterprise Edition et les endpoints, consultez Consulter l'endpoint d'une instance.
product_key
a18wP
Informations d'authentification de l'appareil. Pour plus d'informations, consultez Obtenir les informations d'authentification de l'appareil.
Cet exemple utilise la méthode d'authentification par certificat unique par appareil.
device_name
LightSwitch
device_secret
uwMTmVAMnGGHaAkqmeDY6cHxxB
protocol_version
AIOT_MQTT_VERSION_5_0
Spécifiez 5.0 comme version MQTT.
use_assigned_clientid
1
Pour utiliser la fonctionnalité
Assigned Client Identifierde MQTT 5.0, définissez le paramètreuse_assigned_clientidsur 1. -
Description du mécanisme keep-alive MQTT :
ImportantPendant une période keep-alive, l'appareil doit envoyer au moins un message, y compris les requêtes ping.
Un minuteur démarre lorsque IoT Platform envoie un message CONNACK en réponse à un message CONNECT. Ce minuteur se réinitialise à la réception d'un message PUBLISH, SUBSCRIBE, PING ou PUBACK. IoT Platform vérifie le heartbeat de la connexion MQTT toutes les 30 secondes. Le temps d'attente correspond à l'intervalle entre la connexion de l'appareil à IoT Platform et la prochaine vérification du heartbeat. Le délai d'expiration maximal se calcule selon la formule suivante : Intervalle de heartbeat × 1,5 + Temps d'attente de la vérification. Si le serveur ne reçoit aucun message de l'appareil pendant ce délai maximal, il met fin à la connexion.
Le Link SDK for C intègre le mécanisme keep-alive. Le tableau ci-dessous présente le paramètre permettant de personnaliser les valeurs liées au heartbeat pour les connexions des appareils. À défaut, les valeurs par défaut s'appliquent.
Élément
Valeur par défaut
Description
AIOT_MQTTOPT_HEARTBEAT_MAX_LOST
2
Nombre maximal de heartbeats pouvant être perdus. Au-delà de cette limite, le système établit une nouvelle connexion.
AIOT_MQTTOPT_HEARTBEAT_INTERVAL_MS
25 000
Intervalle entre une déconnexion et l'établissement d'une nouvelle connexion par le système. Valeurs valides : 1 000 à 1 200 000. Unité : millisecondes.
AIOT_MQTTOPT_KEEPALIVE_SEC
1 200
Période keep-alive. Après la perte du heartbeat, le système peut établir une nouvelle connexion dans un délai spécifié. Valeurs valides : 30 à 1 200. Unité : secondes. Il est recommandé de spécifier une valeur supérieure à 300.
-
-
Configurez les callbacks pour surveiller l'état et recevoir des messages.
-
Configurez un callback pour surveiller l'état.
-
Exemple de code :
int main(int argc, char *argv[]) { ... ... /* Specify the default callback to receive MQTT messages. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_RECV_HANDLER, (void *)demo_mqtt_default_recv_handler); /* Specify the callback to handle MQTT events. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER, (void *)demo_mqtt_event_handler); ... ... } -
Paramètres :
Élément
Exemple
Description
AIOT_MQTTOPT_RECV_HANDLER
demo_mqtt_default_recv_handler
Ce callback est appelé lors de la réception d'un message pour exécuter les opérations nécessaires.
AIOT_MQTTOPT_EVENT_HANDLER
demo_mqtt_event_handler
Ce callback est invoqué lorsque l'état de la connexion de l'appareil change afin d'exécuter les opérations requises.
-
-
Définissez le callback de surveillance de l'état.
ImportantÉvitez d'inclure une logique chronophage dans la gestion des événements, sous peine de bloquer les threads de réception des paquets.
Les changements d'état de connexion peuvent résulter de diverses causes, telles que des anomalies réseau, des reconnexions automatiques ou des déconnexions.
Pour gérer ces changements d'état, modifiez le code de la section TODO selon vos besoins métier.
/* The callback to handle MQTT events. When the connection is created, recovered, or closed, the callback is called. For information about the event definition, see core/aiot_mqtt_api.h. */ void demo_mqtt_event_handler(void *handle, const aiot_mqtt_event_t *event, void *userdata) { switch (event->type) { /* Call the aiot_mqtt_connect operation to establish a connection to the MQTT broker. */ case AIOT_MQTTEVT_CONNECT: { printf("AIOT_MQTTEVT_CONNECT\n"); /* TODO: Specify the logic to establish a connection. Do not call time-consuming functions that may block threads. */ */ } break; /* If a disconnection error occurs due to a network exception, the SDK automatically initiates a request to reconnect to the MQTT broker. */ case AIOT_MQTTEVT_RECONNECT: { printf("AIOT_MQTTEVT_RECONNECT\n"); /* TODO: Specify the logic to re-establish a connection. Do not call time-consuming functions that may block threads. */ */ } break; /* A disconnection error occurs due to a network exception. The underlying read or write operation fails. A heartbeat response is not obtained from the MQTT broker. */ case AIOT_MQTTEVT_DISCONNECT: { char *cause = (event->data.disconnect == AIOT_MQTTDISCONNEVT_NETWORK_DISCONNECT) ? ("network disconnect") : ("heartbeat disconnect"); printf("AIOT_MQTTEVT_DISCONNECT: %s\n", cause); /* TODO: Specify the logic to process disconnection issues. Do not call time-consuming functions that may block threads. */ */ } break; default: { } } } -
Définissez le callback de réception des messages.
ImportantN'intégrez pas de logique chronophage pour le traitement des messages, car cela risque de bloquer les threads de réception des paquets.
Adaptez le code de la section TODO à vos besoins métier pour traiter les messages reçus.
/* The default callback function that can be called to receive MQTT messages. This function is called when the SDK receives an MQTT message from the MQTT broker and no custom callback is available. */ void demo_mqtt_default_recv_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata) { switch (packet->type) { case AIOT_MQTTRECV_HEARTBEAT_RESPONSE: { printf("heartbeat response\n"); /* TODO: Define the logic for sending a heartbeat response to the server. In most cases, a response is not sent. */ } break; case AIOT_MQTTRECV_SUB_ACK: { printf("suback, res: -0x%04X, packet id: %d, max qos: %d\n", -packet->data.sub_ack.res, packet->data.sub_ack.packet_id, packet->data.sub_ack.max_qos); /* TODO: Define the logic for sending a response from the MQTT broker to a subscription request. In most cases, a response is not sent. */ } break; case AIOT_MQTTRECV_UNSUB_ACK: { printf("unsuback, , packet id: %d\n", packet->data.unsub_ack.packet_id); /* TODO: Define the logic for sending a response from the MQTT broker to a subscription request. In most cases, a response is not sent. */ } break; case AIOT_MQTTRECV_PUB: { printf("pub, qos: %d, topic: %.*s\n", packet->data.pub.qos, packet->data.pub.topic_len, packet->data.pub.topic); printf("pub, payload: %.*s\n", packet->data.pub.payload_len, packet->data.pub.payload); printf("pub, payload len: %x\n", packet->data.pub.payload_len); aiot_mqtt_props_print(packet->data.pub.props); } break; case AIOT_MQTTRECV_PUB_ACK: { printf("puback, packet id: %d\n", packet->data.pub_ack.packet_id); /* TODO: Define the logic for sending a response from the MQTT broker to a reported QoS 1 message. Typically, a response is not sent. */ } break; case AIOT_MQTTRECV_CON_ACK: { aiot_mqtt_props_print(packet->data.con_ack.props); } break; case AIOT_MQTTRECV_DISCONNECT: { printf("server disconnect, reason code: 0x%x\n", packet->data.server_disconnect.reason_code); } break; default: { } } }
-
Étape 3 : Établir une connexion
Appelez l'opération aiot_mqtt_connect_v5 pour envoyer une demande de connexion et d'authentification à IoT Platform. Pour savoir comment configurer les paramètres, reportez-vous à la section Configurer les paramètres de connexion.
Pour plus d'informations sur la propriété utilisateur MQTT_PROP_ID_USER_PROPERTY spécifiée dans l'exemple de code ci-dessous, consultez mqtt_property_identify_t.
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);
/* Establish a connection to the server over MQTT 5.0. */
res = aiot_mqtt_connect_v5(mqtt_handle, NULL, conn_props);
aiot_mqtt_props_deinit(&conn_props);
if (res < STATE_SUCCESS) {
/* If the MQTT connection fails to be established, release the resources of the MQTT instance. */
aiot_mqtt_deinit(&mqtt_handle);
printf("aiot_mqtt_connect failed: -0x%04X\n\r\n", -res);
printf("please check variables like mqtt_host, produt_key, device_name, device_secret in demo\r\n");
return -1;
}
Étape 4 : Activer les threads keep-alive
Appelez l'opération aiot_mqtt_process pour envoyer un message de heartbeat au broker MQTT et renvoyer les messages QoS 1 n'ayant pas reçu de réponse. Cela permet de maintenir une connexion persistante.
-
Activez les threads keep-alive.
res = pthread_create(&g_mqtt_process_thread, NULL, demo_mqtt_process_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_process_thread failed: %d\n", res); return -1; } -
Pour gérer les threads keep-alive, définissez la fonction suivante :
void *demo_mqtt_process_thread(void *args) { int32_t res = STATE_SUCCESS; while (g_mqtt_process_thread_running) { res = aiot_mqtt_process(args); if (res == STATE_USER_INPUT_EXEC_DISABLED) { break; } sleep(1); } return NULL; }
Étape 5 : Activer les threads de réception des messages
Appelez l'opération aiot_mqtt_recv pour recevoir les messages MQTT du broker. Le callback de réception des messages exécute les opérations nécessaires. En cas de déconnexion suivie d'une reconnexion automatique, c'est le callback de gestion des événements qui prend le relais.
-
Activez les threads de réception des messages.
res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_recv_thread failed: %d\n", res); return -1; } -
Pour gérer ces threads, définissez la fonction suivante :
void *demo_mqtt_recv_thread(void *args) { int32_t res = STATE_SUCCESS; while (g_mqtt_recv_thread_running) { res = aiot_mqtt_recv(args); if (res < STATE_SUCCESS) { if (res == STATE_USER_INPUT_EXEC_DISABLED) { break; } sleep(1); } } return NULL; }
Étape 6 : S'abonner à un topic
Appelez l'opération aiot_mqtt_sub_v5 pour vous abonner à un topic spécifique.
-
Exemple de code :
/* Use the sample code that shows how to subscribe to a topic over MQTT based on your business requirements. */ { char *sub_topic = "/sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post_reply"; mqtt_properties_t *sub_props = aiot_mqtt_props_init(); aiot_mqtt_props_add(sub_props, &user_prop); /* The subscription options. */ sub_options_t opts = { .no_local = 1, .qos = 1, .retain_as_publish = 1, .retain_handling = 1, }; res = aiot_mqtt_sub_v5(mqtt_handle, sub_topic, &opts, NULL, NULL, sub_props); aiot_mqtt_props_deinit(&sub_props); if (res < 0) { printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res); aiot_mqtt_deinit(&mqtt_handle); return -1; } }RemarquePour plus d'informations sur la propriété utilisateur
MQTT_PROP_ID_USER_PROPERTYspécifiée dans le code suivant, consultez mqtt_property_identify_t.Pour plus d'informations sur la définition des options d'abonnement, consultez sub_options_t.
-
Paramètres :
Paramètre
Exemple
Description
sub_topic
/a18wP/LightSwitch/user/get
Topic pour lequel l'appareil dispose de l'autorisation Subscribe. Description :
a1oGscorrespond au ProductKey de l'appareil.LightSwitchcorrespond au DeviceName de l'appareil.
Cet exemple utilise le topic personnalisé par défaut.
Ce topic permet à l'appareil de recevoir des messages d'IoT Platform.
Pour plus d'informations, consultez Qu'est-ce qu'un topic.
sub_props
aiot_mqtt_props_init()
Propriétés supplémentaires à spécifier pour l'abonnement.
opts
.no_local = 1,
.qos = 1,
.retain_as_publish = 1,
.retain_handling = 1,
Options d'abonnement.
Étape 7 : Envoyer un message
Appelez l'opération aiot_mqtt_pub_v5 pour envoyer un message vers un topic spécifique.
-
Exemple de code :
mqtt_properties_t *pub_props = aiot_mqtt_props_init(); /* Use the sample code that shows how to send a message over MQTT based on your business requirements.*/ char *pub_topic = "/sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post"; char *pub_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}"; mqtt_property_t response_prop = { .id = MQTT_PROP_ID_RESPONSE_TOPIC, .value.str.len = strlen(pub_topic), .value.str.value = (uint8_t *)pub_topic, }; char *demo_data_str = "12345"; mqtt_property_t correlation_prop = { .id = MQTT_PROP_ID_CORRELATION_DATA, .value.str.len = strlen(demo_data_str), .value.str.value = (uint8_t *)demo_data_str, }; aiot_mqtt_props_add(pub_props, &response_prop); aiot_mqtt_props_add(pub_props, &correlation_prop); res = aiot_mqtt_pub_v5(mqtt_handle, pub_topic, (uint8_t *)pub_payload, (uint32_t)(strlen(pub_payload)), 1,0, pub_props); if (res < 0) { printf("aiot_mqtt pub failed, res: -0x%04X\n", -res); aiot_mqtt_deinit(&mqtt_handle); return -1; }RemarquePour plus d'informations sur la propriété utilisateur
MQTT_PROP_ID_USER_PROPERTYspécifiée dans le code suivant, consultez mqtt_property_identify_t. -
Paramètres :
Paramètre
Exemple
Description
pub_topic
/a18wP/LightSwitch/user/update
Topic pour lequel vous disposez de l'autorisation Publish. Description :
a1oGsindique le ProductKey de l'appareil.LightSwitchindique le DeviceName de l'appareil.
L'appareil utilise ce topic pour envoyer des messages à IoT Platform.
Pour plus d'informations, consultez Qu'est-ce qu'un topic.
pub_payload
{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}
Contenu du message à envoyer à IoT Platform.
Cet exemple utilisant un topic personnalisé, vous pouvez définir votre propre format de message.
Pour plus d'informations, consultez Formats de données.
pub_props
Pour plus d'informations, consultez l'exemple de code.
Propriétés incluses dans le message.
Une fois la connexion MQTT établie entre l'appareil et IoT Platform, veillez à ne pas dépasser le seuil de messages autorisé.
Pour plus d'informations sur les limites de communication, consultez Limites.
Si le nombre de messages dépasse le seuil, connectez-vous à la console IoT Platform pour consulter les messages accumulés. Pour plus d'informations, consultez Consulter et surveiller les groupes de consommateurs.
Étape 8 : Déconnecter l'appareil d'IoT Platform
Appelez l'opération aiot_mqtt_disconnect_v5 pour déconnecter l'appareil d'IoT Platform.
Pour plus d'informations sur la propriété utilisateur MQTT_PROP_ID_USER_PROPERTY spécifiée dans l'exemple de code ci-dessous, consultez mqtt_property_identify_t.
Les connexions MQTT sont conçues pour les appareils restant connectés en permanence. Vous avez la possibilité de déconnecter les appareils d'IoT Platform. Dans cet exemple, le thread principal sert à configurer les paramètres et à établir la connexion. Une fois celle-ci établie, vous pouvez mettre le thread principal en veille.
{
mqtt_properties_t *disconn_props = aiot_mqtt_props_init();
/* The reason code 0x0 indicates a normal disconnection. */
int demo_reason_code = 0x0;
char *demo_reason_string = "normal_exit";
mqtt_property_t reason_prop = {.id = MQTT_PROP_ID_REASON_STRING, .value.str.len = strlen(demo_reason_string), .value.str.value = (uint8_t *)demo_reason_string};
aiot_mqtt_props_add(disconn_props, &reason_prop);
res = aiot_mqtt_disconnect_v5(mqtt_handle, demo_reason_code, disconn_props);
aiot_mqtt_props_deinit(&disconn_props);
}
Étape 9 : Quitter le programme
Appelez l'opération aiot_mqtt_deinit pour supprimer l'instance de client MQTT et libérer les ressources associées.
res = aiot_mqtt_deinit(&mqtt_handle);
if (res < STATE_SUCCESS) {
printf("aiot_mqtt_deinit failed: -0x%04X\n", -res);
return -1;
}
Étapes suivantes
-
Après avoir configuré le fichier de code d'exemple, compilez-le pour générer un fichier exécutable. Dans cet exemple, le fichier exécutable ./output/mqtt-v5-basic-demo est produit.
Pour plus d'informations, consultez Préparer un environnement.
Pour plus d'informations sur le résultat de l'exécution, consultez Journaux opérationnels.