MQTT – Conectando seu arduino à nuvem – PARTE 3

Fala galera!!!!

Mais um post sobre o MQTT.

Dessa vez eu irei demonstrar como fazer a tão esperada ligação entre o mosquitto e o nosso arduino. Se você leu a parte 1 e a parte 2 sabem que agora iremos fazer a junção do que aprendemos nos posts anteriores.

Então vamos lá!

Para iniciar, precisamos obviamente mudar um pouco aquela imagem que colocamos no primeiro post, ja que aquela imagem representa somente uma via de comunicação, onde o arduino espalha a mensagem para vários outros periféricos que só ficam na escuta. No exemplo, mostrei que o arduino fica ‘propagando’ infinitamente o estado do led ou o estado de um sensor para quem estiver ouvindo. Mas e se quisermos alterar esse valor, como isso seria possível?

Além do desenho maravilhoso vemos que é possível que o mesmo dispositivo possa ser ‘subscriber’ e ‘pusbliser’ ao mesmo tempo sem problema algum!

Então vamos começar a instalar os pacotes necessários no arduino!

Instalando o pacote ‘pubsclient’ no arduino.

Para instalar um pacote no arduino é simples, é só você importar o arquivo zipado para dentro dele.

para isso vamos baixar o zip do github do criador:
https://github.com/knolleary/pubsubclient

Agora é só ir em sketch / incluir Biblioteca/ Adicionar biblioteca ZIP:

Pronto você ja está pronto para utilizar o MQTT.

Mão na massa!!!

Agora vamos realmente integrar tudo!

vou explicar passo a passo como devemos fazer e logo abaixo coloco o código comentado.

O grande ponto positivo de executar o arduino no mosquitto é que realmente não é necessário configurar um ip fixo ou saber exatamente qual ip cada arduino se encontra, pois cada um possue seu Mac address então ficará facil.

  1. Primeiro passo obviamente é se conectar à sua rede wifi , com o ssid, usuário e senha
  2. Depois precisamos configurar o ip, usuário e senha do servidor que está o mosquitto;
  3. Precisamos configurar quais serão nossos serviços (publisher e subscriber)
  4. Configurar uma ação para quando o arduino receber um comando que está escutando
  5. Manter isso em um loop até o fim da eternidade

Agora Eu particularmente gosto de fazer funções para checar se certas atividades ainda são presentes, como por exemplo checar se o wifi ainda está ativo ou se o mosquitto ainda está conectado. Faço isso pois pode acontecer do seu wifi cair ou você perder a conexão da internet e o seu arduino simplesmente vai acreditar que está enviando dado para algum lugar ou pode dar até algum erro de execução e ele parar de executar o que precisa, e você pensar que ele está conectado.

Além disso eu gosto de separar o máximo possível do código em funções distintas (mania de OOP)

então eu tenho:

  • Função que configura o wifi
  • Função que checa se ela ainda está ativa
  • Função que conecta no mosquitto
  • Função de execução quando o arduino recebe um dado no subscriber
  • Função que me envia o estado do sensor que eu escolhi

Por padrão eu estou utilizando a seguinte chamada de publisher e subscriber:

/arduino/macaddress/GET que vai ficar recebendo o estado do sensor

/arduino/macaddress/SET que vai modificar o valor do sensor.

Escolhi por utilizar o mac no meio da chamada para garantir que caso eu tenha mais de 1 dispositivo, um não sobreponha o outro na hora de enviar o estado específico do seu pino.

Agora vamos ao código:

//Desenvolvido por  (Marcus Vincius Brasizza)
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

const char* ssid = "SEUSSID";
const char* password = "SUASENHADOWIFI";
const char* mqtt_server = "ip_mqtt";
const char* login_mqtt = "user_mqtt";
const char* senha_mqtt = "pass_mqtt";
long lastMsg = 0;
const int device = D5;  //DEVICE NO CASO DE SOMENTE SER UMA LAMPADA 

/*
* @ Modelo da chamada do publish ou post:
* /ambiente/MAC-ADDRESS/GET <- Fica emitindo a informação do estado do pino
* /ambiente/MAC-ADDRESS/SET <- Recebe um novo estado para o pino
*/

String publishService = "";
char servicePublish[65] ;
// ^^ Variaveis que irão receber a string de publish, ou seja que irão ficar publicando o resultado na web ^^

String  postService = "";
char servicePost[65] ;
// ^^ Variaveis que irão enviar um valor para o ESP fazendo as alterações no estado de acordo com o valor enviado

WiFiClient espClient;
PubSubClient client(espClient);


void configura_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connectando em: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi conectado");
  Serial.println("IP: ");
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.macAddress());
  String MACADDR = (WiFi.macAddress());
  MACADDR.replace(":","");
  //Aqui eu retiro a pontuação do mac para pegar somente o valor limpo
  //Configurando o link de publish
  publishService +=   "/arduino/";
  publishService +=   MACADDR.c_str();
  publishService +=   "/GET";
  publishService.toCharArray(servicePublish, 65);
  
  //Configurando o link de post
  postService +=   "/arduino/";
  postService +=   MACADDR.c_str();
  postService +=   "/SET";
  postService.toCharArray(servicePost, 65);  
// Aqui eu transformo o as strings em char, pois o parametro do publish e subscriber somente aceita char
}

void checar_wifi(){
  if(WiFi.status() != WL_CONNECTED){
    Serial.println("Conexão perdida");
    configura_wifi(); 
  } 
}

//Essa função irá retornar o estado do pino, a não ser que seja o led interno (LED_BUILTIN) que o estado lógico é invertido
char * estadoSensor(int device){
  char msg[75] ;
  int ledState = digitalRead(device);
   sprintf(msg, "%d", ledState);
    Serial.println(msg);
    return (msg);
}



void callback(char* topic, byte* payload, unsigned int length) { 

  // Liga o led caso o valor do serviço SET enviado seja 1 
  if ((char)payload[0] == '1') {
    digitalWrite(device, HIGH);   
  } else {
    digitalWrite(device, LOW);  // Desliga o led
  }

}

void conectaMQTT(){
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  String clientId = "CASAINTELIGENTE-RASPIBR-";
  clientId += String(random(0xffff), HEX);
   if (client.connect(clientId.c_str(), login_mqtt, senha_mqtt)) {
      Serial.println("conectado ao MQTT");
      char * sensorData = estadoSensor(device);
      client.publish(servicePublish,sensorData);
      
      client.subscribe(servicePost);
    } else {
      Serial.print("erro ao conectar ao MQTT, erro=");
      Serial.print(client.state());
      Serial.println(" tentando novamente em 5 segundos");
     
      delay(5000);
    }
  
}




void setup() {
pinMode(device, OUTPUT);     
Serial.begin(115200);
configura_wifi();  
conectaMQTT();
}

void loop() {  
  checar_wifi();
  if (!client.connected()) {
    conectaMQTT();
  }
  client.loop();
  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;  
     //aqui a cada 2 segundos ele envia o estado do sensor no serviço GET
     char * sensorData = estadoSensor(device);
     client.publish(servicePublish,sensorData);
  } 
}

E como vamos testar???

eu utilizo o MQTT box , que é uma extensão do google chrome (Clique aqui no google chrome) , mas você pode baixar outros que quiser.

o resultado é esse ai no vídeo abaixo!!

Espero que tenham gostado e até a proxima!!!!