Este artigo descreve como chamar as operações de API do Link SDK for C para conectar dispositivos baseados em MQTT ao IoT Platform e receber mensagens. Neste exemplo, utiliza-se o arquivo de código de amostra ./mqtt_basic_demo.c.
Informações básicas
Para obter mais informações sobre conexões MQTT, consulte Visão geral.
Etapa 1: Inicializar um cliente
-
Adicione os arquivos de cabeçalho.
#include "aiot_state_api.h" #include "aiot_sysdep_api.h" #include "aiot_mqtt_api.h" -
Adicione a dependência subjacente e configure o recurso de saída de log.
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb); -
Chame a operação aiot_mqtt_init para crie uma instância de cliente MQTT e inicializar os parâmetros padrão.
mqtt_handle = aiot_mqtt_init(); if (mqtt_handle == NULL) { printf("aiot_mqtt_init failed\n"); return -1; }
Etapa 2: Configurar os recursos necessários
Chame a operação aiot_mqtt_setopt para configurar os seguintes itens:
Para obter mais informações sobre os parâmetros da operação, consulte aiot_mqtt_option_t.
-
Defina os parâmetros de conexão.
-
Código de amostra
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
Exemplo
Descrição
mqtt_host
iot-06z00ax1o.mqtt.iothub.aliyuncs.com
O endpoint.
Se você utilizar uma instância Enterprise Edition ou uma instância pública ativada em 30 de julho de 2021 ou posterior, visualize o endpoint na página Instance Details. Clique em View Development Configurations no canto superior direito. O endpoint será exibido no painel Development Configurations.
Caso utilize uma instância pública ativada antes de 30 de julho de 2021, o endpoint é
${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com.
product_key
a18wP
As informações de autenticação do dispositivo. Para mais detalhes, consulte Obter informações de autenticação do dispositivo.
Neste exemplo, utiliza-se o método de autenticação de certificado único por dispositivo.
device_name
LightSwitch
device_secret
uwMTmVAMnGGHaAkqmeDY6cHxxB
-
Descrição do keep-alive do MQTT:
ImportanteDurante um período de keep-alive, o dispositivo deve enviar pelo menos uma mensagem, incluindo solicitações de ping.
Um temporizador inicia quando o IoT Platform envia uma mensagem CONNACK como resposta a uma mensagem CONNECT. Ao receber uma mensagem PUBLISH, SUBSCRIBE, PING ou PUBACK, o IoT Platform redefine o temporizador. A verificação de heartbeat da conexão MQTT ocorre a cada 30 segundos. O tempo de espera para essa verificação corresponde ao intervalo entre o momento em que o dispositivo se conecta ao IoT Platform e o momento da próxima verificação. O tempo limite máximo é calculado pela seguinte fórmula:
Intervalo de heartbeat × 1,5 + Tempo de espera para verificação de heartbeat. Se o servidor não receber mensagens do dispositivo dentro desse prazo máximo, ele encerrará a conexão.
O Link SDK for C oferece o recurso de keep-alive. É possível especifique os parâmetros abaixo para personalizar o heartbeat da conexão. Caso contrário, o sistema usará os valores padrão.
Parâmetro
Valor padrão
Descrição
AIOT_MQTTOPT_HEARTBEAT_MAX_LOST
2
Número máximo de heartbeats perdidos permitidos. Se o limite for excedido, a conexão será restabelecida.
AIOT_MQTTOPT_HEARTBEAT_INTERVAL_MS
25.000
Intervalo de heartbeat. Unidade: milissegundos. Valores válidos: 1.000 a 1.200.000.
AIOT_MQTTOPT_KEEPALIVE_SEC
1.200
Tempo de keep-alive. Após a perda do heartbeat, é possível restabelecer a conexão dentro do período especificado. Valores válidos: 30 a 1.200. Unidade: segundos. Recomenda-se defina um valor superior a 300.
-
-
Configure callbacks para monitorar status e receber mensagens.
-
Especifique os callbacks para monitorar status.
-
Código de amostra
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
Exemplo
Descrição
AIOT_MQTTOPT_RECV_HANDLER
demo_mqtt_default_recv_handler
Chama o callback ao receber uma mensagem para executar as operações necessárias.
AIOT_MQTTOPT_EVENT_HANDLER
demo_mqtt_event_handler
Aciona o callback quando o status da conexão do dispositivo muda, executando as operações requeridas.
-
-
Defina o callback para monitorar status.
ImportanteEvite incluir lógicas demoradas no tratamento de eventos. Caso contrário, as threads usadas para receber pacotes podem ser bloqueadas.
Alterações no status da conexão incluem exceções de rede, reconexões automáticas e desconexões.
Para lidar com mudanças no status da conexão, modifique o código conforme necessário na seção
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 o callback para receber mensagens.
ImportanteNão utilize lógicas demoradas para processar mensagens. Isso pode bloquear as threads responsáveis por receber pacotes.
Para processar as mensagens recebidas, ajuste o código conforme necessário na seção
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: { } } }
-
Etapa 3: Estabelecer uma conexão
Chame a operação aiot_mqtt_connect para enviar uma solicitação de conexão e autenticação ao IoT Platform. Para saber como especifique os parâmetros, consulte Definir parâmetros de conexão.
/* 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;
}
Etapa 4: Ativar a thread de keep-alive
Utilize a operação aiot_mqtt_process para enviar mensagens de heartbeat ao broker MQTT e reenviar mensagens QoS 1 sem resposta. Isso mantém a conexão persistente ativa.
-
Ative a thread 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 a função para gerencie a thread 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; }
Etapa 5: Ativar a thread de recebimento de mensagens
Execute a operação aiot_mqtt_recv para receber mensagens MQTT do broker. O callback de recebimento de mensagens executa as operações necessárias. Em caso de desconexão seguida de reconexão automática, o callback de tratamento de eventos assume as operações.
-
Ative a thread de recebimento de mensagens.
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 a função para gerencie a thread.
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; }
Etapa 6: Inscrever-se em um tópico
Chame a operação aiot_mqtt_sub para se inscrever em um tópico específico.
-
Código de amostra
{ 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; } }NotaApós configurar o código de amostra, remova os símbolos de anotação de ambos os lados do código.
-
Parâmetros:
Parâmetro
Exemplo
Descrição
sub_topic
/a18wP/LightSwitch/user/get
Tópico com permissão de inscrição (Subscribe).
a18wPrepresenta a ProductKey do dispositivo.LightSwitchrepresenta a DeviceName do dispositivo.
Este exemplo utiliza o tópico personalizado padrão.
Por meio deste tópico, o dispositivo recebe mensagens do IoT Platform.
Para mais informações sobre tópicos, consulte Tópicos.
Etapa 7: Enviar uma mensagem
Utilize a operação aiot_mqtt_pub para enviar uma mensagem a um tópico específico.
-
Código de amostra
{ 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; } }NotaApós configurar o código de amostra, remova os símbolos de anotação de ambos os lados do código.
-
Parâmetros:
Parâmetro
Exemplo
Descrição
pub_topic
/a18wP/LightSwitch/user/update
Tópico com permissão de publicação (Publish).
a18wPrepresenta a ProductKey do dispositivo.LightSwitchrepresenta a DeviceName do dispositivo.
Este tópico permite que o dispositivo envie mensagens ao IoT Platform.
Para mais informações sobre tópicos, consulte Tópicos.
pub_payload
{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}
Mensagem enviada ao IoT Platform.
Como este exemplo usa um tópico personalizado, o formato da mensagem é flexível.
Para detalhes sobre formatos de mensagem, consulte Formatos de dados.
Depois de estabelecer a conexão MQTT entre o dispositivo e o IoT Platform, garanta que o volume de mensagens não ultrapasse o limiar definido.
Para detalhes sobre limites, consulte a seção Conexões e comunicações no tópico Limits da documentação do IoT Platform.
Caso o número de mensagens exceda o limiar, acesse o console do IoT Platform para verificar mensagens acumuladas. Para mais informações, consulte Visualizar e monitorar grupos de consumidores.
Etapa 8: Desconectar o dispositivo do IoT Platform
Conexões MQTT destinam-se a dispositivos que permanecem conectados persistentemente. Você pode desconectar manualmente os dispositivos do IoT Platform.
Neste exemplo, a thread principal define os parâmetros e estabelece a conexão. Após a conexão, coloque a thread principal em suspensão.
Chame a operação aiot_mqtt_disconnect para desconectar o dispositivo do 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;
}
Etapa 9: Sair do programa
Utilize a operação aiot_mqtt_deinit para destruir a instância do cliente MQTT e liberar recursos.
res = aiot_mqtt_deinit(&mqtt_handle);
if (res < STATE_SUCCESS) {
printf("aiot_mqtt_deinit failed: -0x%04X\n", -res);
return -1;
}
Próximos passos
-
Após configurar o arquivo de código de amostra, compile-o para gerar um arquivo executável. Neste exemplo, gera-se o arquivo executável
./output/mqtt-basic-demo.Para mais informações, consulte Compilação e execução.
Para detalhes sobre os resultados da execução, consulte Visualizar logs.