Objetivo

           Com o conhecimento adquirido em: Introdução ao MQTT, Segurança no MQTT e Certificados de Segurança no MQTT. Apresentaremos nesse tutorial um protótipo de monitoramento e controle de residência através do aplicativo mobile chamado: MQTTDash e o broker MQTTBox, esse último já explanado anteriormente. O propósito desse tutorial é exemplificar o funcionamento prático da comunicação MQTT, de forma a fixar o conteúdo aprendido e te auxiliar em seus projetos pessoais. Dividiremos essa postagem nos seguintes tópicos: -Clique se quiser ser encaminhado(a) para algum trecho específico do texto.

Introdução
Lista de Materiais
MQTT
NodeMCU V3 -ESP8266 LoLin
DHT22
Como baixar a placa ESP8266 na IDE do Arduino
Baixando a Biblioteca PubSubClient
Configurando o MQTTBox para o ESP8266
Protótipo de Casa Monitorada -Montagem na Protoboard
Protótipo de Casa Monitorada - Biblioteca DHT
Protótipo de Casa Monitorada -Programação
Protótipo de Casa Monitorada -MQTTBox
Protótipo de Casa Monitorada -Aplicativo
Protótipo de Casa Monitorada -Funcionando


Para acompanhar esse tutorial é necessário que você tenha visto os tutoriais anteriores, pois trabalharemos com conhecimentos adquiridos previamente, além de utilizarmos a ferramenta MQTTBox, apresentada em: Introdução ao MQTT

 

Introdução

 

            Em meio ao avanço da tecnologia e as infinitas possibilidades que surgiram com esse crescimento, surgiu a domótica. Originada da palavra francesa Domotique, sendo que domus significa casa e imotique automático, a palavra é constantemente utilizada quando nos referimos a Casas Inteligentes, essas casas são otimizadas para que seu controle e monitoramento seja realizado por um software, de forma a oferecer maior comodidade e segurança aos moradores. Outrossim, um projeto de automação residencial pode ser voltado para acessibilidade, pois com um aplicativo mobile, um cadeirante consegue ter controle da iluminação de sua residência sem precisar acionar os interruptores correspondentes. Um outro uso é em projetos sustentáveis, com o monitoramento é possível controlar gastos desnecessários com energia elétrica.

 

           No nosso projeto, vamos controlar 4 Leds de forma a simular a iluminação de quatro cômodos diferentes de uma casa, sendo esses: Sala, Quarto, Cozinha e Banheiro, além disso, vamos monitorar a temperatura e a umidade.


Domótica


Lista de Materiais:
           Para concluir a atividade disposta nesse tutorial, tenha os seguintes componentes:

 

01- Placa NodeMCU V3 - ESP8266 - CH340

01- Cabo micro USB

04- Jumper Macho-macho

04- Led Alto Brilho Branco – 5mm

04- Resistor 220Ω

01- Módulo Sensor DHT22

02- Protoboard 400 pontos

 

           Caso não tenha, você pode adquiri-los clicando em cada componente ou acessando o nosso site: https://www.curtocircuito.com.br/

MQTT

 

            Para realização do nosso protótipo faremos uso da comunicação MQTT, explanada nos tutoriais anteriores. O MQTT é um protocolo de comunicação voltado para o uso em IoT- Internet of Things, em português, Internet das Coisas. É leve e seu funcionamento se baseia na troca de informações entre Subscriber (Subscrito) e Publisher (Publicador), sendo que o mensageiro responsável por encaminhar e receber os dados é chamado de broker, podendo esse ser hospedado na nuvem ou local.

 

           O exemplo abaixo é semelhante ao nosso protótipo, o sensor de temperatura atua como Publisher e publica o dado medido no tópico “temp”, esse dado é transmitido ao Broker que encaminha para todos os clientes que estão subscritos nesse mesmo tópico “temp”, no caso, o Computador e o Celular. Para maior compreensão do MQTT, consulte os tutoriais anteriores.

 

MQTT Funcionamento

NodeMCU V3 - ESP8266 LoLin

 

            Para realizar essa comunicação, é necessário o uso da internet, em razão disso, utilizaremos o NodeMCU V3 - ESP8266 (LoLin), que é uma placa microcontroladora que realiza comunicação WiFi sem a necessidade do uso de um módulo externo para isso.

ESP8266

          O ESP8266 apresenta algumas vantagens em relação Arduino Uno R3, essas diferenças são expressas na tabela a seguir:

Comparação Arduino e ESP8266

          Para mais informações da placa, acesse:

 

Datasheet: NodeMCU V3 - ESP8266 - CH340

 

          Sendo a pinagem da placa expressa pela seguinte ilustração:


Pinos ESP8266 LoLin
Tabela ESP8266 Pinos


DHT22

 

           O DHT22 é um sensor que realiza medições de umidade e temperatura, permitindo leituras na faixa dos -40°C a 80°C, com umidade de 0 a 100%. Seu funcionamento é baseado no uso de um sensor capacitivo de umidade e um termistor, com função de medir a temperatura do ar circundante. Utilizaremos o módulo DHT22, que é esse mesmo sensor em sua forma embarcada.

 

           A pinagem do DHT22 e do módulo DHT22 é:

