Introduction: NiceWeather

PONTIFÍCIA UNIVERSIDADE CATÓLICA DE MINAS GERAIS

Curso: Especialização em Arquitetura de Software Distribuído

Data: 21/09/2020

Unidade: Praça da Liberdade

Disciplina: Internet das Coisas

Professor: Ilo Rivero

Alunos:

Eduardo Borges

Ismael Amaral

João Bosco

INTRODUÇÃO

O NiceWeather é uma solução automatizada para climatizar sua casa, seu trabalho ou qualquer outro ambiente fechado. Você define os parâmetros desejados, tais como, umidade relativa do ar e temperatura, e o NiceWeather faz todo o resto. Se preferir, pode controlar os aparelhos remotamente de qualquer smartphone ou computador, basta um browser e acesso à internet.

FUNCIONAMENTO

As informações de umidade relativa do ar e temperatura são enviadas para uma aplicação web através de uma API Restful. Esta aplicação, por sua vez, armazena tais informações e as utiliza, em conjunto com parâmetros pré-definidos, para calcular o estado de umidificadores e ar-condicionados.

Os usuários podem optar pelas seguintes configurações:

AUTO: os aparelhos são controlados pela aplicação web;

ON: os aparelhos se mantém ligados;

OFF: os aparelhos se mantém desligados.

Quando os aparelhos estão em estado automático, eles funcionam da seguinte maneira:

- Ar Condicionado

Temperatura mínima: o ar condicionado é desligado quando a temperatura atingir a mínima configurada;

Temperatura máxima: o ar condicionado é ligado quando a temperatura atingir a máxima configurada.

Obs.: enquanto a temperatura estiver entre a mínima e a máxima, o estado atual do ar condicionado é mantido. Ou seja, se ele estiver ligado, permanece ligado e se estiver desligado, permanece desligado.

- Umidificador

Umidade mínima: o umidificador é ligado quando a umidade relativa do ar atingir a mínima configurada;

Umidade máxima: o umidificador é desligado quando a umidade relativa do ar atingir a máxima configurada.

Obs.: enquanto a umidade relativa estiver entre a mínima e a máxima, o estado atual do umidificador é mantido. Ou seja, se ele estiver ligado, permanece ligado e se estiver desligado, permanece desligado.

SEGURANÇA EM 1º LUGAR

Por questões de segurança, iremos simular os aparelhos com uma fita LED que utiliza uma fonte de 5V. Caso utilizem aparelhos reais, é necessário tomar muito cuidado e se atentar para a amperagem do módulo relé.

Step 1: Componentes

NodeMCU (ESP8266)


O NodeMCU é uma placa da família ESP8266 que pode ser utilizado para projetos IoT. Ela já vem com WiFi embutido, facilitando o desenvolvimento de protótipos que precisam se conectar à internet. Uma das vantagens, é sua compatibilidade com o ArduinoIDE, fazendo com que as mais diversas bibliotecas possam ser utilizadas.

– Processador ESP8266-12E

– Arquitetura RISC de 32 bits

– Processador pode operar em 80MHz / 160MHz

– 4Mb de memória flash

– 64Kb para instruções

– 96Kb para dados

– WiFi nativo padrão 802.11b/g/n

– Opera em modo AP, Station ou AP + Station

– Pode ser alimentada com 5VDC através do conector micro USB

– Possui 11 pinos digitais– Possui 1 pino analógico com resolução de 10 bits

– Pinos digitais, exceto o D0 possuem interrupção, PWM, I2C e one wire

– Pinos operam em nível lógico de 3.3V

– Pinos não tolerantes a 5V (ATENÇÃO)

– Possui conversor USB Serial integrado

– Programável via USB ou WiFi (OTA)

– Compatível com a IDE do Arduino

– Compatível com módulos e sensores utilizados no Arduino


Protoboard


É placa com uma matriz de contatos que permite a construção de circuitos experimentais sem a necessidade de solda, permitindo com rapidez e segurança desde uma alteração de posição de um determinado componente até sua substituição. Nela, faremos a conexão entre os componentes do projeto (NodeMCU, relés e sensores).


Módulo Relé 3.3v 2 Canais

É um módulo utilizado para acionar cargas com a tensão maior que a do microcontrolador, no nosso caso, o NodeMCU. É necessário bastante cuidado, pois, é altamente perigoso trabalhar com eletricidade. Nesse projeto, utilizaremos um relé simples de 10A, pois, iremos simular os aparelhos. Para trabalhar com aparelhos reais, é necessário ficar atento à amperagem.


