As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Demonstração de compartilhamento de conexão coreMQTT
Importante
Esta é uma versão arquivada do Guia do usuário do FreeRTOS para usar com a versão 202012.00 do FreeRTOS. Para obter a versão mais recente deste documento, consulte o Guia do usuário do FreeRTOS.
Introdução
O projeto de demonstração do compartilhamento de conexão CoreMQTT mostra como usar um aplicativo multiencadeado para estabelecer uma conexão com o agente AWS MQTT usando TLS com autenticação mútua entre o cliente e o servidor. Esta demonstração usa uma implementação de interface de transporte baseada em mbedTLS para estabelecer uma conexão TLS autenticada pelo servidor e pelo cliente e demonstra um fluxo de trabalho de publicação e assinatura de MQTT no nível de QoS 1
nota
Para configurar e executar as demonstrações do FreeRTOS, siga as etapas em Conceitos básicos do FreeRTOS.
Esta demonstração usa uma fila de threads segura para manter comandos para interagir com a API MQTT. Tome nota de quatro tarefas nesta demonstração.
-
Uma tarefa de comando (principal) recebe comandos da fila de comandos e os processa. As outras tarefas colocam comandos nessa fila para serem processados. Essa tarefa entra em um loop, durante o qual processa os comandos. Se um comando de encerramento for recebido, essa tarefa escapará do loop.
-
Uma tarefa de publicador síncrona cria uma série de operações de publicação e as envia para a fila de comandos. Em seguida, essas operações são executadas pela tarefa de comando. Essa tarefa usa publicação síncrona, o que significa que ela aguardará a conclusão de cada operação de publicação antes de programar a próxima.
-
Uma tarefa de publicador assíncrona cria uma série de operações de publicação e as envia para a fila de comandos. Em seguida, essas operações são executadas pela tarefa de comando. A diferença entre essa tarefa e a anterior é que ela não espera a conclusão de uma operação de publicação antes de programar a próxima. Ela verifica o status de cada operação de publicação após todas as operações de publicação serem adicionadas à fila. Observe que a diferença entre a publicação síncrona e assíncrona está apenas no comportamento dessas tarefas. Não há diferenças nos comandos de publicação propriamente ditos.
-
Uma tarefa de assinante cria uma assinatura MQTT em um filtro de tópicos que corresponde aos tópicos de todas as mensagens publicadas pelas duas tarefas do publicador. Essa tarefa entra em um loop e espera receber as mensagens que foram publicadas pelas outras tarefas.
As tarefas podem ter filas para manter as mensagens recebidas. A tarefa de comando enviará as mensagens recebidas para a fila de qualquer tarefa assinada no tópico de entrada.
Esta demonstração usa uma conexão TLS com autenticação mútua para se conectar a AWS. Se a rede for desconectada inesperadamente durante a demonstração, o cliente tentará se reconectar usando a lógica de recuo exponencial. Se o cliente se reconectar com êxito, mas o agente não conseguir retomar a sessão anterior, o cliente assinará novamente os mesmos tópicos da sessão anterior.
Thread única versus thread múltipla
Existem dois modelos de uso da coreMQTT, o com thread única e o com threads múltiplas (multitarefas). Esta demonstração mostra como você pode criar o próprio esquema com threads múltiplas. Há também outro exemplo com threads múltiplas que executa o protocolo MQTT em segundo plano em uma tarefa de agente (ou daemon). Para obter mais informações, consulte Agente e demonstrações MWTT usando a coreMQTTMQTT_ProcessLoop
. Além disso, se você usar uma tarefa de agente, várias tarefas de aplicação poderão compartilhar uma única conexão MQTT sem a necessidade de primitivas de sincronização, como mutexes.
Código-fonte
O arquivo fonte de demonstração tem um nome mqtt_demo_connection_sharing.c
e pode ser encontrado no
diretório e no GitHubfreertos
/demos/coreMQTT/
Funcionalidade
Essa demonstração cria quatro tarefas no total: três que solicitam chamadas à API MQTT e uma que processa essas solicitações e é a tarefa principal. Nesta demonstração, a tarefa principal entra em um loop que cria as três subtarefas, chama o loop de processamento e depois faz a limpeza. A tarefa principal cria uma conexão MQTT única com o agente que é compartilhada entre as subtarefas. Duas das subtarefas publicam mensagens para o agente e a terceira recebe as mensagens de volta, usando uma assinatura MQTT para um filtro de tópicos que corresponde a todos os tópicos das mensagens publicadas.
Typedefs
A demonstração define as seguintes estruturas, enumerações e ponteiros de função.
- Comandos
-
Em vez de fazer chamadas diretamente à API MQTT, as tarefas usam estruturas
Command_t
para criar comandos que instruem a tarefa principal a chamar a operação de API apropriada para elas. Os comandos têm os tipos a seguir:-
PROCESSLOOP
-
PUBLISH
-
SUBSCRIBE
-
UNSUBSCRIBE
-
PING
-
DISCONNECT
-
RECONNECT
-
TERMINATE
O comando
TERMINATE
não tem uma operação de API MQTT correspondente. Ele é usado na demonstração para instruir a tarefa principal a interromper o processamento de comandos e iniciar as operações de limpeza. Como algumas informações adicionais, por exemplo, informações de publicação ou assinatura, são necessárias para alguns comandos MQTT comoMQTT_Publish
,MQTT_Subscribe
eMQTT_Unsubscribe
, usamos o campoCommandContext_t
. Esse campo é obrigatório para esses três comandos e é opcional para outros.Como esse contexto é obrigatório para esses comandos, não altere esse valor depois que o comando for colocado na fila, até que o comando seja concluído. Quando um comando é concluído, um retorno de chamada opcional pode ser invocado. Nesta demonstração, usamos um retorno de chamada que cria uma notificação de tarefa para informar à tarefa de chamada que o comando foi concluído. Para operações MQTT que exigem confirmações (assinaturas, cancelamentos de assinaturas e publicações com QoS maior que 0), o comando será considerado concluído quando a confirmação for recebida. Caso contrário, o comando será concluído quando a chamada de API MQTT correspondente for retornada.
As definições a seguir podem ser encontradas no arquivo
mqtt_demo_connection_sharing.c
:-
Estrutura Command_t
-
CommandType_t
enumeração
-
- Confirmações
-
Como algumas operações do MQTT exigem uma confirmação, elas usam uma matriz de AckInfo_t
que contém o identificador do pacote da confirmação esperada e o comando original que a espera, para que seu retorno de chamada de conclusão possa ser invocado. - Assinaturas
-
Essa demonstração pode rastrear assinaturas para cada tarefa. Para fazer isso, cada tarefa que solicita uma assinatura deve fornecer uma fila de mensagens na qual receberá de volta as mensagens publicadas (SubscriptionElement_t
). Várias tarefas podem assinar o mesmo filtro de tópicos, pois espera-se que usem filas de resposta separadas. - Mensagens publicadas recebidas
-
Como as tarefas são executadas paralelamente à tarefa principal, seria difícil e demorado se a tarefa principal tivesse que esperar cada tarefa assinada ler uma mensagem publicada recebida. Portanto, cada mensagem recebida é copiada para a fila de respostas de qualquer tarefa que esteja inscrita no tópico da mensagem publicada (PublishElement_t).
Como os pacotes de publicação recebidos do cliente MQTT contêm ponteiros para o buffer de rede do cliente, a carga e o nome do tópico da mensagem recebida são copiados em buffers separados antes de serem inseridos em uma fila de resposta. Dessa forma, a tarefa assinada ainda poderá ler as informações recebidas após o cliente MQTT limpar o buffer de rede.
Tarefa principal
A tarefa principal do aplicativo, RunCoreMQTTConnectionSharingDemoclean session
definido, depois se desconecta e se reconecta com o sinalizador não definido. Após o loop de processamento encerrar, ele se desconecta do agente e faz loop novamente a partir do ponto em que fez a reconexão da rede.
A conclusão da demonstração com êxito gerará um resultado semelhante ao da imagem a seguir.