Pinos DHT22

 

            Note que o módulo não conta com o pino ENB, pois o mesmo não é necessário para uso do sensor.

 

            Abra a sua IDE do Arduino e prossiga com o tutorial, caso não tenha, baixe e instale gratuitamente através do site oficial:

 

https://www.arduino.cc/en/main/software#

 

            Se tiver, prossiga com o tutorial.

 

            Como baixar a placa ESP8266 na IDE do Arduino

 

            Se você nunca utilizou a placa ESP8266 com a IDE do Arduino, será necessário instalar a extensão de placa Generic ESP8266 Module na IDE.

 

            Realize uma busca caso queira confirmar. Na Interface da IDE, clique no canto superior em Ferramentas > Placa:_______ , em seguida realize uma busca pelos modelos de placa, procure a Generic ESP8266 Module, caso não tenha, ensinaremos o processo para inserção da mesma, do contrário, pule essa etapa do tutorial.

Busca pela placa Generic ESP8266 na IDE
           Na IDE, clique em Arquivo> Preferências

 

Preferências IDE

           Em seguida, clique nesse pequeno ícone ao lado da caixa de texto, uma janela será aberta.

Inclusão de placas na IDE

           
             Insira o link abaixo na caixa de texto, caso já tenha algum link nesse espaço, não apague, pressione ENTER para ir para a linha seguinte e cole o novo link:

 

http://arduino.esp8266.com/stable/package_esp8266com_index.json

código placa ESP8266 na IDE

           Clique em   e em seguida clique  em  novamente.

           De volta à tela inicial do Arduino, entre novamente em Ferramentas>Placa:_____ e vá para Gerenciador de Placas...


Gerenciador de placas da IDE

 

 

             
           Uma janela será aberta, procure: esp8266 e ao encontrar o esp8266 by ESP8266 Community clique em Instalar.

Instalar placa na IDE

 

 

           Depois de instalar, clique em fechar
           Confira se sua placa está disponível em Ferramentas> Placa:______

Generic ESP8266 Module


Baixando a Biblioteca PubSubClient

 

           Para realizar a nossa comunicação MQTT com o ESP8266 é necessário que seja instalada a Biblioteca PubSubClient.

 

           Clique em Ferramentas>Gerenciar Bibliotecas...

Gerenciar Bibliotecas

           Realize uma busca por “PubSubClient”, instale a biblioteca feita por Nick O’Leary clicando em Instalar.

PubSubClient

            Depois de instalar, vamos voltar para a tela inicial do Arduino e abrir o exemplo dedicado ao ESP8266.

 

            Clique em Arquivo>Exemplos>PubSubClient>mqtt_esp8266

Exemplo PubSubClient

           Tendo aberto o programa, vamos realizar as configurações iniciais para teste de comunicação MQTT entre o ESP8266 e a plataforma MQTTBox.

 

           Para esse teste inicial, eu vou inserir o nome da minha rede Wi-Fi e a senha da mesma nos seguintes espaços:

Conexão Wi-Fi ESP8266

           Dessa forma:

ESP8266 Wi-Fi

           Por enquanto usarei o broker do próprio programa.

 

           Prosseguindo com as configurações, agora vou configurar os tópicos de publicação e assinatura do ESP8266.

Tópicos MQTT

             Vou modificar o nome dos meus tópicos, é importante realizar essa mudança porque esses tópicos são do exemplo, em razão disso, muitas pessoas publicam e subscrevem neles, o que dificulta a análise.

Publicação e Subscrição no ESP8266

 

           No final do programa existe mais uma função de client.publish, insira o mesmo nome de tópico que você colocou no client.publish anterior.

Função de publicação do ESP8266

            Abaixo está disponível esse exemplo, eu me permiti fazer mais algumas alterações que não interferem no funcionamento, traduzi as frases que serão printadas e modifiquei o tempo da mensagem que será encaminhada periodicamente, além disso, comentei cada função para facilitar a compreensão do código.

 