Sensor DHT11

O DHT11 é um sensor de temperatura e umidade que permite fazer leituras de temperaturas entre 0 a 50 Celsius e umidade entre 20 a 90%, muito usado para projetos com Arduino. Também é compatível com o NodeMCU.

Step 2: Circuito

É preciso ficar atento com a voltagem dos componentes. O NodeMCU travalha com 3.3V.

MUITO CUIDADO AO FAZER AS LIGAÇÕES ELÉTRICAS!!!

)-: PERIGO DE MORTE :-(

Step 3: Sketch NodeMCU

A aplicação que roda no NodeMCU foi desenvolvida utilizando o Arduino Software (IDE). O sketch está disponível no GitHub.

PREPARE O AMBIENTE

Ajuste o Arduino IDE para trabalhar com a placa NodeMCU:

  • Instale a placa esp8266: acesse o menu Ferramentas > Placa > Gerenciador de Placas e pesquise por esp8266;
  • Selecione a placa NodeMCU 1.0 (ESP-12E Module) através do menu Placa > Gerenciador de Placas > ESP8266 Boards.

Instale as seguintes bibliotecas (menu Sketch > Incluir Bibliotecas > Gerenciar Bibliotecas) :

  • ArduinoJson: manipular o JSON retornado pelas APIs da aplicação web;
  • ESP8266WiFi: realizar a conexão com o WIFI;
  • SimpleTimer: executar algumas funções de tempos em tempos;
  • DHT Sensor: obter as informações do sensor DHT11;
  • ESP8266HTTPClient: fazer as chamadas nas APIs da aplicação web.

ALGORÍTIMO

Incluindo as bibliotecas necessárias:

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <SimpleTimer.h>
#include <DHT.h>
#include <ESP8266HTTPClient.h>

Definindo a rede WIFI e a pinagem utilizada:

char ssid[] = "SUA_REDE";  //Informe o nome da rede WIFI
char pass[] = "PASSWORD";  //Informe a senha da rede WIFI

//Digital 2
const int releUmidificador = D2;
//Digital 3
const int releArCondicionado = D3;
//Digital 4
const int DHTPIN = D4;

Realizando as configurações iniciais no método setup():

  • configurar pinagem:
  //iniciar desligado
  digitalWrite(releUmidificador, HIGH);
  digitalWrite(releArCondicionado, HIGH);
  //Saída para reles
  pinMode(releUmidificador, OUTPUT); 
  pinMode(releArCondicionado, OUTPUT);<br>
  • conectar no WIFI e iniciar sensor DHT11:
  WiFi.begin(ssid, pass);
  //Não prossegue enquanto não conectar no WIFI
  while (WiFi.status() != WL_CONNECTED) {
    delay(2000);
    Serial.println("Connecting ao " + String(ssid) + "...");
  }
  //Inicia o sensor de temperatura/umidade
  dht.begin();
  • configurar timer para executar funções:
  //Configura o timer para enviar as informações do sensor a cada 5 segundos
  timer.setInterval(5000L, enviarInormacoesSensor);
  //Configura o timer para obter o estado dos equipamentos a cada 1 segundo
  timer.setInterval(1000L, obterEstadoEquipamentos);

O loop apenas executa o timer para que as funções "enviarInformacoesSensor" e "obterEstadoEquipamentos" sejam chamadas:

void loop() {
  //Executa o timer
  timer.run();
} 

Enviando informações para o sensor (substitua o IP):

//Esta função irá ler as informações de umidade e temperatura
//e enviá-las para uma aplicação web através de uma API Restful
void enviarInormacoesSensor() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  //Checa se as informações de umidade e temperatura foram obtidas
  if (isnan(h) || isnan(t)) {
    Serial.println("Não foi possível obter as informações de umidade e temperatura do sensor DHT!");
    return;
  }
  //Checa se está conectado no WIFI
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    //Substituir pelo ip/url da aplicação web
    http.begin("http://192.168.0.18:8080/public/v1/temperaturaUmidade");
    http.addHeader("Content-Type", "application/json");
    String body = "{\"temperatura\":\""+ String(t) +"\", \"umidade\":\""+ String(h) +"\"}";

    Serial.println(body);
    
    int httpCode = http.POST(body);
    if (httpCode == -1) {
      Serial.println("Não foi possível enviar as informações para a aplicação web... Status: " + httpCode);
    }
    //Encerra a conexão
    http.end();
  }
}<br>

