Apesar de ser uma linguagem de programação com uma significativa idade, a linguagem C está constantemente evoluindo e seu uso continua muito relevante no desenvolvimento de software embarcado, como mostrado no Ranking das Linguagens de Programação mais usadas em 2018 (IEEE Spectrum). O próprio Kernel Linux (e, também, outros softwares importantes para uma distribuição Linux) é desenvolvido majoritariamente em linguagem C, reforçando portanto a importância desta linguagem de programação. Além disso, os compiladores C estão cada vez melhores (sobretudo os destinados às plataformas e arquiteturas embarcadas), garantindo que os softwares compilados tenham desempenho excelente. Logo, faz pleno sentido desenvolver software embarcado em linguagem C.
Nesta linha de raciocínio, este artigo mostra como desenvolver em C um cliente MQTT utilizando a biblioteca open-source Paho MQTT, abrindo portanto para o leitor a possibilidade de integração com as plataformas de Internet das Coisas a partir de programas escritos em C no Linux Embarcado.
Hardware utilizado
Como o título deste artigo sugere, este artigo pode ser aplicado em diversas distribuições Linux para sistemas embarcados. Porém, para poder exemplificar, mostrar e validar todo o processo de compilação e instalação da biblioteca e a programação de um cliente MQTT, foi escolhido como hardware-alvo a placa de desenvolvimento Beaglebone Black. O motivo da escolha foi devido a esta ser uma das placas de desenvolvimento mais empregadas em projetos em nível mundial, tanto como hobby quanto no âmbito de projetos comerciais. A figura 1 mostra a Beaglebone Black (Rev. C).
O protocolo MQTT – Linhas gerais
O protocolo MQTT (Message Queue Telemetry Transport) é um protocolo criado no final dos anos 90 pela IBM, destinado à comunicação M2M (Machine-to-Machine). Apesar de não ser algo novo, possui larga utilização atualmente devido a ser um protocolo classificado como lightweight (utiliza poucos recursos computacionais dos seus clientes e utiliza pouco tráfego de dados para funcionar). Desta forma, configura-se como um dos mais adequados protocolos para projetos IoT em clientes embarcados, onde poder computacional, consumo energético, memória, armazenamento e quantidade de dados a serem trafegados são sempre diminutos.
Em linhas gerais, o MQTT utiliza um servidor (chamado broker), o qual faz a mediação / direcionamento de comunicação entre N clientes, os quais podem enviar (publish) e/ou receber (subscribe) dados. Ou seja, todos os dados trafegam obrigatoriamente pelo broker, e este é o responsável por receber as mensagens dos remetentes e enviá-las aos destinatários. Tal controle de remetentes e destinatários é feito através de tópicos MQTT, os quais servem para os clientes informarem aos brokers o que desejam receber e para quem desejam enviar dados. Observe a figura 2.
Ainda, o broker pode estar em uma rede local ou em uma rede de alcance maior (como em um servidor com acesso à Internet), permitindo, portanto, a comunicação entre clientes a nível mundial.
Para mais detalhes sobre o MQTT, leia o artigo MQTT – Protocolos para IoT, do autor Marcelo Barros.
A biblioteca Paho MQTT
A biblioteca Paho MQTT trata-se de uma biblioteca open-source para desenvolvimento de clientes MQTT (e, mais recentemente, desenvolvimento de clientes MQTT-SN também). Esta biblioteca é um projeto do iot.eclipse.org e possui como principais características ser leve, suportar comunicação MQTT segura (TLS/SSL) e por possuir versões para várias linguagens de programação dominantes, tais como Java, C e Python. Além disso, computacionalmente falando, trata-se de uma biblioteca muito leve (tanto em consumo de memória, armazenamento, quanto processamento requerido).
Com o boom do IoT mundo afora, esta biblioteca é uma ótima escolha àqueles que desejam acrescentar em seus projetos conectividade com as plataformas IoT (Amazon AWS, Microsoft Azure, etc.), uma vez que a grande maioria delas permite o envio e recepção de dados por MQTT.
A documentação da biblioteca para a linguagem C pode ser lida neste link.
Procedimento de compilação e instalação – Paho MQTT C client
Antes de partir para a programação do cliente MQTT e C, é necessária a compilação e instalação da biblioteca Paho MQTT (para linguagem C). Para isso, siga o procedimento abaixo:
Atualização dos pacotes já existentes
Como primeiro passo, é altamente recomendável atualizar os pacotes instalados. Isso evita possíveis incompatibilidades ou erros nas instalações de pacotes deste procedimento. Para isso, execute os comandos a seguir:
sudo apt-get update sudo apt-get upgrade
Instalação dos pacotes de desenvolvimento do OpenSSL
A bibloteca Paho MQTT da suporte à comunicação segura com MQTT (utilizando TLS/SSL), logo os pacotes de desenvolvimento do OpenSSL são necessários para sua compilação e funcionamento. Para instalar os pacotes de desenvolvimento do OpenSSL, execute os comandos a seguir:
sudo apt-get install libssl-dev
Instalação do Doxygen
O Doxygen também precisa ser instalado. Ele fará com que toda a documentação da biblioteca possa ser gerada, algo muito importante para quem quiser desenvolver aplicações com esta biblioteca (sobretudo para trabalhos mais sérios, já que a documentação é bem completa). Para fazer esta instalação, execute o comando a seguir:
sudo apt-get install doxygen
Obtenção do repositório da biblioteca
A biblioteca Paho MQTT, conforme dito anteriormente neste mesmo artigo, é open-source. Desta forma, para utilizá-la, precisaremos baixar seu código-fonte e, posteriormente, fazer a compilação do mesmo. Para isso, execute o comando abaixo:
git clone https://github.com/eclipse/paho.mqtt.c.git
Compilação e instalação
Agora é a etapa de compilação e instalação da biblioteca. Para isso, vá ao diretório do repositório (o qual foi baixado no item anterior):
cd paho.mqtt.c
Em seguida, faça a compilação da biblioteca e de sua documentação com os comandos abaixo:
make make html
Uma vez compilada, a biblioteca pode ser instalada. Para isso, utilize o comando abaixo:
sudo make install
A partir deste ponto, a biblioteca Paho MQTT (C client) está pronta para uso.
Programando um cliente MQTT simples em C
É chegada a hora de desenvolver um cliente MQTT em C, utilizando a biblioteca Paho MQTT. Tal cliente terá como finalidade fazer echo da mensagem MQTT recebida de um tópico em outro tópico. Para isso, considere o código-fonte a seguir. É fortemente recomendada a leitura de seus comentários para maior compreensão do mesmo.
/*
* Includes
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <MQTTClient.h>
/*
* Defines
*/
/* Caso desejar utilizar outro broker MQTT, substitua o endereco abaixo */
#define MQTT_ADDRESS "tcp://iot.eclipse.org"
/* Substitua este por um ID unico em sua aplicacao */
#define CLIENTID "MQTTCClientID"
/* 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 */
printf("Mensagem recebida! \n\rTopico: %s Mensagem: %s\n", topicName, payload);
/* Faz echo da mensagem recebida */
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 (conexao & subscribe) */
MQTTClient_create(&client, MQTT_ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
MQTTClient_setCallbacks(client, NULL, NULL, on_message, NULL);
rc = MQTTClient_connect(client, &conn_opts);
if (rc != MQTTCLIENT_SUCCESS)
{
printf("\n\rFalha na conexao ao broker MQTT. Erro: %d\n", rc);
exit(-1);
}
MQTTClient_subscribe(client, MQTT_SUBSCRIBE_TOPIC, 0);
while(1)
{
/*
* o exemplo opera por "interrupcao" no callback de recepcao de
* mensagens MQTT. Portanto, neste laco principal eh preciso fazer
* nada.
*/
}
}
Para compilar, deve ser considerada a biblioteca Paho MQTT. Assumindo que o código-fonte seja salvo como main.c e que o binário final irá se chamar mqtt_exemplo, o comando de compilação é o seguinte:
gcc main.c -o mqtt_exemplo -lpaho-mqtt3c -Wall
E, para executar, utilize o seguinte comando:
./mqtt_exemplo
Pronto! Agora basta testar com um cliente MQTT de sua preferência. A figura 4 mostra o teste do programa em ação, utilizando o cliente MQTT MQTT Lens e o terminal com o programa rodando na Beaglebone Black.
Saiba mais
MQTT-SN: MQTT para rede de sensores
Exibindo valores de temperatura e umidade no app MQTT Dash com o sensor DHT11
Raspberry Pi 3 na IoT – MQTT e Python
Referências








Muito Interessante. Valeu. 😉
Gostaria de fazer um projeto onde uso um broker local, no codigo diz para modificar #define MQTT_ADDRESS , minha pergunta é como devo modifica-lo
Se o broker é local, você pode utilizar o ip de loopback (127.0.0.1) ou localhost.
Ola, tenho uma placa com reles que conectada a rede cabeada aciona reles quando recebe o comando pelo browser tipo 192.168.1/1/low e gostaria q o cliente mqtt q vc ensinou em vez de fazer o echo chamasse este ip para a placa acionar o rele? mas sem browser ou abrir janela alguma, como faço ?? parece simples mas sou iniciante e ainda estou engatinhando, agradeço se detalhar.
Olá, sou iniciante no mundo IOT, e tenho visto vários posts seus, devo parabeniza-lo e pedir sua ajuda, possuo uma placa que aciona os seus reles por comandos de rede tipo 192.168.1.10/1, e gostaria de usar um Raspberry com servidor mosquito para aciona-los, para isso teria o servidor mosquito rodando no rasp, e tbm o cliente sub q deveria escutar e mandar o comando chamando o ip 192.168.1.10/1, gostaria de um exemplo de como chamar este ip sem abrir nenhuma janela, para q a placa acione o rele? ai poderia usar o código do seu post acima, mas em vez… Leia mais »
Pedro, cumprimentos pelo artigo. Você usou qual imagem no seu Beaglebone Black? Pode indicar o link por favor? Você salvou na memória da própria placa ou foi via cartão SD? Qual a vantagem dessa rede sobre a rede CAN? Obrigada!
Jordana, obrigado pela leitura! Eu utilizei a imagem Debian 9.5 2018-08-30 4GB SD IoT na BeagleBone Black (é a imagem mais atual disponível em https://beagleboard.org/latest-images). O link direto para download desta imagem é: https://debian.beagleboard.org/images/bone-debian-9.5-iot-armhf-2018-08-30-4gb.img.xz Eu utilizei um cartao SD (não utilizei a memória interna, eMMC). O motivo é que, para projetos que ando trabalhando na BeagleBone Black, o tamanho da memória interna não é suficiente. Porém, se você desejar, consegue instalar esta imagem na memória interna sem problemas. Quanto a comparação com a rede CAN, não vejo sentido na comparação. Este artigo fala sobre o MQTT, um protocolo de comunicação… Leia mais »
Obrigada pela resposta, Bruno! 🙂
Legal Pedro, segui todas as etapas e funcionou. Agora estou curioso em saber o que eu posso fazer com isso. Sera que eu posso criar um broker MQTT local ? Usando um esp8266 como propõe o Fabio Souza em seus artigos ?
Olá fabitencourt63, fico feliz que deu certo o projeto por ai! Sobre o que fazer com os conhecimentos / aprendizado em criar um cliente MQTT, há inúmeras possibilidades, como por exemplo as que cito abaixo. Lembrando que o que foi passado neste artigo foi como construir um cliente MQTT. A construção de um broker MQTT está fora do escopo deste artigo. – Transmitir informações de entradas (digitais e/ou analógicas) e controlar saídas diversas via Internet (algo que eu faço neste local: https://github.com/phfbertoleti/bacon_cape_lib/tree/master/mqtt_example) – Fazer projetos de automação em geral (incluindo automação residencial) – Comunicar módulos / centrais a nível mundo… Leia mais »