/************************************************************************************************** 
* Programa: Tutorial Comunicação MQTT
* Autor: Curto Circuito
* Descrição: Programa baseado no exemplo mqtt_esp8266 do autor Nick O'Leary
***************************************************************************************************/
#include <ESP8266WiFi.h> //inclusão da biblioteca WiFi do ES8266 #include <PubSubClient.h> //inclusão da biblioteca PubSubClient const char* ssid = "Nome da Rede"; //Insira o nome da sua rede Wi-Fi no espaço "Nome da sua rede" const char* password = "senhadarede"; //No espaço "Senha da sua rede", insira sua senha Wi-Fi const char* mqtt_server = "broker.mqtt-dashboard.com"; //Broker da comunicação MQTT WiFiClient espClient; //Cria o cliente WiFi que pode ser conectado ao endereço de IP e porta especificados PubSubClient client(espClient); //Recebe como entrada o WiFi Client definido acima unsigned long lastMsg = 0; #define MSG_BUFFER_SIZE (50) char msg[MSG_BUFFER_SIZE]; int value = 0; void setup() { //Laço de configuração pinMode(BUILTIN_LED, OUTPUT); //Define o LED próprio do ESP8266 como saída Serial.begin(115200); //Baudrate da comunicação serial setup_wifi(); //Chama o laço "setup_wifi" client.setServer(mqtt_server, 1883); //Utiliza o broker definido em mqtt_server e a porta 1883 client.setCallback(callback); //Quando uma mensagem for recebida, executa o laço callback } void setup_wifi() { //Laço de configuração WiFi delay(10); //Atraso de 10ms Serial.println(); //Quebra de linha Serial.print("Conectando com "); //Printa na serial "Conectado com" Serial.println(ssid); //Printa nome da rede definido em ssid WiFi.begin(ssid, password); //WiFi inicializa com o nome da rede e a senha while (WiFi.status() != WL_CONNECTED) { //Enquanto o status da conexão WiFi for diferente de conectado delay(500); //Atraso de 0,5s Serial.print("."); //Printa "." } randomSeed(micros()); Serial.println(); //Quebra de linha Serial.println("WiFi conectado"); //Printa na serial "WiFi conectado" Serial.println("Endereço de IP: "); //Printa na serial "Endereço de IP:" Serial.println(WiFi.localIP()); //Aparece na serial o seu IP } void callback(char* topic, byte* payload, unsigned int length) { //Laço callback (tópico, mensagem, tamanho da mensagem) Serial.print("Mensagem recebida ["); //Printa "Mensagem recebida [" Serial.print(topic); //Printa o tópico Serial.print("] "); //Printa "]", ficando "Mensagem recebida[tópico]" for (int i = 0; i < length; i++) { //Enquanto i for menor que o comprimento da mensagem, é deslocada uma letra, fazendo aparecer o texto Serial.print((char)payload[i]); //Printa a mensagem com o limite de 50 caracteres } Serial.println(); //Quebra de linha if ((char)payload[0] == '1') { //Acende o LED do ESP8266 se a mensagem recebida for 1 digitalWrite(BUILTIN_LED, LOW); //Manda nível baixo para o LED, ligando-o, já que o mesmo está normalmente em nível lógico alto } else { //Caso contrário digitalWrite(BUILTIN_LED, HIGH); //Manda nível lógico alto paa o LED, desligando. } } void reconnect() { //Laço de reconexão while (!client.connected()) { //Permanece no loop até ser realizada a reconexão Serial.print("Aguardando conexão MQTT..."); //Printa "Aguardando conexão MQTT..." if (client.connect("ESP8266Client")) { //Se o cliente for conectado Serial.println("conectado"); //Printa "conectado" client.publish("publicacao_do_esp8266", "hello world"); //Publica no tópico "publicação_do_es8266" a mensagem "hello world" client.subscribe("subscricao_do_esp8266"); //Subscreve no tópico "subscricao_do_esp8266" } else { //Caso contrário Serial.print("falhou, rc="); //Printa "falho, rc=" Serial.print(client.state()); //Printa o estado do cliente Serial.println(" tente novamente em 5s"); //Printa "tente novamente em 5s" delay(5000); //Atraso de 5s } } } void loop() { //Laço de loop if (!client.connected()) { //Se o cliente não estiver conectado, vai para o laço de reconexão reconnect(); } client.loop(); //O cliente fica em loop até que seja estabelecida a conexão long now = millis(); //Define now como milisegundo if (now - lastMsg > 5000) { //Se "now" - a última mensagem for maior que 5s lastMsg = now; //A última mensagem = now ++value; //Acrescenta value snprintf (msg, 75, "hello world #%ld", value); //Printa mensagem "hello world", acompanhada do value incrementado Serial.print("Publica mensagem: "); //Printa "Publica mensagem:" Serial.println(msg); //Printa a mensagem client.publish("publicacao_do_esp8266", msg); //Publica a mensagem no tópico "publicacao_do_esp8266" } } /***************************************************************************** * FIM DO PROGRAMA *****************************************************************************/


           Depois de inserir o código na sua IDE, conecte o ESP8266 ao computador através de um cabo USB, selecione a placa como “
Generic ESP8266 Module”.

Generic ESP8266 Module Arduino

             Em seguida, selecione a porta disponível, lembrando que o número da COM pode variar, não se preocupe caso a sua não seja COM18.

Porta COM


Configurando o MQTTBox para o ESP8266

           Abra o MQTTBox, caso não saiba mexer nessa ferramenta, veja os tutoriais anteriores sobre o MQTT.

 

           Ao abrir, clique em Create MQTT Client
           Crie um nome para esse cliente MQTT em “MQTT Client Name”, modifique o protocolo “Protocol” para mqtt/tcp e insira o broker utilizado em nosso programa em “Host”.


MQTTBox pré configuração

 

 

           Finalizando essa configuração inicial, clique em “Save”.

 

           Vamos agora criar o nosso Subscrito, devemos realizar a inscrição no tópico que vai receber a publicação do ESP8266, nomeamos de “publicacao_do_esp8266”.

