Este artículo describe cómo invocar las operaciones de API del Link SDK para C con el fin de conectar dispositivos basados en MQTT a IoT Platform y recibir mensajes. En este ejemplo se utiliza el archivo de código de muestra ./mqtt_basic_demo.c.
Contexto
Para obtener más información sobre las conexiones MQTT, consulte Overview.
Paso 1: Inicializar un cliente
-
Agregue los archivos de encabezado.
#include "aiot_state_api.h" #include "aiot_sysdep_api.h" #include "aiot_mqtt_api.h" -
Agregue la dependencia subyacente y configure la función de salida de registros.
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb); -
Invoque la operación aiot_mqtt_init para crear una instancia de cliente MQTT e inicializar los parámetros predeterminados.
mqtt_handle = aiot_mqtt_init(); if (mqtt_handle == NULL) { printf("aiot_mqtt_init failed\n"); return -1; }
Paso 2: Configurar las funciones obligatorias
Invoque la operación aiot_mqtt_setopt para configurar los siguientes elementos:
Para obtener más información sobre los parámetros de la operación, consulte aiot_mqtt_option_t.
-
Establezca los parámetros de conexión.
-
Código de muestra
char *product_key = "a18wP******"; char *device_name = "LightSwitch"; char *device_secret = "uwMTmVAMnGGHaAkqmeDY6cHxxB******"; char *mqtt_host = "iot-06z00ax1o******.mqtt.iothub.aliyuncs.com"; ... ... /* Set the endpoint of the MQTT broker. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *)url); /* Set the port of the MQTT broker. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *)&port); /* Set the ProductKey of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY, (void *)product_key); /* Set the DeviceName of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME, (void *)device_name); /* Set the DeviceSecret of the device. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET, (void *)device_secret); /* Set the security credential of the connection. */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred); -
Parámetros:
Parámetro
Ejemplo
Descripción
mqtt_host
iot-06z00ax1o.mqtt.iothub.aliyuncs.com
El endpoint.
Si utiliza una instancia Enterprise Edition o una instancia pública activada el 30 de julio de 2021 o después, consulte el endpoint en la página Instance Details. Haga clic en View Development Configurations en la esquina superior derecha. El endpoint se muestra en el panel Development Configurations.
Si utiliza una instancia pública activada antes del 30 de julio de 2021, el endpoint es
${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com.
product_key
a18wP
La información de autenticación del dispositivo. Para obtener más información, consulte Obtain device authentication information.
En este ejemplo se utiliza el método de autenticación de certificado único por dispositivo.
device_name
LightSwitch
device_secret
uwMTmVAMnGGHaAkqmeDY6cHxxB
-
Descripción del keep-alive de MQTT:
ImportanteDurante un periodo de keep-alive, el dispositivo debe enviar como mínimo un mensaje, incluidas las solicitudes de ping.
Un temporizador se inicia cuando IoT Platform envía un mensaje CONNACK como respuesta a un mensaje CONNECT. Cuando IoT Platform recibe un mensaje PUBLISH, SUBSCRIBE, PING o PUBACK, el temporizador se restablece. IoT Platform comprueba el latido de la conexión MQTT cada 30 segundos. El tiempo de espera para la comprobación del latido corresponde al intervalo entre el momento en que un dispositivo se conecta a IoT Platform y el momento en que se realiza la siguiente comprobación. El tiempo máximo de espera se calcula mediante la siguiente fórmula:
Heartbeat interval × 1.5 + Wait time for the heartbeat check. Si el servidor no recibe mensajes del dispositivo dentro del tiempo máximo de espera, finaliza la conexión con el dispositivo.
Link SDK para C proporciona la capacidad de keep-alive. Puede especificar los siguientes parámetros para personalizar el latido de una conexión. De lo contrario, se utilizan los valores predeterminados.
Parámetro
Valor predeterminado
Descripción
AIOT_MQTTOPT_HEARTBEAT_MAX_LOST
2
El número máximo de latidos que pueden perderse. Si se supera el límite, se restablece la conexión.
AIOT_MQTTOPT_HEARTBEAT_INTERVAL_MS
25,000
El intervalo de latido. Unidad: milisegundos. Valores válidos: de 1,000 a 1,200,000.
AIOT_MQTTOPT_KEEPALIVE_SEC
1,200
El tiempo de keep-alive. Después de perder el latido, puede restablecer la conexión dentro del periodo especificado. Valores válidos: de 30 a 1,200. Unidad: segundos. Se recomienda establecer un valor mayor a 300.
-
-
Configure las devoluciones de llamada para supervisar el estado y recibir mensajes.
-
Especifique las devoluciones de llamada para supervisar el estado.
-
Código de muestra
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); ... ... } -
Parámetros:
Parámetro
Ejemplo
Descripción
AIOT_MQTTOPT_RECV_HANDLER
demo_mqtt_default_recv_handler
Cuando se recibe un mensaje, se invoca la devolución de llamada para realizar las operaciones necesarias.
AIOT_MQTTOPT_EVENT_HANDLER
demo_mqtt_event_handler
Cuando cambia el estado de la conexión del dispositivo, se invoca la devolución de llamada para realizar las operaciones necesarias.
-
-
Defina la devolución de llamada para supervisar el estado.
ImportanteNo especifique lógica que consuma mucho tiempo para gestionar eventos. De lo contrario, los hilos utilizados para recibir paquetes podrían bloquearse.
Los cambios en el estado de la conexión incluyen excepciones de red, reconexiones automáticas y desconexiones.
Para gestionar los cambios en el estado de la conexión, puede modificar el código según sea necesario en la sección
TODO.
/* 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 with the MQTT broker. */ case AIOT_MQTTEVT_CONNECT: { printf("AIOT_MQTTEVT_CONNECT\n"); /* TODO: Specify the processing logic after the connection is established. 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 with the MQTT broker. */ case AIOT_MQTTEVT_RECONNECT: { printf("AIOT_MQTTEVT_RECONNECT\n"); /* TODO: Specify the processing logic after the connection is re-established. 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: { } } } -
Defina la devolución de llamada para recibir mensajes.
ImportanteNo especifique lógica que consuma mucho tiempo para procesar mensajes. De lo contrario, los hilos utilizados para recibir paquetes podrían bloquearse.
Para procesar los mensajes recibidos, puede modificar el código según sea necesario en la sección
TODO.
/* The default callback to process MQTT messages. When the SDK receives messages from the MQTT broker and you do not configure callbacks, the following operation is called. */ 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: Specify the logic to process heartbeat responses from the MQTT broker. In most cases, this logic is not required. */ } 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: Specify the logic to process the responses of the MQTT broker to subscription requests. In most cases, this logic is not required. */ } 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); /* TODO: Specify the logic to process the messages that are sent from the MQTT broker. */ } break; case AIOT_MQTTRECV_PUB_ACK: { printf("puback, packet id: %d\n", packet->data.pub_ack.packet_id); /* TODO: Specify the logic to process the responses of the MQTT broker to QoS 1 messages. In most cases, this logic is not required. */ } break; default: { } } }
-
Paso 3: Establecer una conexión
Invoque la operación aiot_mqtt_connect para enviar una solicitud de conexión y autenticación a IoT Platform. Para obtener información sobre cómo especificar los parámetros, consulte Set connection parameters.
/* Establish an MQTT connection with IoT Platform. */
res = aiot_mqtt_connect(mqtt_handle);
if (res < STATE_SUCCESS) {
/* Release resources of the MQTT instance if the MQTT connection fails to be established. */
aiot_mqtt_deinit(&mqtt_handle);
printf("aiot_mqtt_connect failed: -0x%04X\n", -res);
return -1;
}
Paso 4: Habilitar el hilo de keep-alive
Invoque la operación aiot_mqtt_process para enviar un mensaje de latido al broker MQTT y reenviar los mensajes QoS 1 que no han recibido respuesta. De esta manera se habilita una conexión persistente.
-
Habilite el hilo de 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; } -
Configure la función para gestionar el hilo de keep-alive.
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; }
Paso 5: Habilitar el hilo para recibir mensajes
Invoque la operación aiot_mqtt_recv para recibir mensajes MQTT del broker. Las operaciones necesarias se realizan mediante la devolución de llamada para recibir mensajes. Si ocurre una desconexión seguida de una reconexión automática, las operaciones necesarias se ejecutan mediante la devolución de llamada para gestionar eventos.
-
Habilite el hilo para recibir mensajes.
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; } -
Configure la función para gestionar el hilo.
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; }
Paso 6: Suscribirse a un tema
Invoque la operación aiot_mqtt_sub para suscribirse a un tema específico.
-
Código de muestra
{ char *sub_topic = "/a18wP******/LightSwitch/user/get"; res = aiot_mqtt_sub(mqtt_handle, sub_topic, NULL, 1, NULL); if (res < 0) { printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res); return -1; } }NotaDespués de configurar el código de muestra, elimine los símbolos de comentario a ambos lados del código.
-
Parámetros:
Parámetro
Ejemplo
Descripción
sub_topic
/a18wP/LightSwitch/user/get
El tema que tiene permiso de suscripción.
a18wPindica el ProductKey del dispositivo.LightSwitchindica el DeviceName del dispositivo.
En este ejemplo se utiliza el tema personalizado predeterminado.
El dispositivo puede recibir mensajes de IoT Platform mediante este tema.
Para obtener más información sobre los temas, consulte Topics.
Paso 7: Enviar un mensaje
Invoque la operación aiot_mqtt_pub para enviar un mensaje a un tema específico.
-
Código de muestra
{ char *pub_topic = "/a18wP******/LightSwitch/user/update"; char *pub_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}"; res = aiot_mqtt_pub(mqtt_handle, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0); if (res < 0) { printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res); return -1; } }NotaDespués de configurar el código de muestra, elimine los símbolos de comentario a ambos lados del código.
-
Parámetros:
Parámetro
Ejemplo
Descripción
pub_topic
/a18wP/LightSwitch/user/update
El tema que tiene permiso de publicación.
a18wPindica el ProductKey del dispositivo.LightSwitchindica el DeviceName del dispositivo.
El dispositivo puede enviar mensajes a IoT Platform mediante este tema.
Para obtener más información sobre los temas, consulte Topics.
pub_payload
{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}
El mensaje que se envía a IoT Platform.
En este ejemplo se utiliza un tema personalizado. Por lo tanto, puede personalizar el formato del mensaje.
Para obtener más información sobre los formatos de mensaje, consulte Data formats.
Una vez establecida la conexión MQTT entre el dispositivo e IoT Platform, asegúrese de que el número de mensajes no supere el umbral.
Para obtener más información sobre los límites, consulte Connections and communications, el tema Limits en la documentación de IoT Platform.
Si el número de mensajes supera el umbral, inicie sesión en la consola de IoT Platform para ver los mensajes acumulados. Para obtener más información, consulte View and monitor consumer groups.
Paso 8: Desconectar el dispositivo de IoT Platform
Las conexiones MQTT están diseñadas para dispositivos que permanecen conectados de forma persistente. Puede desconectar manualmente los dispositivos de IoT Platform.
En este ejemplo, el hilo principal se utiliza para establecer parámetros y crear la conexión. Una vez establecida la conexión, puede poner el hilo principal en reposo.
Invoque la operación aiot_mqtt_disconnect para desconectar el dispositivo de IoT Platform.
res = aiot_mqtt_disconnect(mqtt_handle);
if (res < STATE_SUCCESS) {
aiot_mqtt_deinit(&mqtt_handle);
printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res);
return -1;
}
Paso 9: Salir del programa
Invoque la operación aiot_mqtt_deinit para destruir la instancia del cliente MQTT y liberar recursos.
res = aiot_mqtt_deinit(&mqtt_handle);
if (res < STATE_SUCCESS) {
printf("aiot_mqtt_deinit failed: -0x%04X\n", -res);
return -1;
}
Siguientes pasos
-
Después de configurar el archivo de código de muestra, compílelo para generar un archivo ejecutable. En este ejemplo se genera el archivo ejecutable
./output/mqtt-basic-demo.Para obtener más información, consulte Compilation and running.
Para obtener más información sobre los resultados de ejecución, consulte View logs.