Acessando API para obter alterar o estado dos equipamentos (substitua o IP):

//Esta função irá obter as informações
//que indicarão quais equipamentos
//devem ser ligados/desligados
void obterEstadoEquipamentos() {
  //Checa se está conectado no WIFI
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    //Substituir pelo ip/url da aplicação web
    http.begin("http://192.168.0.18:8080/public/v1/estadoAparelhos");
    http.addHeader("Content-Type", "application/json");
    int httpCode = http.GET();
    //Status OK
    if (httpCode == 200) {
      StaticJsonDocument<200> doc;
      deserializeJson(doc, http.getString());
 
      const char * estadoUmidificadorChar = doc["estadoUmidificador"]; 
      const char * estadoArCondicionadoChar = doc["estadoArCondicionado"]; 
      estadoUmidificador = String(estadoUmidificadorChar);
      estadoArCondicionado = String(estadoArCondicionadoChar);

      //Se NONE, não altera o estado do umidificador
      if (!estadoUmidificador.equals("NONE")) {
        if (estadoUmidificador.equals("ON")) {
          Serial.println("Umidificador ligado");
          digitalWrite(releUmidificador, LOW);
        } else {
          Serial.println("Umidificador desligado");
          digitalWrite(releUmidificador, HIGH);
        }
      }
      //Se NONE, não altera o estado do ar-condicionado
      if (!estadoArCondicionado.equals("NONE")) {
        if (estadoArCondicionado.equals("ON")) {
          Serial.println("Ar-condicionado ligado");
          digitalWrite(releArCondicionado, LOW);
        } else {
          Serial.println("Ar-condicionado desligado");
          digitalWrite(releArCondicionado, HIGH);
        }
      }
    }
    http.end();
  }
}<br>

Step 4: Aplicação Web

A aplicação web foi desenvolvida utilizando o SpringBoot 2.3.3 em conjunto com uma base de dados MySql. O código fonte está disponível no GitHub (/sources/server).

Foram disponibilizados scripts (/scripts) para criação das tabelas necessárias.

Criar tabela para armazenar dados enviados pelo sensor:

CREATE TABLE `historico_temperatura_umidade` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `data` timestamp NOT NULL,
  `temperatura` decimal(5,2) NOT NULL,
  `umidade` decimal(5,2) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_data` (`data`) /*!80000 INVISIBLE */,
  KEY `idx_temperatura` (`temperatura`),
  KEY `idx_umidade` (`umidade`)
) ENGINE=InnoDB AUTO_INCREMENT=14447 DEFAULT CHARSET=utf8;

Criar tabela para armazenar parâmetros gerais:

CREATE TABLE `parametros` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `tipo` varchar(45) NOT NULL,
  `valor` longtext,
  PRIMARY KEY (`id`),
  UNIQUE KEY `tipo_UNIQUE` (`tipo`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

As configurações de conexão com a base de dados devem ser definidas no arquivo application.properties:

spring.jpa.hibernate.ddl-auto=validate
spring.datasource.url=jdbc:mysql://${IOT_MYSQL_HOST:localhost}:3306/db_example?useTimezone=true&serverTimezone=America/Sao_Paulo
spring.datasource.username=${IOT_MYSQL_USERNAME:username}
spring.datasource.password=${IOT_MYSQL_PASSWORD:password}<br>

A aplicação disponibiliza duas APIs para comunicação com o NodeMCU.

- POST URI "/public/v1/temperaturaUmidade": utilizada para gravar os dados de temperatura/umidade obtidos pelo sensor.

Exemplo payload:

{ "temperatura" : 29.9, "umidade" : 44.02 }

- GET URI "/public/v1/estadoAparelhos" : utilizada para retornar o estado dos aparelhos.

Exemplo response:

{ "estadoUmidificador" : "NONE|ON|OFF", "estadoArCondicionado" : "NONE|ON|OFF" }

onde NONE indica que o estado atual do aparelho não deve ser modificado.

Através da aplicação web, é possível visualizar checar a temperatura e umidade relativa do ar, bem como ajustar os parâmetros gerais e alterar o estado dos aparelhos.