Publicação no esp8266

           Depois criaremos o nosso Publicador, responsável por publicar a mensagem no ESP8266, assinaremos o tópico “subscricao_do_esp8266”.

Publisher MQTTBox

           Realizando todas as configurações, voltaremos para a IDE e compilaremos nosso programa clicando em  Compilar

 

           Aguarde até o seu programa ser compilado, quando surgir a mensagem informando que ele está carregado, pressione o reset (RST) do seu microcontrolador.

Carregado

 

           Para monitoramento do nosso programa rodando no ESP8266, vamos abrir o Monitor Serial. Para isso devemos clicar em COM , localizado no canto superior direito da IDE.

Monitor Serial

           O nosso microcontrolador foi conectado e iniciou as publicações periódicas, vamos conferir no MQTTBox.

Publicação do ESP8266 no MQTTBox

           O ESP8266 está funcionando perfeitamente como Publicador, publicando mensagens para o Subscrito do MQTTBox, agora vamos testar o ESP8266 como Subscrito, digitaremos uma mensagem no tópico “Topic to publish” e clicaremos em “Publish”.

Publicação do MQTTBox no ESP8266

           Abrimos o monitor serial para conferir se a mensagem chegou ao ESP8266.

MQTTBox publicando mensagem no monitor serial

           Agora publicaremos o 1 para nos certificarmos que o ESP8266 está respondendo às mensagens publicadas, na programação definimos que se fosse publicado o número 1, o LED interno do ESP8266 acenderia, caso contrário, apagaria ou permaneceria apagado.
Acendendo um LED MQTT
           No nosso monitor conseguimos visualizar a mensagem encaminhada

Mensagem publicada no ESP8266 pelo MQTTBox

 

           E o ESP8266 se comporta como o esperado

 

 

 

ESP8266

 


Protótipo de Casa Monitorada –Montagem na Protoboard

 

            De posse dos componentes necessários e de ciência do funcionamento de cada parte, monte o protótipo abaixo. Como o software utilizado (Fritzing) para montagem não conta com o Módulo Sensor DHT22, eu utilizei o Sensor DHT22, note que eu não fiz a ligação do terceiro pino, você também pode utilizar o sensor caso não tenha o módulo, ligando exatamente dessa forma.
Protótipo ligação ESP8266 com DHT22 e LEDsProtótipo MQTT casa monitorada e controlada ESP8266

Protótipo de Casa Monitorada –Biblioteca DHT

 

           Para a nossa programação, utilizaremos a biblioteca do Sensor DHT, caso você não tenha, siga esse passo a passo para inserir na sua IDE.

 

           Clique em Ferramentas > Gerenciar Bibliotecas...

Gerenciar bibliotecas

 

            Ao abrir a janela, faça uma busca por DHT e instale a versão mais recente da biblioteca da Adafruit clicando em “Instalar”.

DHT biblioteca


Protótipo de Casa Monitorada –Programação

 

           Depois de realizada a montagem do protótipo e as bibliotecas pertinentes ao proposto tiverem sido baixadas (PubSubClient.h e DHT.h), vamos iniciar a nossa programação.

 

Primeiro incluímos as bibliotecas, definimos os pinos, constantes e variáveis.

 

Programação 1

 

           Em seguida vamos estabelecer a conexão com o broker, para isso precisamos fazer as configurações de Internet, inserimos nosso SSID (nome da rede) e password (senha da rede), logo em seguida definimos um broker para troca de dados, utilizamos o mesmo broker do exemplo para ESP8266 da biblioteca PubSubClient.

 

PubSubClient rede

 

           Terminamos de declarar nossas variáveis

Programação 3

 

           No laço de configurações, faremos as configurações necessárias para o DHT realizar as leituras.

 

Programação 4

 

           Seguidamente, definiremos os pinos correspondentes aos LEDs e o modo de operação (INPUT/OUTPUT), tendo em mente a tabela dos pinos ESP8266  - IDE.

 

Programação 5

 

           No laço de configuração do WiFi, definiremos como o ESP8266 vai se comportar durante uma tentativa de conexão WiFi, e depois.

 

Programação 6

 

           Em callback, ou retorno, faremos as configurações da mensagem para ser publicada de forma correta no tópico.

 

Programação 6

 

           Em seguida realizaremos um processo que repetiremos para cada LED (Lâmpada de um cômodo da casa), definiremos que se o ESP8266 receber uma mensagem referente à inicial maiúscula desse cômodo, o LED vai acender, se receber a letra minúscula, o LED vai apagar, ou seja:

 

Inicial em caixa alta: Nível lógico alto

 

Inicial em caixa baixa: Nível lógico baixo

 

           Essa mensagem será publicada no tópico casa/publisher, enquanto uma mensagem do estado da lâmpada será publicada no tópico referente ao cômodo, no exemplo da sala: casa/sala.

 

Programação 8

 

           No laço de reconexão, criaremos um ID de cliente randômico, e faremos as configurações necessárias para a reconexão, caso a conexão seja perdida.

 

Programação 9

 

           Em loop faremos as configurações do sensor para que realizemos as publicações de medições na serial e nos tópicos correspondentes.

 

Programação 10
Programação 10

 

           O programa na íntegra está disponível abaixo, assim como o anterior, todas as funções estão comentadas para facilitar o entendimento.

 

/***************************************************************************** * Programa: Tutorial Casa Monitorada * Autor: Curto Circuito * Descrição: Programa de monitoramento e controle residencial através de aplicativo * em comunicação MQTT com o ESP8266 ******************************************************************************/


#include <ESP8266WiFi.h> // Inclusão de biblioteca do ESP8266 WiFi
#include <PubSubClient.h> // Inclusão da biblioteca de Publicador/Subscrito
#define MSG_BUFFER_SIZE (50) // Tamanho do buffer de recebimento
char msg[MSG_BUFFER_SIZE];                                                                        // A Mensagem será do tipo char e do tamanho definido pelo buffer de recebimento // 
#include <Adafruit_Sensor.h>
#include <DHT.h> // Biblioteca do sensor 
#include <DHT_U.h> 
#define DHTPIN 5 // Pino utilizado para o DHT, correspondente ao D1
#define DHTTYPE DHT22 // Define o tipo de DHT
DHT_Unified dht(DHTPIN, DHTTYPE);                                                                 // Considera valor do pino e do tipo de DHT
uint32_t delayMS;                                                                                 // Variável de atraso
const char* ssid = "Minha rede";                                                          // ID de conexão 
const char* password = "senhadarede";                                                              // senha de conexão
const char* mqtt_server = "broker.mqtt-dashboard.com";                                            // endereço do broker
WiFiClient espClient;                                                                             // Cliente ESP WiFi
PubSubClient client(espClient);                                                                   // Cliente ESP Publicador/Subscrito
unsigned long lastMsg = 0;                                                                        // define última mensagem com valor inicial igual a zero
int value = 0;                                                                                    // variável de valor inteiro inicializada em zero

char Sala;                                                                                        // inclui variável char de nome Sala /LED D2/
char Quarto;                                                                                      // inclui variável char de nome Quarto /LED D4/
char Cozinha;                                                                                     // inclui variável char de nome Cozinha /LED D5/ 
char Banheiro;                                                                                    // inclui variável char de nome Banheiro /LED D7/

void setup() {                                                                                    // laço de configuração 
  
  dht.begin();                                                                                    // inicializa DHT
  Serial.println(F("Sensor DHT22"));                                                              // Printa "Sensor DHT22"
  sensor_t sensor;                                                                                // Sensor de temperatura
  
  /////////Sensor de Temperatura//////////
  dht.temperature().getSensor(&sensor);                                                           // imprime detalhes do sensor de temperatura
  Serial.println(F("------------------------------------"));                                      // Printa quebra de linha com ----
  Serial.println(F("Temperatura"));                                                               // Printa "Temperatura"
  Serial.print  (F("Sensor: ")); Serial.println(sensor.name);                                     // Printa o nome do sensor
  Serial.print  (F("Valor máximo: ")); Serial.print(sensor.max_value); Serial.println(F("°C")); //Printa valor máximo de temperatura em graus Celsius
  Serial.print  (F("Valor mínimo: ")); Serial.print(sensor.min_value); Serial.println(F("°C")); //Printa valor mínimo de temperatura em graus Celsius
  Serial.print  (F("Resolução: ")); Serial.print(sensor.resolution); Serial.println(F("°C"));    // Printa a resolução em graus Celsius
  Serial.println(F("------------------------------------"));                                      // quebra de linha com ----
 
  /////////Sensor de Umidade//////////
  dht.humidity().getSensor(&sensor);                                                              // imprime detalhes do sensor de umidade
   Serial.println(F("------------------------------------"));                                     // Printa quebra de linha com ----
  Serial.println(F("Umidade"));                                                                   // Printa "Umidade"
  Serial.print  (F("Sensor: ")); Serial.println(sensor.name);                                     // Printa o nome do sensor
  Serial.print  (F("Valor máximo: ")); Serial.print(sensor.max_value); Serial.println(F("%"));  // Printa o valor máximo de umidade em porcentagem
  Serial.print  (F("Valor mínimo: ")); Serial.print(sensor.min_value); Serial.println(F("%"));  // Printa o valor mínimo de umidade em porcentagem
  Serial.print  (F("Resolução: ")); Serial.print(sensor.resolution); Serial.println(F("%"));     // Printa a resolução em porcentagem
  Serial.println(F("------------------------------------"));                                      // quebra de linha com ----
  
  delayMS = sensor.min_delay / 1000;        
  
  Sala = 4;                                                                                       // define Sala como o LED ligado ao pin 4 (D2 do ESP8266)
  Quarto = 2;                                                                                     // define Quarto como o LED ligado ao pin 2 (D4 do ESP8266)
  Cozinha = 14;                                                                                   // define Cozinha como o LED ligado ao pin 14 (D5 do ESP8266)
  Banheiro = 13;                                                                                  // define Banheiro como o LED ligado ao pin 13 (D7 do ESP8266)

  pinMode(Sala, OUTPUT);                                                                          // configura Sala como saída
  pinMode(Quarto, OUTPUT);                                                                        // configura Quarto como saída
  pinMode(Cozinha, OUTPUT);                                                                       // configura Cozinha como saída
  pinMode(Banheiro, OUTPUT);                                                                      // configura Banheiro como saída
  
  Serial.begin(115200);                                                                           // define baudrate da comunicação serial
  
  setup_wifi();                                                                                   // configuração WiFi
  client.setServer(mqtt_server, 1883);                                                            // seta servidor como mqtt de port 1883
  client.setCallback(callback);                                                                   // seta mensagem de retorno
}