- Loop de comando
-
O loop de comando, prvCommandLoop
, espera que os comandos sejam colocados na fila de comandos e, em seguida, chama a API MQTT apropriada. Todos os comandos, exceto DISCONNECT
eTERMINATE
, resultam na chamada deMQTT_ProcessLoop
. Esta demonstração define um retorno de chamada de ativação do soquete para adicionar um comandoPROCESSLOOP
à fila quando os dados estão disponíveis no soquete. No entanto, podem existir muitos comandos à frente na fila nesse momento. Para garantir que não negligenciemos os dados recebidos enquanto outros comandos são processados,MQTT_ProcessLoop
é chamado para uma iteração única após cada comando. - Comandos de processamento
-
Veja a prvProcessCommand
função.
Tarefa síncrona do publicador
A tarefa síncrona do editor, prvSyncPublishTarefaPUBLISH
operações de forma síncrona e espera que cada operação seja concluída antes de programar a próxima. Esta demonstração usa QoS 1 para publicar mensagens, isso significa que essas operações não são consideradas concluídas até que o pacote de confirmação de publicação seja recebido.
Tarefa de publicador assíncrona
A tarefa assíncrona do editor, prvAsyncPublishTarefa
Tarefa do assinante
A tarefa do assinante, prvSubscribeTaskTERMINATE
que sinaliza a tarefa principal para encerrar o loop de comando.