Como desenvolver um cliente MQTT em C na Raspberry Pi 1

Esse post vai te ensinar como fazer seu primeiro cliente MQTT em C na Raspberry Pi, de modo que mesmo em sistemas onde a performance deve ser maximizada (com uso de linguagem C como principal linguagem de programação) seja possível implementar um cliente MQTT e tornar seu dispositivo e aplicação comunicáveis via MQTT.

O MQTT (Message Queuing Telemetry Transport) é um dos protocolos mais populares se tratando de Internet das Coisas. Mesmo já com certa “idade” (foi criado em 1999), este ainda continua sendo um protocolo ideal para comunicação M2M (Machine-to-Machine) e para comunicação via Internet com baixíssimo tráfego de dados. Desta forma, sobretudo para dispositivos que funcionam sob conectividade móvel com restrição de consumo de dados (3G e afins), o MQTT é um protocolo muito importante. Além disso, muitos sistemas embarcados, majoritariamente por questão de maximização de desempenho, possuem suas aplicações desenvolvidas em C “puro”, o que faz com que desenvolver aplicações em C que utilizem um servidor ou um cliente MQTT faça sentido.

Material necessário

Para este projeto, você precisará apenas de

Importante: sua Raspberry Pi já deve estar com cartão SD, para máxima performance, é recomendado o uso de um cartão SD classe 10. O sistema operacional deve estar instalado, operante e com conectividade à Internet funcionando corretamente. Para aprender a configurar a Raspberry Pi Basta acessar o post Primeiros Passos com Raspberry Pi e Linux. Também é necessário ter acesso a um console / terminal da Raspberry Pi, seja de forma local (via monitor, teclado e mouse) ou remota (SSH ou VNC).

Biblioteca C para MQTT: Paho-MQTT 

A biblioteca Paho MQTT trata-se de uma biblioteca open-source para desenvolvimento de clientes MQTT, sendo que dentre seus pontos fortes se destaca por ser muito leve e de fácil utilização. Se você acompanha os posts sobre MQTT com Python, deve ter notado que a maioria deles utiliza esta biblioteca. Isso acontece pois esta biblioteca possui versões para várias linguagens de programação, incluindo Python, C e JavaScript. Logo, para quem já usou / estava acostumado com a biblioteca Paho MQTT no Python, este artigo será bem tranquilo e intuitivo, já que os princípios e funções utilizadas são praticamente os mesmos.

Para a versão em linguagem C especificamente, existe a documentação oficial.

Neste post, iremos instalar essa biblioteca da forma mais “roots”: baixaremos o código-fonte da mesma na Raspberry Pi, compilaremos o código e, no fim, instalaremos a biblioteca. O porque de fazer isso dessa forma é simples: podemos garantir no fim do processo que a versão mais atual é a que será compilada e instalada, o que pode não ser verdade ao utilizarmos a instalação via algum gerenciador de pacotes (como o apt-get, por exemplo). Além disso, você aprenderá como baixar, compilar e instalar uma biblioteca no Linux, aprendizado que pode ser valioso nos seus projetos futuros.

Preparando o terreno

Antes de prosseguir, tenha certeza que todos as aplicações já instaladas na sua Raspberry estejam na última versão disponível. Para isso, execute os comandos abaixo em um console da Raspberry Pi.

sudo apt-get update 
sudo apt-get upgrade

A execução pode demorar um pouco, a depender da quantidade de aplicações a serem atualizadas e de sua velocidade de conexão à Internet. Feito isso, é necessário instalar os pacotes de desenvolvimento do OpenSSL, já que estes são requeridos na compilação e uso da biblioteca Paho-MQTT. Para isso, utilize o comando abaixo:

sudo apt-get install libssl-dev

Para finalizar a “preparação de terreno”, a última coisa que deve ser feita é instalar o Doxygen. Esta aplicação é necessária para a geração da documentação da biblioteca a partir do código-fonte da mesma. A instalação do Doxygen pode ser feita utilizando o comando abaixo:

sudo apt-get install doxygen

Obtenção do código-fonte da biblioteca

Para obter o código-fonte da biblioteca, vá a seu diretório home e obtenha o código-fonte a partir da ferramenta git. Para isso, utilize os comandos abaixo:

cd ~ 
git clone https://github.com/eclipse/paho.mqtt.c.git

O download pode demorar alguns segundos, a depender da velocidade da sua conexão à Internet. Finalizado o download, faça a compilação da biblioteca, geração da documentação e instalação da biblioteca com os comandos abaixo. Isso pode demorar alguns minutos. Durante este processo o uso de CPU de sua Raspberry PI irá se elevar muito. Portanto, para uma otimização do tempo que este processo leva, é altamente recomendável que você não esteja usando a placa para nada além do processo aqui mostrado:

cd paho.mqtt.c
make
make html
sudo make install

Feito isso, a biblioteca Paho MQTT para linguagem C está pronta para uso!

Desenvolvendo seu primeiro cliente MQTT em C na Raspberry Pi