void setup_wifi() {                                                                               // inicia laço de configuração WiFi

  delay(10);                                                                                      // atraso de 0,01S;
  Serial.println("");                                                                             // quebra de linha
  Serial.print("Conectando com ");                                                                // printa na serial "Conectado com"
  Serial.println(ssid);                                                                           // printa ID da rede

  WiFi.begin(ssid, password);                                                                     // inicializa o WiFi com o uso da ID de rede e da senha

  while (WiFi.status() != WL_CONNECTED) {                                                         // enquanto o WiFi não estiver conectado, printa na serial "."
    delay(500);                                                                                   // atraso de 0.5 para aparecimento de um novo "."
    Serial.print(".");                                    
  }                  

  Serial.println("");                                                                             // quebra de linha 
  Serial.println("WiFi conectado");                                                               // printa "WiFi conectado"
  Serial.println("IP: ");                                                                         // printa "IP:"
  Serial.println(WiFi.localIP());                                                                 // printa na serial o IP da conexão local
}

void callback(char* topic, byte* payload, unsigned int length) {                                  // inicializa mensagem de retorno (tópico, mensagem e comprimento) 
  Serial.print("Mensagem recebida [");                                                            // printa "Mensagem recebida ["
  Serial.print(topic);                                                                            // printa o nome do tópico que enviou a mensagem
  Serial.print("] ");                                                                             // fecha "]"
  for (int i = 0; i < length; i++) {                                                              // Para i = 0 e enquanto i for menor que o comprimento da mensagem, inclui um caractere
    Serial.print((char)payload[i]);                                                               // printa o conteúdo da mensagem
  }
  Serial.println("");                                                                             // quebra de linha 
  if ((char)payload[0] == 'S') {                                                                  // se a mensagem recebida for S (maiúsculo)
    digitalWrite(Sala, HIGH);                                                                     // o LED Sala vai para nível lógico alto
    snprintf (msg, MSG_BUFFER_SIZE, "A luz da sala está ligada");                                 // aparece mensagem indicando que a luz da sala está ligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/sala", msg);                                                             // publica a mensagem no tópico "casa/sala"
  }
  Serial.println("");                                                                             // quebra de linha
  if ((char)payload[0] == 's') {                                                                  // se a mensagem recebida for s (minúsculo)
    digitalWrite(Sala, LOW);                                                                      // o LED Sala vai para nível lógico baixo 
    snprintf (msg, MSG_BUFFER_SIZE, "A luz da sala está desligada");                              // aparece mensagem indicando que a luz da sala está desligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/sala", msg);                                                             // publica a mensagem no tópico "casa/sala" 
  }
  Serial.println("");                                                                             // quebra de linha
  if ((char)payload[0] == 'Q') {                                                                  // se a mensagem recebida for Q (maiúsculo)
    digitalWrite(Quarto, HIGH);                                                                   // o LED Quarto vai para nível lógico alto
    snprintf (msg, MSG_BUFFER_SIZE, "A luz do quarto está ligada");                               // aparece mensagem indicando que a luz do quarto está ligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/quarto", msg);                                                           // publica a mensagem no tópico "casa/quarto" 
  }
   Serial.println("");                                                                            // quebra de linha
   if ((char)payload[0] == 'q') {                                                                 // se a mensagem recebida for q (minúsculo)
    digitalWrite(Quarto, LOW);                                                                    // o LED quarto vai para nível lógico baixo 
    snprintf (msg, MSG_BUFFER_SIZE, "A luz do quarto está desligada");                            // aparece mensagem indicando que a luz do quarto está desligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/quarto", msg);                                                           // publica a mensagem no tópico "casa/quarto"
  }
  Serial.println("");                                                                             // quebra de linha
  if ((char)payload[0] == 'C') {                                                                  // se a mensagem recebida for C (maiúsculo)
    digitalWrite(Cozinha, HIGH);                                                                  // o LED cozinha vai para nível lógico alto
    snprintf (msg, MSG_BUFFER_SIZE, "A luz da cozinha está ligada");                              // aparece mensagem indicando que a luz da cozinha está ligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/cozinha", msg);                                                          // publica a mensagem no tópico "casa/cozinha"
  }
  Serial.println("");                                                                             // quebra de linha
   if ((char)payload[0] == 'c') {                                                                 // se a mensagem recebida for c (minúsculo)
    digitalWrite(Cozinha, LOW);                                                                   // o LED cozinha vai para nível lógico baixo
    snprintf (msg, MSG_BUFFER_SIZE, "A luz da cozinha está desligada");                           // aparece mensagem indicando que a luz da cozinha está desligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/cozinha", msg);                                                          // publica a mensagem no tópico "casa/cozinha"
  }
  Serial.println("");                                                                             // quebra de linha
  if ((char)payload[0] == 'B') {                                                                  // se a mensagem recebida for B (maiúsculo)
    digitalWrite(Banheiro, HIGH);                                                                 // o LED banheiro vai para nível lógico alto
    snprintf (msg, MSG_BUFFER_SIZE, "A luz do banheiro está ligada");                             // aparece mensagem indicando que a luz do banheiro está ligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/banheiro", msg);                                                         // publica a mensagem no tópico "casa/banheiro"
  }
   Serial.println("");                                                                            // quebra de linha
   if ((char)payload[0] == 'b') {                                                                 // se a mensagem recebida for b (minúsculo)
    digitalWrite(Banheiro, LOW);                                                                  // o LED banheiro vai para o nível lógico baixo
    snprintf (msg, MSG_BUFFER_SIZE, "A luz do banheiro está desligada");                          // aparece mensagem indicando que a luz do banheiro está desligada
    Serial.print("Publica mensagem: ");                                                           // printa "Publica mensagem:"
    Serial.println(msg);                                                                          // printa a mensagem
    client.publish("casa/banheiro", msg);                                                         // publica a mensagem no tópico "casa/banheiro"
    
  }
}

