Protocolo MQTT e Aplicativo no Celular
- Felipe Luiz Oliveira
- 10 de out. de 2024
- 5 min de leitura
Neste post demonstramos como configurar uma comunicação MQTT entre a placa HF-003 e um celular para leitura das entradas e escrita nas saídas remotamente em qualquer parte do mundo.
O MQTT (Message Queue Telemetry Transport) é um protocolo de mensagens leve, criado para comunicação M2M (Machine to Machine) e exige muito pouco em termos de processamento e banda de rede. Devido a estas característica torna-se um dos protocolos favoritos para aplicações de IoT (Internet of Things).
Inicialmente descreveremos como funciona a comunicação via MQTT. Ela é composta por três partes:
PUBLISHER: É quem irá disponibilizar as informações. Nesta aplicação, o celular será um publisher do estado dos botões de acionamento das saídas
SUBSCRIBER: São os assinantes, ou seja, aqueles que lêem as informações disponibilizada pelos publishers
BROKER: É um servidor MQTT disponível na internet, sua função é gerenciar as mensagens enviadas pelos publishers e lidas pelos subscribers. Como está na internet, ele torna a comunicação entre dispositivos possível em qualquer lugar do planeta.
Neste exemplo não utilizaremos IP fixo para a placa, basta conecta-la a um roteador com acesso a internet e o endereço deve ser atribuído automaticamente.
Vamos ao código:
#include <UIPEthernet.h>
#include <PubSubClient.h>
#define CLIENT_ID "HofferPLC"
#define PUBLISH_DELAY 5000
int led_a = 6;
int led_b = 7;
int led_c = 8;
int led_d = 9;
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
const char* mqtt_server = "broker.mqtt-dashboard.com";
long previousMillis;
EthernetClient ethClient;
PubSubClient mqttClient;
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Mensagem Recebida [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Liga o LED Se mensagem = 1
if ((char)payload[0] == 'A') {
digitalWrite(led_a, HIGH);
}
if ((char)payload[0] == 'B') {
digitalWrite(led_b, HIGH);
}
if ((char)payload[0] == 'C') {
digitalWrite(led_c, HIGH);
}
if ((char)payload[0] == 'D') {
digitalWrite(led_d, HIGH);
}
if ((char)payload[0] == 'a') {
digitalWrite(led_a, LOW);
}
if ((char)payload[0] == 'b') {
digitalWrite(led_b, LOW);
}
if ((char)payload[0] == 'c') {
digitalWrite(led_c, LOW);
}
if ((char)payload[0] == 'd') {
digitalWrite(led_d, LOW);
}
}
void sendData() {
char msgBuffer[20];
if(mqttClient.connect(CLIENT_ID)) {
mqttClient.publish("publica_hoffer", "Teste Hoffer");
Serial.print("Mensagem Enviada");
}
}
void reconnect() {
// Loop until we're reconnected
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (mqttClient.connect("arduinoMQTT")) {
Serial.println("connected");
// Once connected, publish an announcement...
mqttClient.publish("publica_hoffer","hello world");
// ... and resubscribe
mqttClient.subscribe("subscreve_hoffer");
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
pinMode(led_a, OUTPUT);
pinMode(led_b, OUTPUT);
pinMode(led_c, OUTPUT);
pinMode(led_d, OUTPUT);
// setup serial communication
Serial.begin(9600);
while(!Serial) {};
Serial.println(F("MQTT Arduino Demo"));
Serial.println();
// setup ethernet communication using DHCP
if(Ethernet.begin(mac) == 0) {
Serial.println(F("Unable to configure Ethernet using DHCP"));
for(;;);
}
Serial.println(F("Ethernet configured via DHCP"));
Serial.print("IP address: ");
Serial.println(Ethernet.localIP());
Serial.println();
// setup mqtt client
mqttClient.setClient(ethClient);
mqttClient.setServer(mqtt_server, 1883);
mqttClient.setCallback(callback);
Serial.println(F("MQTT client configured"));
Serial.println();
Serial.println(F("Ready to send data"));
previousMillis = millis();
}
void loop() {
if (!mqttClient.connected()) {
reconnect();
}
// it's time to send new data?
if(millis() - previousMillis > PUBLISH_DELAY) {
sendData();
previousMillis = millis();
}
mqttClient.loop();
}
ATENÇÃO: Para iniciar a programação da aplicação MQTT você precisa ter instalado na IDE do Arduino as seguintes bibliotecas:
UIPEthernet.h
PubSubClient.h
Ambas estão disponíveis para download no Gerenciador de Bibliotecas da IDE do Arduino.
A seguir faremos a análise dos principais pontos do software do Arduino:
Primeiramente criamos uma ID única para a nossa placa, você pode dar outros nomes para a mesma, mas não utilize nada muito genérico para evitar conflitos com o broker:
#define CLIENT_ID "HofferPLC"
Depois escolhemos o nosso Broker. Neste exemplo utilizaremos o MQTT Dashboard, que tem o endereço broker.mqtt-dashboard.com. Existem outros disponíveis como o iot.eclipse.org e o test.mosquitto.org
const char* mqtt_server = "broker.mqtt-dashboard.com";
Em seguida temos a rotina de callback. Ela é utilizada quando a placa recebe uma mensagem do broker e é responsável por interpreta-la. Para o funcionamento do acionamento remoto das saídas da placa, definimos que quando a mensagem (payload) for uma letra maiúscula ela liga uma saída (nomeamos as saídas como led_a, led_b, led_c e led_d) e quando for uma letra minúscula desliga a saída correspondente:
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Mensagem Recebida [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// Liga o LED Se mensagem = 1
if ((char)payload[0] == 'A') {
digitalWrite(led_a, HIGH);
}
if ((char)payload[0] == 'B') {
digitalWrite(led_b, HIGH);
}
if ((char)payload[0] == 'C') {
digitalWrite(led_c, HIGH);
}
if ((char)payload[0] == 'D') {
digitalWrite(led_d, HIGH);
}
if ((char)payload[0] == 'a') {
digitalWrite(led_a, LOW);
}
if ((char)payload[0] == 'b') {
digitalWrite(led_b, LOW);
}
if ((char)payload[0] == 'c') {
digitalWrite(led_c, LOW);
}
if ((char)payload[0] == 'd') {
digitalWrite(led_d, LOW);
}
}
A seguir temos a rotina de envio de mensagens, neste exemplo fazemos com que a placa mande uma mensagem de texto “Teste Hoffer” para o celular. É só um teste e em breve modificaremos esta rotina.
void sendData() {
char msgBuffer[20];
if(mqttClient.connect(CLIENT_ID)) {
mqttClient.publish("publica_hoffer", "Teste Hoffer");
Serial.print("Mensagem Enviada");
}
}
A última rotina desenvolvida é a de reconexão. Caso o servidor MQTT caia, esta função será responsável por tentar uma nova conexão a cada 5 segundos:
void reconnect() {
// Faz o loop até conectar
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (mqttClient.connect("arduinoMQTT")) {
Serial.println("connected");
// Once connected, publish an announcement...
mqttClient.publish("publica_hoffer","hello world");
// ... and resubscribe
mqttClient.subscribe("subscreve_hoffer");
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
Agora, dentro da função SETUP() iniciamos a rede Ethernet e a comunicação MQTT:
if(Ethernet.begin(mac) == 0) {
Serial.println(F("Unable to configure Ethernet using DHCP"));
for(;;);
}
////////////////////////////////////////////////////////////////////
mqttClient.setClient(ethClient);
mqttClient.setServer(mqtt_server, 1883);
mqttClient.setCallback(callback);
Serial.println(F("MQTT client configured"))
Você deve ter notado que em várias partes do código aparecem mensagens que são enviadas a porta serial. Trabalhe com o monitor serial aberto na IDE Arduino para você acompanhar os passos de conexão, envio e recebimento de mensagens.
A seguir passamos para a aplicação no celular:
Baixe o aplicativo DASH MQTT da loja de aplicativos e iremos configura-lo para acionar as saídas da placa:
Abra o aplicativo e a seguinte tela será apresentada:
Clique no sinal de “+” para criar uma nova dashboard, na tela entre um nome para sua aplicação e também o endereço do broker, conforme figura abaixo:
Com o dashboard criado, você deverá visualiza-lo na tela principal do app:
Em seguida, clique no dashboard criado para inserir os componentes:
Clique no sinal de “+” para inserir os componentes, será apresentada uma lista de opções:
Selecione “Switch/Button” para inserir um botão que acionará uma das saídas digitais da placa. Entre um nome para o botão e também a configuração de letra maiúscula para ligar e letra minúscula para desligar. Neste primeiro botão configuramos a letra “A” e “a”:
Clique no botão salvar no lado superior esquerdo da tela e você terá seu primeiro botão:
Segure o botão por alguns segundos até o menu apresentado acima aparecer. Selecione “Clone” para criar os outros botões.
Configure-os da mesma maneira que o botão LED A, desta vez com as letras “B” e “b”, “C” e “c” e finalmente “D” e “d”.
O resultado final será o apresentado abaixo:
Conecte a placa HF-003 a energia e ao seu roteador, acompanhe pelo monitor serial a conexão fda placa com o Broker e em seguida acione os botões em seu celular para acionar as saídas digitais: