Quantcast
Channel: MakerHero
Viewing all articles
Browse latest Browse all 418

Controle e Monitoramento IoT com NodeMCU e MQTT

$
0
0

Controle e Monitoramento IoT com NodeMCU e MQTT

O módulo Wifi ESP8266 NodeMCU é uma das mais interessantes placas / plataformas existentes. A razão disso é simples: em uma pequena placa estão disponíveis I/Os, circuitaria de regulação de tensão, conectividade USB para programação (em Lua ou pela Arduino IDE) e conectividade WI-FI (ESP8266 12-E), caracterizando uma placa auto-suficiente para projetos envolvendo IoT, como faremos neste post envolvendo o NodeMCU e MQTT.

NodeMCU - Controle e monitoramento IoT

Será mostrada uma das mais interessantes aplicações desta placa: a conectividade com a nuvem através de MQTT para monitoramento e controle de um output, com um diferencial: a interface com o usuário sendo uma página web.

Funcionamento do MQTT

O MQTT (Message Queue Telemetry Transport) consiste em um protocolo de mensagens leve, criado para comunicação M2M (Machine to Machine). Por exigir muito pouco “poder de fogo” em termos de processamento e banda / consumo de Internet, este é um dos protocolos ideais para dispositivos embarcados. Por esta razão, o MQTT é famoso no conceito IoT (Internet of Things).

Uma comunicação MQTT é composta das seguintes partes: há publishers (quem irá disponibilizar informações), subscribers (quem irá receber as informações) e Broker (servidor MQTT, na nuvem / acessível de qualquer lugar do planeta que contenha conexão com a Internet). Teoricamente, não há limite especificado de subscribers e publishers em uma mesma comunicação MQTT, pois o limite nesse aspecto  é do servidor em lidar com as conexões.

Em suma: publishers enviam informação para o Broker, subscribers recebem informação do Broker e o Broker gerencia a troca de mensagens. Ou seja, o trabalho pesado fica a cargo do Broker, deixando os sistemas embarcados livre para gerenciar outras coisas.

NodeMCU e MQTT

Sem entrar no mérito da especificação do protocolo MQTT (ou seja, byte a byte do protocolo), grosso modo uma mensagem MQTT publicada / enviada possui duas partes importantes:

  • Tópico – “chave” / identificação da informação publicada. É usado para direcionar a informação publicada / enviada a quem assina (quem “dá subscribe”) no tópico. O tópico consiste de uma string (por exemplo: MQTTTesteTopico)
  • Payload – informação que deseja enviar (propriamente dita).

Um publisher, conectado ao Broker (servidor MQTT) , envia/publica as informações em um dado momento. Os subscribers, assim como os publishers, também estão conectados aos brokers e “escutando” mensagens trafegadas com o tópico-alvo. Quando uma mensagem com o tópico alvo é publicada, automaticamente são direcionadas aos subscribers.

Em outras palavras: uma solução em IoT que usa MQTT possui somente um servidor (Broker), sendo todo o restante composto de clients MQTT.

Outra informação importante é que um mesmo client MQTT pode ser subscriber e publisher de diversos tópicos.

Como utilizar o NodeMCU e MQTT

O NodeMCU pode ser programado para interagir com um broker MQTT, ou seja, ele pode ser programado para ser um client MQTT. Antes de ser programado para isso, é necessário:

1 – Preparar a IDE Arduino para programar o NodeMCU. Veja como fazer isso no post Como programar o NodeMCU com IDE Arduino

2 – Baixar e instalar a biblioteca pubsubclient. Para baixar, visite o GitHub do projeto.

Feito isso, devemos escolher um broker MQTT para utilizar. Há inúmeros brokers disponíveis para uso (tanto públicos / sem custo quanto privados / pagos). Dos públicos, eu recomendo fortemente o iot.eclipse.org (broker oficial da equipe que mantém o MQTT), que irá funcionar perfeitamente com o nosso projeto de NodeMCU e MQTT.

Enfim, agora é possível usarmos o NodeMCU como um client MQTT! Para isso, será feito um projeto que permite controlar e monitorar um output do NodeMCU via MQTT. O output em questão é o próprio LED da placa (que, neste caso, está ligado diretamente ao output D0).

Importante:
1)
O LED possui acionamento em lógica invertida, ou seja, para acendê-lo é preciso enviar o estado LOW para D0 e para apagá-lo é necessário enviar estado High. Isto ocorre pois o output está ligado ao catodo do LED na placa.

2) O ID MQTT no código serve como identificador para o broker, o permitindo gerenciar as conexões. Se você escolher um ID MQTT que já está sendo utilizado, a conexão do mesmo será interrompida para a sua ser estabelecida. Isto pode gerar grandes transtornos para ambos os dispositivos com mesmo ID MQTT. Desta forma, recomendo que o ID MQTT seja escolhido como algo aleatório (assim garante-se unicidade do mesmo).

3) Como não foi utilizado nenhum componente além da própria NodeMCU, não há circuito esquemático envolvido (ou seja, em termos de hardware é preciso somente do NodeMCU!)

Programa NodeMCU e MQTT

Vamos à programação!

#Programa: NodeMCU e MQTT - Controle e Monitoramento IoT
#Autor: Pedro Bertoleti

#include <ESP8266WiFi.h> // Importa a Biblioteca ESP8266WiFi
#include <PubSubClient.h> // Importa a Biblioteca PubSubClient

//defines:
//defines de id mqtt e tópicos para publicação e subscribe
#define TOPICO_SUBSCRIBE "MQTTFilipeFlopEnvia"     //tópico MQTT de escuta
#define TOPICO_PUBLISH   "MQTTFilipeFlopRecebe"    //tópico MQTT de envio de informações para Broker
                                                   //IMPORTANTE: recomendamos fortemente alterar os nomes
                                                   //            desses tópicos. Caso contrário, há grandes
                                                   //            chances de você controlar e monitorar o NodeMCU
                                                   //            de outra pessoa.
#define ID_MQTT  "HomeAut"     //id mqtt (para identificação de sessão)
                               //IMPORTANTE: este deve ser único no broker (ou seja, 
                               //            se um client MQTT tentar entrar com o mesmo 
                               //            id de outro já conectado ao broker, o broker 
                               //            irá fechar a conexão de um deles).
                               

//defines - mapeamento de pinos do NodeMCU
#define D0    16
#define D1    5
#define D2    4
#define D3    0
#define D4    2
#define D5    14
#define D6    12
#define D7    13
#define D8    15
#define D9    3
#define D10   1


// WIFI
const char* SSID = "SSID"; // SSID / nome da rede WI-FI que deseja se conectar
const char* PASSWORD = "SENHA"; // Senha da rede WI-FI que deseja se conectar
 
// MQTT
const char* BROKER_MQTT = "iot.eclipse.org"; //URL do broker MQTT que se deseja utilizar
int BROKER_PORT = 1883; // Porta do Broker MQTT


//Variáveis e objetos globais
WiFiClient espClient; // Cria o objeto espClient
PubSubClient MQTT(espClient); // Instancia o Cliente MQTT passando o objeto espClient
char EstadoSaida = '0';  //variável que armazena o estado atual da saída
 
//Prototypes
void initSerial();
void initWiFi();
void initMQTT();
void reconectWiFi(); 
void mqtt_callback(char* topic, byte* payload, unsigned int length);
void VerificaConexoesWiFIEMQTT(void);
void InitOutput(void);

/* 
 *  Implementações das funções
 */
void setup() 
{
    //inicializações:
    InitOutput();
    initSerial();
    initWiFi();
    initMQTT();
}
 
//Função: inicializa comunicação serial com baudrate 115200 (para fins de monitorar no terminal serial 
//        o que está acontecendo.
//Parâmetros: nenhum
//Retorno: nenhum
void initSerial() 
{
    Serial.begin(115200);
}

//Função: inicializa e conecta-se na rede WI-FI desejada
//Parâmetros: nenhum
//Retorno: nenhum
void initWiFi() 
{
    delay(10);
    Serial.println("------Conexao WI-FI------");
    Serial.print("Conectando-se na rede: ");
    Serial.println(SSID);
    Serial.println("Aguarde");
    
    reconectWiFi();
}
 
//Função: inicializa parâmetros de conexão MQTT(endereço do 
//        broker, porta e seta função de callback)
//Parâmetros: nenhum
//Retorno: nenhum
void initMQTT() 
{
    MQTT.setServer(BROKER_MQTT, BROKER_PORT);   //informa qual broker e porta deve ser conectado
    MQTT.setCallback(mqtt_callback);            //atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega)
}
 
//Função: função de callback 
//        esta função é chamada toda vez que uma informação de 
//        um dos tópicos subescritos chega)
//Parâmetros: nenhum
//Retorno: nenhum
void mqtt_callback(char* topic, byte* payload, unsigned int length) 
{
    String msg;

    //obtem a string do payload recebido
    for(int i = 0; i < length; i++) 
    {
       char c = (char)payload[i];
       msg += c;
    }
  
    //toma ação dependendo da string recebida:
    //verifica se deve colocar nivel alto de tensão na saída D0:
    //IMPORTANTE: o Led já contido na placa é acionado com lógica invertida (ou seja,
    //enviar HIGH para o output faz o Led apagar / enviar LOW faz o Led acender)
    if (msg.equals("L"))
    {
        digitalWrite(D0, LOW);
        EstadoSaida = '1';
    }

    //verifica se deve colocar nivel alto de tensão na saída D0:
    if (msg.equals("D"))
    {
        digitalWrite(D0, HIGH);
        EstadoSaida = '0';
    }
    
}
 
//Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair)
//        em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito.
//Parâmetros: nenhum
//Retorno: nenhum
void reconnectMQTT() 
{
    while (!MQTT.connected()) 
    {
        Serial.print("* Tentando se conectar ao Broker MQTT: ");
        Serial.println(BROKER_MQTT);
        if (MQTT.connect(ID_MQTT)) 
        {
            Serial.println("Conectado com sucesso ao broker MQTT!");
            MQTT.subscribe(TOPICO_SUBSCRIBE); 
        } 
        else 
        {
            Serial.println("Falha ao reconectar no broker.");
            Serial.println("Havera nova tentatica de conexao em 2s");
            delay(2000);
        }
    }
}
 
//Função: reconecta-se ao WiFi
//Parâmetros: nenhum
//Retorno: nenhum
void reconectWiFi() 
{
    //se já está conectado a rede WI-FI, nada é feito. 
    //Caso contrário, são efetuadas tentativas de conexão
    if (WiFi.status() == WL_CONNECTED)
        return;
        
    WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI
    
    while (WiFi.status() != WL_CONNECTED) 
    {
        delay(100);
        Serial.print(".");
    }
  
    Serial.println();
    Serial.print("Conectado com sucesso na rede ");
    Serial.print(SSID);
    Serial.println("IP obtido: ");
    Serial.println(WiFi.localIP());
}

//Função: verifica o estado das conexões WiFI e ao broker MQTT. 
//        Em caso de desconexão (qualquer uma das duas), a conexão
//        é refeita.
//Parâmetros: nenhum
//Retorno: nenhum
void VerificaConexoesWiFIEMQTT(void)
{
    if (!MQTT.connected()) 
        reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita
    
     reconectWiFi(); //se não há conexão com o WiFI, a conexão é refeita
}

//Função: envia ao Broker o estado atual do output 
//Parâmetros: nenhum
//Retorno: nenhum
void EnviaEstadoOutputMQTT(void)
{
    if (EstadoSaida == '0')
      MQTT.publish(TOPICO_PUBLISH, "D");

    if (EstadoSaida == '1')
      MQTT.publish(TOPICO_PUBLISH, "L");

    Serial.println("- Estado da saida D0 enviado ao broker!");
    delay(1000);
}

//Função: inicializa o output em nível lógico baixo
//Parâmetros: nenhum
//Retorno: nenhum
void InitOutput(void)
{
    //IMPORTANTE: o Led já contido na placa é acionado com lógica invertida (ou seja,
    //enviar HIGH para o output faz o Led apagar / enviar LOW faz o Led acender)
    pinMode(D0, OUTPUT);
    digitalWrite(D0, HIGH);          
}


//programa principal
void loop() 
{   
    //garante funcionamento das conexões WiFi e ao broker MQTT
    VerificaConexoesWiFIEMQTT();

    //envia o status de todos os outputs para o Broker no protocolo esperado
    EnviaEstadoOutputMQTT();

    //keep-alive da comunicação com broker MQTT
    MQTT.loop();
}

Desta forma, seu NodeMCU vira um client MQTT acessível de qualquer lugar do planeta!

Interação com o NodeMCU

Vimos até agora que é possível transformar a incrível placa NodeMCU em um client MQTT acessível por todo o planeta. Mas e para interagir com ele (ligar e desligar o output), como faremos?

Para isso, desenvolvi uma interface web que pode ser baixada clicando AQUI. Você pode hospedar essa interface em QUALQUER servidor web ou mesmo rodar no seu próprio computador / rodar localmente (desde que o computador possua conexão com Internet, claro)!

Esta interface web é basicamente um websocket que se comunica diretamente com o broker, por isso pode estar rodando em qualquer lugar com disponibilidade de Internet que funciona.

Observe a figura abaixo:

Figura 1 – screenshot da página de controle do NodeMCU

Figura 1 – screenshot da página de controle do NodeMCU

Para funcionar:

1 – Definir as strings dos tópicos de publish e subscribe e clicar em “Conectar”. Aguardar a mensagem Conectado ao Broker! aparecer na sessão “Debug / respostas do servidor”.

2 – Clicar em Ligar e Desligar para comandar o LED da placa NodeMCU. Observe que na sessão “Status do output” irá constar o estado atual do LED. Este estado é recebido do próprio NodeMCU, via MQTT (o que torna este controle um controle em tempo real).

3 – Se divertir com o NodeMCU e MQTT!

Gostou ? Ajude-nos a melhorar o blog atribuindo uma nota a este tutorial (estrelas no final do artigo), comente e visite nossa loja FILIPEFLOP!

Site: Blog FILIPEFLOP


Viewing all articles
Browse latest Browse all 418