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é.
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.
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 :-(
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>
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.