void reconnect() {                                                                                // laço para reconexão 
  while (!client.connected()) {                                                                   // enquanto não é estabelecida reconexão
    Serial.print("Aguardando conexão MQTT...");                                                   // printa no serial "Aguardando conexão MQTT..." 
    String clientId = "ESP8266Client";                                       
    clientId += String(random(0xffff), HEX);                                                      // cria uma identidade de cliente aleatória
    if (client.connect(clientId.c_str())) {                                                       // Se é realizada a conexão
      Serial.println("conectado");                                                                // printa "conectado" no serial 
      client.subscribe("casa/publisher");                                                         // e realiza subscrição no tópico "teste_entrada" 
    } else {                                                                                      // caso contrário
      Serial.print("falhou, rc=");                                                                // printa a mensagem "falhou, rc="
      Serial.print(client.state());                                                               // printa status do client
      Serial.println("tente novamente em 5s");                                                    // printa na serial "tente novamente em 5s" 
      delay(5000);                                                                                // atraso de 5s antes de reiniciar o laço void reconnect
    }
  }
}

void loop() {                                                                                     // laço de repetição 
  delay(delayMS);                                                                                 // atraso 
  sensors_event_t event;                                                                          // inicia evento de medições do sensor
  dht.temperature().getEvent(&event);                                                             // inicia evento de DHT temperatura
  if (isnan(event.temperature)) {                                                                 // se não ocorrer a leitura de temperatura
    Serial.println(F("Erro na leitura da temperatura!"));                                         // printa a mensagem "Erro na leitura da temperatura!"
  }
  else {                                                                                          // caso contrário
    Serial.print(F("Temperatura: "));                                                             // Printa "Temperatura:"
    Serial.print(event.temperature);                                                              // Imprime na serial a medição de temperatura
    Serial.println(F("°C"));                                                                      // Printa C°
    sprintf(msg,"%f",event.temperature);                                                          // Salva o valor de temperatura na mensagem
    client.publish("casa/temperatura", msg);                                                      // Publica a mensagem no tópico casa/temperatura
  }
  dht.humidity().getEvent(&event);                                                                // inicia evento de DHT umidade
  if (isnan(event.relative_humidity)) {                                                           // se não ocorrer a leitura da umidade 
    Serial.println(F("Erro na leitura da umidade!"));                                             //printa a mensagem "Erro na leitura da umidade!"
  }
  else {                                                                                          // caso contrário
    Serial.print(F("Umidade: "));                                                                 // printa "Umidade:"
    Serial.print(event.relative_humidity);                                                        // Imprime na serial a medição de umidade
    Serial.println(F("%"));                                                                       // Printa %
    sprintf(msg,"%f",event.relative_humidity);                                                    // Salva o valor de umidade na mensagem
    client.publish("casa/umidade", msg);                                                          // Publica a mensagem no tópico casa/umidade
  }
  if (!client.connected()) {                                                                      // Se o cliente não se conectar
    reconnect();                                                                                  // vai para laço de reconexão
  }
  client.loop();                                                                                  // permitir o processamento e a publicação de mensagens e dados
}

 

 

 

 

 

 

 

 

 


Protótipo de Casa Monitorada –MQTTBox

            Vamos criar um novo cliente da mesma forma que fizemos anteriormente, adicionaremos um Publisher e seis Subscribers, sendo quatro destinados aos cômodos, um à temperatura e um à umidade, dessa forma:

MQTTBox layout

MQTTBox layout 2

MQTTBox 3 Laayout