Com a biblioteca Paho-MQTT para linguagem C instalada, é hora de desenvolver seu primeiro cliente MQTT em C. Tal cliente terá como finalidade fazer echo da mensagem MQTT recebida de um tópico em outro tópico (ou seja, enviar/publicar as mensagens que recebeu, utilizando tópicos distintos).
O código-fonte deste cliente MQTT está a seguir. É fortemente recomendada a leitura de seus comentários para maior compreensão do mesmo. Copie o código-fonte a seguir e salve em sua Raspberry Pi como primeiro_client_mqtt.c.

/*
* Includes
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <MQTTClient.h>

/*
* Defines
*/
/* Caso desejar utilizar um broker MQTT diferente do iot.eclipse.org, substitua o endereco abaixo pelo do broker desejado */
#define MQTT_ADDRESS   "tcp://iot.eclipse.org"
/* Substitua este por um ID unico em sua aplicacao */
#define CLIENTID       "MQTTCClientID_MakerHero"  

/* Substitua aqui os topicos de publish e subscribe por topicos exclusivos de sua aplicacao */
#define MQTT_PUBLISH_TOPIC     "MQTTCClientPubTopic"
#define MQTT_SUBSCRIBE_TOPIC   "MQTTCClientSubTopic"

/*
*  Variaveis globais
*/
MQTTClient client;

/*
* Prototipos de funcao
*/
void publish(MQTTClient client, char* topic, char* payload);
int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message);

/*
* Implementacoes
*/

/* Funcao: publicacao de mensagens MQTT
 * Parametros: cleinte MQTT, topico MQTT and payload
 * Retorno: nenhum
*/
void publish(MQTTClient client, char* topic, char* payload) {
    MQTTClient_message pubmsg = MQTTClient_message_initializer;

    pubmsg.payload = payload;
    pubmsg.payloadlen = strlen(pubmsg.payload);
    pubmsg.qos = 2;
    pubmsg.retained = 0;
    MQTTClient_deliveryToken token;
    MQTTClient_publishMessage(client, topic, &pubmsg, &token);
    MQTTClient_waitForCompletion(client, token, 1000L);
}

/* Funcao: callback de mensagens MQTT recebidas e echo para o broker
 * Parametros: contexto, ponteiro para nome do topico da mensagem recebida, tamanho do nome do topico e mensagem recebida
 * Retorno : 1: sucesso (fixo / nao ha checagem de erro neste exemplo)
*/
int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message) {
    char* payload = message->payload;

    /* Mostra a mensagem recebida no tópico subescrito*/
    printf("Mensagem recebida! \n\rTopico: %s Mensagem: %s\n", topicName, payload);

    /* Faz echo da mensagem recebida no tópico de publish */
    publish(client, MQTT_PUBLISH_TOPIC, payload);

    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

int main(int argc, char *argv[])
{
   int rc;
   MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

   /* Inicializacao do MQTT e configução de funcao de callback MQTT */
   MQTTClient_create(&client, MQTT_ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
   MQTTClient_setCallbacks(client, NULL, NULL, on_message, NULL);

   /* Conecta-se ao broker (e sai do programa caso a conexao venha a falhar) */
   rc = MQTTClient_connect(client, &conn_opts);
 
   if (rc != MQTTCLIENT_SUCCESS)
   {
       printf("\n\rFalha na conexao ao broker MQTT. Erro: %d\n", rc);
       exit(-1);
   }

   /* Faz subscribe no topico definido em MQTT_SUBSCRIBE_TOPIC */
   MQTTClient_subscribe(client, MQTT_SUBSCRIBE_TOPIC, 0);

   /* Programa principal */
   while(1)
   {
       /*
        * este client opera por "interrupcao", ou seja, opera em função do que é recebido no callback de recepcao de 
        * mensagens MQTT. Portanto, neste laco principal nao eh preciso fazer nada.
        */
   }
}

Para compilar o cliente MQTT escrito acima, é preciso utilizar a biblioteca Paho-MQTT para linguagem C. Execute o comando abaixo para fazer esta compilação:

gcc primeiro_client_mqtt.c -o primeiro_client_mqtt -lpaho-mqtt3c -Wall

Após a compilação, execute o client MQTT utilizando o comando abaixo:

./primeiro_client_mqtt

Teste do cliente MQTT desenvolvido

Neste ponto, é possível testar o cliente MQTT desenvolvido. Para isso, utilize no seu computador um programa de cliente MQTT de sua preferência (como o MQTTLens, por exemplo). A figura 1 mostra o cliente MQTT desenvolvido em ação, utilizando o cliente MQTT MQTTLens. Aqui, tudo que é publicado no MQTTLens para o tópico de Publish é recebido de volta (echo) pelo tópico de subscribe, comprovando o funcionamento do cliente MQTT proposto.

MQTT em C na Raspberry Pi
Figura 1 – teste do cliente MQTT desenvolvido

Gostou do post sobre como fazer um cliente MQTT em C na Raspberry Pi? Deixe seu comentário logo abaixo.

Faça seu comentário

Acesse sua conta e participe

Um Comentário

  1. Agora sim Funcionou, Grato , Fernando da Microgenios (EAD) que me passou essa referência.