Protótipo de Casa Monitorada –Aplicativo

             Para monitoramento e controle via aplicativo, utilizaremos um aplicativo mobile chamado “MQTTDash”, o mesmo encontra-se disponível na Play Store para download gratuito

MQTTDash na Playstore

 

            Depois de finalizado o processo de baixar e instalar, abra o seu aplicativo e crie um novo arquivo clicando no + no canto superior direito da tela.

 

            Adicionar novo projeto

 

 

 

            Agora faremos as pré-configurações do nosso projeto mobile, selecionaremos a opção de conexão automática,  criaremos o nome do projeto “Name”, o endereço do broker “Adress”, o "Port" e deixaremos as outras configurações da mesma forma. Clique no disquete no canto superior para salvar.
MQTTDash pré-configurações

 

            Clique no projeto que você criou para iniciarmos a montagem da Dashboard.

 

MQTT Dash

 

            Ao abrir a nossa Dashboard, clicaremos no + para inserção dos widgets que usaremos.

 

Adicionar widgets MQTTDash

 

           Primeiramente colocaremos o texto indicando o Status da lâmpada do cômodo em questão, para isso selecionaremos a opção “Text”.

 

Widget text mqttdash

 

            Primeiro, criaremos um nome para a nossa caixa de texto, depois configuraremos para que essa caixa de texto se inscreva para receber a informação publicada no tópico do cômodo que ela representa, por exemplo: Para caixa de texto do status da sala, usaremos: Topic(sub): casa/sala

 

Inserção de texto 1
Inserção de texto 2

 

            Como a nossa mensagem é um pouco longa, definimos o Main text size (tamanho do texto) para Small (pequeno).

 

            Você também pode definir a cor do texto em Main text color (cor do texto) se assim desejar.

 

            Depois de configurar, clique no disquete para Salvar.

 

            Concluindo esse processo de monitoramento, vamos incluir nosso botão para controle da lâmpada desse mesmo cômodo. Novamente na parte de Widgets, vamos selecionar Switch/button.
 

Widget button

 

            Assim como fizemos com a caixa de texto, vamos criar um nome, em Topic (sub) nos inscreveremos no publisher, sendo: casa/publisher. Em Topic (pub), colocaremos igualmente o tópico: casa/publisher. Ou seja, esse botão receberá toda informação que for publicada (incluindo as do MQTTBox), e terá o direito de publicar no ESP8266. Além disso, mudarei o 1 do modo ON e o 0 do modo OFF para as letras correspondentes ao cômodo, igualmente, mudarei as cores e os ícones do botão, sendo isso apenas um floreio opcional.


Configurações do botão MQTTDash     
           Minha configuração de interruptor ficou da seguinte forma:
Interruptor MQTTDash

 

           Depois disso, faremos o mesmo para todos os cômodos da casa: modificando os tópicos da caixa de texto para o cômodo de monitoramento, em botão mudaremos as inicias que farão o LED acender ou apagar, e adicionaremos ícones e cores para deixar o aplicativo mais lúdico, sendo essas as configurações primordiais:

Tabela de cômodos para widget text
Tabela cômodos com o modo Switch

           Atentando-se para o seguinte fator: Se você quiser que sua Dashboard fique com o layout semelhante ao que fizemos, insira um text e em seguida o switch daquele mesmo cômodo, de forma revezada, assim: text da sala > switch/button da sala> text do quarto > switch/button do quarto> text da cozinha > switch/button da cozinha > tex do banheiro > switch/button do banheiro


 

MQTTDash casa inteligente controle iluminação

 

            Agora vamos inserir as medições de temperatura e umidade, para isso, vamos em + > Range/progress

MQTTDash barra de progresso

 

            Vamos nos inscrever em Topic(sub): casa/temperatura e fazer configurações básicas de cor e precisão 2 para aparecerem dois números após a vírgula. Também vamos inserir a unidade C° em postfix.

 

Temperatura


Faremos o mesmo para umidade, sendo Topic(sub) : casa/umidade e unidade em porcentagem.

 

 

 

Umidade MQTTDash

 

          Sensor de Umidade MQTTDash
         O seu dashboard deve ficar dessa forma:

 

MQTTDash Projeto

 

Dashboard completo MQTTDash

 

 

 

Projeto de Casa Monitorada -Funcionamento

 

            Depois de realizar a compilação do programa, vamos testar o aplicativo

Funcionamento MQTTDash  
            E o funcionamento através do MQTTBox ficou da seguinte forma:



Conclusão

           A Comunicação via protocolo MQTT se mostrou eficaz na transmissão e recepção de dados. O Funcionamento dos tópicos, publicador e subscrito também atuaram de acordo com o exposto nos tutoriais anteriores, com isso, sabemos que podemos contar com esse tipo de comunicação para os nossos projetos de IoT, abrindo a possibilidade de colocar o nosso microcontrolador como emissor (publicador) e receptor (subscrito). Nos próximos tutoriais vamos criar uma comunicação segura para esse mesmo projeto, além de criarmos um Dashboard para PC via IO Adafruit.
Nao esqueça de deixar o seu feedback e qualquer dúvida nos comentários abaixo.

Abraços, Equipe Curto Circuito :)