Neste post você aprenderá à desenvolver um sistema para controle de cargas utilizando uma Dashboard de Internet das Coisas (IoT) e uma famosa plataforma de prototipagem: a placa Arduino UNO.
Para este tutorial você precisará dos seguintes componentes eletrônicos:
Também será necessário ter:
Mais abaixo será detalhado o processo de criação das contas.
Para controlar as cargas via Internet é necessário ter uma plataforma da internet para gerenciar os dados de nosso Arduino. Iremos utilizar a plataforma da Adafruit IO. Para isso é necessário criar uma conta da Adafruit.
Antes de prosseguirmos, devemos explicar o que é feed.
Para enviar os dados da Dashboard para o Arduino, ou do Arduino para a Dashboard, é necessário ter um lugar onde armazenar os dados na nuvem. Este lugar é os Feeds. Se você, por exemplo, tiver um sensor de temperatura e um sensor de umidade, você deve criar dois feeds com nomes distintos para a armazenagem dos seus dados.
Os feeds podem ser privados ou públicos. Feeds privados só são visíveis para você. Já os feeds públicos podem ser vistos por qualquer pessoa do mundo.
Antes de prosseguimos, devemos explicar o que é uma Dashboard.
Dashboard onde você pode visualizar e controlar os dados dos Feeds. Em uma Dashboard, você pode colocar gráficos, botões, controles deslizantes, mapas e ícones.
Agora que terminamos de implementar a Dashboard, podemos programar o Arduino.
Para o desenvolvimento do circuito eletrônico deste tutorial, siga o Diagrama abaixo:
O hardware é composto de um Arduino UNO como microcontrolador, uma Shield Ethernet W5100, que oferecerá à placa Arduino uma Conexão de Internet e um Módulo Relé de 4 Canais para controle das cargas. As cargas podem ser qualquer equipamento elétrico que não ultrapasse as especificações técnicas do Relé. No caso do nosso módulo Relé utilizado, ele possui as seguintes especificações:
Ele suporta no máximo 10A de Corrente Elétrica e 250V de Tensão Elétrica em Corrente Alternada. Isso significa que se quiséssemos conectar algum equipamento elétrico que drene mais do que 10A ou que utilize mais do que 250V em Corrente Alternada, não poderíamos utilizar com este Módulo Relé.
Recomendo que leia os seguintes artigos daqui da Eletrogate, para um aprofundamento no hardware:
Para desenvolvermos o software para o Arduino, devemos fazer o download de uma biblioteca: a Adafruit MQTT Library.
Para isso, siga o passo a passo abaixo:
Com a instalação finalizada, coloque o seguinte código na IDE Arduino:
/*************************************************** Controle de Cargas por Adafruit IO Ethernet Exemplo Criado em 01 de Julho de 2021 por Michel Galvão ****************************************************/ //Inclusão de Bibliotecas #include <SPI.h> #include "Adafruit_MQTT.h" #include "Adafruit_MQTT_Client.h" #include <Ethernet.h> #include <EthernetClient.h> #include <Dns.h> #include <Dhcp.h> //Definição de endereço MAC para placa Ethernet byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Definição de Endereço IP para a placa Ethernet IPAddress iotIP (192, 168, 0, 177); // Coloque uma sequência válida da sua rede //Definição de Variáveis Adafruit.io #define AIO_SERVER "io.adafruit.com" #define AIO_SERVERPORT 1883 #define AIO_USERNAME "Coloque_aqui_seu_Usuario_de_Adafruit_IO" #define AIO_KEY "Coloque_aqui_sua_Senha_de_Adafruit_IO" //Definição de Pinos Relés #define pinoRele1 6 #define pinoRele2 5 #define pinoRele3 3 #define pinoRele4 2 //Variavel controle Inicialização bool executaSoNoInicio = true; //Configuração Ethernet Client EthernetClient client; //Configuração Adafruit MQTT Client Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY); //Você não precisa alterar nada nesta linha: #define halt(s) { Serial.println(F( s )); while(1); } //FEEDS //Observe que os endereços do MQTT para Adafruit IO seguem o formato: <username>/feeds/<feedname> // Configure os feeds de publicação aqui: //Feed Feedback Rele 1 (Status) Adafruit_MQTT_Publish statusRele1 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/status-rele-1"); //Feed Feedback Rele 1 (Status) Adafruit_MQTT_Publish statusRele2 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/status-rele-2"); //Feed Feedback Rele 1 (Status) Adafruit_MQTT_Publish statusRele3 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/status-rele-3"); //Feed Feedback Rele 1 (Status) Adafruit_MQTT_Publish statusRele4 = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/status-rele-4"); // Configure os feeds de inscrição aqui: // Feed Rele 1 Adafruit_MQTT_Subscribe botaoRele1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/botao-rele-1"); // Feed Rele 2 Adafruit_MQTT_Subscribe botaoRele2 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/botao-rele-2"); // Feed Rele 3 Adafruit_MQTT_Subscribe botaoRele3 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/botao-rele-3"); // Feed Rele 4 Adafruit_MQTT_Subscribe botaoRele4 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/botao-rele-4"); //Ponteiro para recebimento de mensagens MQTT Adafruit_MQTT_Subscribe *subscription; //Código de configuração aqui, para ser executado uma vez void setup() { //Configuração da taxa de transferência em bits por segundo (baud rate) para transmissão serial Serial.begin(115200); //Configura o pino especificado para funcionar como uma saída pinMode(pinoRele1, OUTPUT); pinMode(pinoRele2, OUTPUT); pinMode(pinoRele3, OUTPUT); pinMode(pinoRele4, OUTPUT); //setamos o nível lógico dos pinos dos relés para HIGH para que, no ínicio, fiquem desligados digitalWrite(pinoRele1, HIGH); digitalWrite(pinoRele2, HIGH); digitalWrite(pinoRele3, HIGH); digitalWrite(pinoRele4, HIGH); Serial.println(F("Controle de Cargas por Adafruit IO")); Serial.println(F("Iniciando o Client")); //Iniciando o Client inicializaMQTTAdafruitIO(); } //Código principal aqui, para executar repetidamente void loop() { // Verifica se a conexão com o servidor MQTT está ativa MQTT_conecta(); while ((subscription = mqtt.readSubscription(5000))) { AdafruitRecebeMensagem_Rele1(); AdafruitRecebeMensagem_Rele2(); AdafruitRecebeMensagem_Rele3(); AdafruitRecebeMensagem_Rele4(); } if (executaSoNoInicio == true) { AdafruitEnvio_Rele1(); AdafruitEnvio_Rele2(); AdafruitEnvio_Rele3(); AdafruitEnvio_Rele4(); executaSoNoInicio = false; } pingAdafruit(); // faz ping no servidor } void MQTT_conecta() { // Função para conectar e reconectar conforme necessário ao servidor MQTT if (mqtt.connected()) { return; //Pare se já estiver conectado. } else { //Variável de Controle int numeroDeTentativas = 0; //Retorno de mensagem int8_t ret; while ((ret = mqtt.connect()) != 0) { // Faz uma condição: Se a tentativa de conexão ret retornar diferente de 0, não estamos conectado ao servidor if (numeroDeTentativas >= 4) { //Se o número de tentativas for igual ou maior que quatro, sai do while. Esta condição serve para o programa não ficar somente tentando fazer conexão, caso a internet fique offline. break; } Serial.print(F("Conexão Erro MQTT: ")); Serial.print(ret); //Informa ao usuário o código de erro. //Veja os códigos de erro na lista abaixo: //ret: // 0 = conectado //-1 = Erro ao conectar ao servidor // 1 = Protocolo errado // 2 = ID rejeitada // 3 = Servidor indisponível // 4 = Nome de usuário ou senha incorretos // 5 = Não autenticado // 6 = Falha ao assinar // 7 = Bloqueado pelo Servidor. Entre em contato com a administração de Adafruit IO Serial.println();//Cria uma linha de espaço na Serial mqtt.disconnect(); // desconecta para novamente tentar fazer uma conexão válida delay(5000); // espere 5 secondos numeroDeTentativas++; } delay(1500); if (ret == 0) { // Se estivermos conectado ao servidor, informa ao usuário Serial.print(F("MQTT Conectado! ")); Serial.println(ret); } numeroDeTentativas++; } } void inicializaMQTTAdafruitIO() { //Inicializa MQTT Adafruit IO //Inicializa a biblioteca Ethernet e as configurações de rede. Ethernet.begin(mac, iotIP); delay(1000); //give the ethernet a second to initialize subscricaoAdafruitIO(); } void subscricaoAdafruitIO() { //Inscreve-se nos feeds mqtt.subscribe(&botaoRele1); mqtt.subscribe(&botaoRele2); mqtt.subscribe(&botaoRele3); mqtt.subscribe(&botaoRele4); } void pingAdafruit() { // faz um ping no servidor para manter a conexão mqtt ativa if (!mqtt.ping()) { mqtt.disconnect(); } } bool AdafruitEnvio_Rele1() { bool retorno = true; if (!digitalRead(pinoRele1)) { //Se a leitura digital do pino pinoRele for true, significará que está desligada a carga. Então invertemos o estado para que vire o inverso. if (!statusRele1.publish("star")) { Serial.println(F("Falha no envio do ícone star")); } else { Serial.println(F("Ícone star enviado!")); retorno = false; } } else { if (!statusRele1.publish("star-o")) { Serial.println(F("Falha no envio do ícone star-o")); } else { Serial.println(F("Ícone star-o enviado!")); retorno = false; } } return retorno; } bool AdafruitEnvio_Rele2() { bool retorno = true; if (!digitalRead(pinoRele2)) { //Se a leitura digital do pino pinoRele for true, significará que está desligada a carga. Então invertemos o estado para que vire o inverso. if (!statusRele2.publish("w:wind-beaufort-1")) { Serial.println(F("Falha no envio do ícone w:wind-beaufort-1")); } else { Serial.println(F("Ícone w:wind-beaufort-1 enviado!")); retorno = false; } } else { if (!statusRele2.publish("w:wind-beaufort-0")) { Serial.println(F("Falha no envio do ícone w:wind-beaufort-0")); } else { Serial.println(F("Ícone w:wind-beaufort-0 enviado!")); retorno = false; } } return retorno; } bool AdafruitEnvio_Rele3() { bool retorno = true; if (!digitalRead(pinoRele3)) { //Se a leitura digital do pino pinoRele for true, significará que está desligada a carga. Então invertemos o estado para que vire o inverso. if (!statusRele3.publish("star")) { Serial.println(F("Falha no envio do ícone star")); } else { Serial.println(F("Ícone star enviado!")); retorno = false; } } else { if (!statusRele3.publish("star-o")) { Serial.println(F("Falha no envio do ícone star-o")); } else { Serial.println(F("Ícone star-o enviado!")); retorno = false; } } return retorno; } bool AdafruitEnvio_Rele4() { bool retorno = true; if (!digitalRead(pinoRele4)) { //Se a leitura digital do pino pinoRele for true, significará que está desligada a carga. Então invertemos o estado para que vire o inverso. if (!statusRele4.publish("check")) { Serial.println(F("Falha no envio do ícone check")); } else { Serial.println(F("Ícone check enviado!")); retorno = false; } } else { if (!statusRele4.publish("power-off")) { Serial.println(F("Falha no envio do ícone power-off")); } else { Serial.println(F("Ícone power-off enviado!")); retorno = false; } } return retorno; } void AdafruitRecebeMensagem_Rele1() { if (subscription == &botaoRele1) { Serial.print("Recebido dado Rele 1: "); Serial.println((char *)botaoRele1.lastread); // a mensagem recebida está em object.lastread //Estamos mostrando ao usuário de Adafruit IO que o arduino ouviu a mensagem if (!statusRele1.publish("w:cloud-refresh")) { Serial.println(F("Falha no envio do ícone w:cloud-refresh")); } else { Serial.println(F("Ícone w:cloud-refresh enviado!")); } delay(500); // tempo de espera necessário if (strcmp(botaoRele1.lastread, "0") == 0) { // strcmp(string1, string2) : Compara string1 com string2 e retorna 0 caso as duas strings serem iguais digitalWrite(pinoRele1, !LOW);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } else { digitalWrite(pinoRele1, !HIGH);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } Serial.print(F("\nEstado Atual Rele 1: ")); Serial.print(!digitalRead(pinoRele1)); Serial.println(); AdafruitEnvio_Rele1(); } } void AdafruitRecebeMensagem_Rele2() { if (subscription == &botaoRele2) { Serial.print("Recebido dado Rele 2: "); Serial.println((char *)botaoRele2.lastread); // a mensagem recebida está em object.lastread //Estamos mostrando ao usuário de Adafruit IO que o arduino ouviu a mensagem if (!statusRele2.publish("w:cloud-refresh")) { Serial.println(F("Falha no envio do ícone w:cloud-refresh")); } else { Serial.println(F("Ícone w:cloud-refresh enviado!")); } delay(500); // tempo de espera necessário if (strcmp(botaoRele2.lastread, "0") == 0) { // strcmp(string1, string2) : Compara string1 com string2 e retorna 0 caso as duas strings serem iguais digitalWrite(pinoRele2, !LOW);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } else { digitalWrite(pinoRele2, !HIGH);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } Serial.print(F("\nEstado Atual Rele 2: ")); Serial.print(!digitalRead(pinoRele2)); Serial.println(); AdafruitEnvio_Rele2(); } } void AdafruitRecebeMensagem_Rele3() { if (subscription == &botaoRele3) { Serial.print("Recebido dado Rele 3: "); Serial.println((char *)botaoRele3.lastread); // a mensagem recebida está em object.lastread //Estamos mostrando ao usuário de Adafruit IO que o arduino ouviu a mensagem if (!statusRele3.publish("w:cloud-refresh")) { Serial.println(F("Falha no envio do ícone w:cloud-refresh")); } else { Serial.println(F("Ícone w:cloud-refresh enviado!")); } delay(500); // tempo de espera necessário if (strcmp(botaoRele3.lastread, "0") == 0) { // strcmp(string1, string2) : Compara string1 com string2 e retorna 0 caso as duas strings serem iguais digitalWrite(pinoRele3, !LOW);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } else { digitalWrite(pinoRele3, !HIGH);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } Serial.print(F("\nEstado Atual Rele 3: ")); Serial.print(!digitalRead(pinoRele3)); Serial.println(); AdafruitEnvio_Rele3(); } } void AdafruitRecebeMensagem_Rele4() { if (subscription == &botaoRele4) { Serial.print("Recebido dado Rele 4: "); Serial.println((char *)botaoRele4.lastread); // a mensagem recebida está em object.lastread //Estamos mostrando ao usuário de Adafruit IO que o arduino ouviu a mensagem if (!statusRele4.publish("w:cloud-refresh")) { Serial.println(F("Falha no envio do ícone w:cloud-refresh")); } else { Serial.println(F("Ícone w:cloud-refresh enviado!")); } delay(500); // tempo de espera necessário if (strcmp(botaoRele4.lastread, "0") == 0) { // strcmp(string1, string2) : Compara string1 com string2 e retorna 0 caso as duas strings serem iguais digitalWrite(pinoRele4, !LOW);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } else { digitalWrite(pinoRele4, !HIGH);// inverte estado do rele recebido, pois o rele liga quando recebe sinal LOW e desliga quando recebe sinal HIGH } Serial.print(F("\nEstado Atual Rele 4: ")); Serial.print(!digitalRead(pinoRele4)); Serial.println(); AdafruitEnvio_Rele4(); } }
No código, deve-se primeiro incluir as bibliotecas:
Após isso vem a definição dos endereços MAC e IP da placa Ethernet.
E então vem a definição de variáveis da Adafruit IO. Na variável AIO_USERNAME e AIO_KEY, você deve substituir o valor delas por suas credenciais da Adafruit IO: Nome de usuário e Chave Ativa, respectivamente.
E então, declaramos os pinos utilizados pelos relés.
Declaramos uma variável de controle para executarmos um trecho de código uma única vez dentro do loop. Veremos este trecho mais à frente.
Fazemos a instanciação das Classes Ethernet e Adafruit_MQTT_Client. Também uma configuração inicial.
Declaramos todos os feeds que utilizamos em Adafruit IO. Começamos com os feeds em que iremos fazer as publicações (do Arduino para Adafruit IO).
Depois declaramos os feeds em que iremos se inscrever (da Adafruit IO para Arduino).
Em void Setup (inicialização do programa), definimos os pinos dos relés como Saída e o setamos para nível Lógico HIGH para que fiquem desligados no ínicio. Em seguida, configuramos a taxa de transferência em bits por segundo (baud rate) para transmissão serial e iniciamos o MQTT Adafruit IO.
Em void Loop (programa principal em loop infinito), começamos verificando se há conexão com o servidor de Adafruit IO. Se não houver conexão a função tenta reconectar. Mais abaixo, dentro do loop, esperamos as assinaturas dos feeds chegarem. Ficamos esperando pelo tempo definido dentro da função readSubscription(), no nosso programa, esperamos por 5000 milissegundos. Fazemos uma condição com a variável ‘executaSoNoInicio’ para verificar se podemos executar as instruções. Esta condição só ficará verdadeira somente uma única vez, pois declaramos a variável de controle como false. Por fim, fazemos ping no servidor, pois ele exige que enviamos algo à ele de tempos em tempos.
Na função MQTT_conecta, através de uma condição, verificamos se há conexão ao Servidor Adafruit IO. Se não houver conexão, tentamos fazer conexão por 4 vezes seguidas, com um intervalo de 1,5 segundos. Se após as 4 tentativas, ainda não houver conexão, alertamos ao usuário, através do Serial Monitor, o código do erro. Os códigos de erro você pode verificar a seguir:
Na função subscricaoAdafruitIO, se inscrevemos nos feeds dos botões da Dashboard através da função mqtt.subscribe(& feedObject), onde feedObject é o objeto de subscrição que declaramos no início do programa.
Na função AdafruitRecebeMensagem_Rele1, verificamos se recebemos alguma mensagem do servidor Adafruit referente ao feed da seguinte condição: if(subscription == &botaoRele1). A mensagem recebida do servidor Adafruit IO está no método feedObject.lastread, onde feedObject é o objeto de subscrição. Após isso, enviamos ao servidor uma mensagem contendo um nome de ícone para que possamos ver que o arduino recebeu o comando da Dashboard Adafruit. A lista completa de ícones que você pode utilizar, você encontra em: https://io.adafruit.com/icons-faq.
Nesta mesma função, mudamos o estado do pino do relé de acordo com o que recebemos do Servidor Adafruit IO. Fazemos isto condição if (strcmp(botaoRele1.lastread, “0”) == 0). A função strcmp é uma função da linguagem C que compara duas strings e retorna 0 caso as duas strings serem iguais. Depois enviamos o ícone de status dependendo da leitura digital do pino do relé. Fazemos isso incluindo a função AdafruitEnvio_Rele1(). Esta função lê o pino referente ao relé e envia um determinado ícone dependendo da leitura digital realizada.
As outras funções dos outros relés, segue esta mesma lógica.
Agora desenvolveremos uma plataforma personalizada para poder acessar o sistema via Dispositivo Mobile. Caso se acessarmos a dashboard da Adafruit IO por um Smartphone, a organização dos blocos iria ser prejudicada.
Por isso desenvolveremos a plataforma personalizada.
Será necessário instalar uma biblioteca no Node-RED para exibição de um Painel Visual. Para isso, siga os passos abaixo.
Para fazer o painel (dashboard), importe o projeto para o seu editor Node-RED. Para isso, siga os passos abaixo.
[{"id":"be3bb942.e19898","type":"tab","label":"Flow Controle Reles","disabled":false,"info":""},{"id":"bdbb51de.7c761","type":"ui_form","z":"be3bb942.e19898","name":"Formulário de Login","label":"","group":"7218d749.0c8698","order":1,"width":0,"height":0,"options":[{"label":"Usuário","value":"user","type":"text","required":true,"rows":null},{"label":"Senha","value":"pass","type":"password","required":true,"rows":null}],"formValue":{"user":"","pass":""},"payload":"","submit":"Entrar","cancel":"Cancelar","topic":"","topicType":"str","splitLayout":"","x":140,"y":180,"wires":[["9f6e2d3a.3e1a6"]]},{"id":"9f6e2d3a.3e1a6","type":"function","z":"be3bb942.e19898","name":"Verificação de Login","func":"var userEntrada = msg.payload.user;\nvar passEntrada = msg.payload.pass;\n\nvar meuUsername = \"Substitua_isto_por_seu_Username_desejado\"; // Seu Username\nvar minhaSenha = \"Substitua_isto_por_sua_Senha_desejada\"; // Sua Senha\n\n/*flow.set(\"NomeDaVariavel\", ValorDaVariavel);: define uma váriavel global*/\nflow.set(\"id_Usuario\", msg.socketid); // Define o ID do usuário Atual\n\nmsg.payload = 0; // valor de identificação de usuário inválido\nif(userEntrada == meuUsername){\n msg.payload = 1; // valor de identificação de senha inválido\n if(passEntrada == minhaSenha){\n msg.payload = 2; // valor de identificação de usuário logado\n }\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":180,"wires":[["bd81e53.0f0fd18"]]},{"id":"bd81e53.0f0fd18","type":"switch","z":"be3bb942.e19898","name":"Direcionamento de condição","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"},{"t":"eq","v":"2","vt":"num"}],"checkall":"true","repair":false,"outputs":3,"x":600,"y":180,"wires":[["705601ca.509bf"],["dd05394d.3930d8"],["8b802c4e.1b047"]]},{"id":"705601ca.509bf","type":"function","z":"be3bb942.e19898","name":"Condição 0 - Usuário Inválido","func":"msg.payload = \"Usuário Inválido\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":890,"y":120,"wires":[["16eefa81.c09ac5"]]},{"id":"dd05394d.3930d8","type":"function","z":"be3bb942.e19898","name":"Condição 1- Senha Inválida","func":"msg.payload = \"Senha Inválida\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":160,"wires":[["16eefa81.c09ac5"]]},{"id":"8b802c4e.1b047","type":"function","z":"be3bb942.e19898","name":"Condição 2 - Login Efetuado","func":"msg.payload = \"Login Efetuado\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":200,"wires":[["a1be1e79.ff4de","4e4446b1.692388"]]},{"id":"16eefa81.c09ac5","type":"ui_toast","z":"be3bb942.e19898","position":"dialog","displayTime":"3","highlight":"red","sendall":false,"outputs":1,"ok":"Tente Novamente","cancel":"","raw":false,"topic":"","name":"Mensagem de Alerta de Falha","x":1190,"y":140,"wires":[[]]},{"id":"a1be1e79.ff4de","type":"ui_toast","z":"be3bb942.e19898","position":"bottom right","displayTime":"4","highlight":"green","sendall":false,"outputs":0,"ok":"OK","cancel":"","raw":false,"topic":"","name":"Mensagem de Sucesso de Logon do Usuário","x":1230,"y":180,"wires":[]},{"id":"b7a1e002.2b1d1","type":"comment","z":"be3bb942.e19898","name":"Tela de Login do Usuário","info":"","x":150,"y":120,"wires":[]},{"id":"4e4446b1.692388","type":"function","z":"be3bb942.e19898","name":"Direcionar para Tela Principal","func":"msg.payload = { \n group: {\n //show: Mostrar grupo\n show : [\"Dashboard_Controle_Reles_Sair\",\n \"Dashboard_Controle_Reles_Gerenciamento_dos_Reles\"],\n //hide: Esconder grupo\n hide : [\"Dashboard_Controle_Reles_Entrar\"]\n \n }\n};\nflow.set(\"Tempo_Sessao\",Date.now()); // Define o Tempo de Sessão com o Tempo Atual\n/*flow.set(\"NomeDaVariavel\",ValorDaVariavel);: define uma váriavel global*/\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1180,"y":220,"wires":[["cceca583.7eb418"]]},{"id":"f6e76a1e.0e7928","type":"ui_button","z":"be3bb942.e19898","name":"Btn Logout","group":"2841a806.b30388","order":0,"width":0,"height":0,"passthru":false,"label":"Logout","tooltip":"Clique aqui e saia da sessão atual. Será necessário fazer login novamente","color":"","bgcolor":"red","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":470,"y":700,"wires":[["90e0adf6.c6c18"]]},{"id":"fc082e89.5ab46","type":"function","z":"be3bb942.e19898","name":"Fazer Logout","func":"msg = {};\nflow.set(\"Tempo_Sessao\", 0);\nmsg.payload = { group: {\n show : [\"Dashboard_Controle_Reles_Entrar\"],\n hide : [\"Dashboard_Controle_Reles_Sair\", \"Dashboard_Controle_Reles_Gerenciamento_dos_Reles\"]\n }\n};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":910,"y":720,"wires":[["f1415df7.6af6f"]]},{"id":"f1415df7.6af6f","type":"ui_ui_control","z":"be3bb942.e19898","name":"Tela Logon","events":"all","x":1070,"y":720,"wires":[[]]},{"id":"cceca583.7eb418","type":"ui_ui_control","z":"be3bb942.e19898","name":"Tela Principal","events":"all","x":1390,"y":220,"wires":[[]]},{"id":"300ada1c.1e6e36","type":"comment","z":"be3bb942.e19898","name":"Tela de logout","info":"","x":470,"y":660,"wires":[]},{"id":"39bf8f8b.795d4","type":"inject","z":"be3bb942.e19898","name":"Timer 3 segundos","props":[],"repeat":"3","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"str","x":110,"y":480,"wires":[["8755431e.38cf7","a55e8973.63aae8"]]},{"id":"8755431e.38cf7","type":"function","z":"be3bb942.e19898","name":"Verificação de Sessão Expirada","func":"var Tempo_de_Sessao = flow.get(\"Tempo_Sessao\"); // flow.get(\"NomeDaVariavel\");: obtém o valor da váriavel global requerida\nvar Tempo_Atual = Date.now(); // Guarda o valor do Tempo Atual\nvar Tempo_de_Sessao_Maximo = 600000; // tempo de sessão máximo em milissegundos. 600000 ms = 10 minutos\n\n\nif(Tempo_de_Sessao == 0){//sem nenhum usuário logado...\n msg.payload = 0;\n}else{\n if(Tempo_Atual-Tempo_de_Sessao>Tempo_de_Sessao_Maximo){ // verifica se o tempo de sessão está dentro do limite\n msg.payload = 1;\n }\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":440,"wires":[["997176f.f172388"]]},{"id":"997176f.f172388","type":"switch","z":"be3bb942.e19898","name":"Direcionador de Condição","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":610,"y":440,"wires":[["1d631e.bec2ace2"],["fc4f05eb.8e9ba8"]]},{"id":"1d631e.bec2ace2","type":"function","z":"be3bb942.e19898","name":"Sem Usuario Logado - Mostra Logon","func":"var msg = {};\nmsg.payload = {group:{\n show:[\"Dashboard_Controle_Reles_Entrar\"],\n hide:[\"Dashboard_Controle_Reles_Sair\",\"Dashboard_Controle_Reles_Gerenciamento_dos_Reles\"]\n}};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":890,"y":420,"wires":[["2768f297.85dc0e"]]},{"id":"fc4f05eb.8e9ba8","type":"function","z":"be3bb942.e19898","name":"Tempo expirado - Mostra Logon","func":"flow.set(\"Tempo_Sessao\", 0); // zera a variável de Tempo de Sessão\nflow.set(\"id_Usuario\", undefined); // define o ID do Usuário como undefined, pois nenhum usuário está logado\n\nmsg.payload = \"Tempo de Sessão Expirado. Faça logon novamente.\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":870,"y":460,"wires":[["c554748d.7a96b8","7f84c508.2e36fc","578c973a.b858a8"]]},{"id":"7f84c508.2e36fc","type":"ui_toast","z":"be3bb942.e19898","position":"dialog","displayTime":"3","highlight":"","sendall":false,"outputs":1,"ok":"OK","cancel":"","raw":false,"topic":"","name":"Notificação Tempo Expirado","x":1220,"y":500,"wires":[[]]},{"id":"c554748d.7a96b8","type":"ui_audio","z":"be3bb942.e19898","name":"Narração da mensagem","group":"4506115d.9f004","voice":"Google português do Brasil","always":"","x":1210,"y":460,"wires":[]},{"id":"578c973a.b858a8","type":"function","z":"be3bb942.e19898","name":"Redirecionamento para Logon","func":"msg = {}; // zera msg para segurança\nmsg.payload ={group:{\n show:[\"Dashboard_Controle_Reles_Entrar\"],\n hide:[\"Dashboard_Controle_Reles_Sair\",\"Dashboard_Controle_Reles_Gerenciamento_dos_Reles\"]\n}};\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1230,"y":540,"wires":[["3bb2f13d.8be48e"]]},{"id":"3bb2f13d.8be48e","type":"ui_ui_control","z":"be3bb942.e19898","name":"Tela Logon","events":"all","x":1450,"y":520,"wires":[[]]},{"id":"2768f297.85dc0e","type":"ui_ui_control","z":"be3bb942.e19898","name":"Tela Logon","events":"all","x":1170,"y":420,"wires":[[]]},{"id":"a55e8973.63aae8","type":"function","z":"be3bb942.e19898","name":"Exibição de Tempo Final Sessão","func":"var tempo_De_Sessao = flow.get(\"Tempo_Sessao\"); // obtém o tempo de sessão\nvar tempo_Atual = Date.now(); // obtém o tempo atual\n\nif(tempo_De_Sessao == 0){\n \n return null;\n \n}else {\n \n var diferenca_Tempo = Math.floor((600000-(tempo_Atual-tempo_De_Sessao))/1000)+1;\n \n if(diferenca_Tempo <= 7 && diferenca_Tempo>=0){\n \n msg.payload = \"Tempo restante de Sessão: \"+diferenca_Tempo+\" Segundos.\";\n \n }else{\n \n return null;\n \n }\n \n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":520,"wires":[["9d2e383e.92d798"]]},{"id":"9d2e383e.92d798","type":"ui_toast","z":"be3bb942.e19898","position":"bottom right","displayTime":"2","highlight":"rgb(198, 192, 11)","sendall":false,"outputs":0,"ok":"OK","cancel":"","raw":false,"topic":"","name":"Notificação Tempo Final Sessão","x":630,"y":520,"wires":[]},{"id":"7c343889.0cf778","type":"comment","z":"be3bb942.e19898","name":"Controle Tempo de Sessão","info":"Este controle verifica se a sessão está dentro do limite de tempo definido.","x":150,"y":360,"wires":[]},{"id":"73eb6926.6e4698","type":"comment","z":"be3bb942.e19898","name":"LOGON","info":"","x":680,"y":40,"wires":[]},{"id":"18202030.e6ccc","type":"ui_toast","z":"be3bb942.e19898","position":"bottom right","displayTime":"5","highlight":"rgb(198, 192, 11)","sendall":false,"outputs":0,"ok":"OK","cancel":"","raw":false,"topic":"","name":"","x":790,"y":680,"wires":[]},{"id":"90e0adf6.c6c18","type":"function","z":"be3bb942.e19898","name":"","func":"msg.payload = \"Você será redirecionado para a Página Inicial em 3 segundos...\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":700,"wires":[["18202030.e6ccc","90f69c30.dbb4b"]]},{"id":"90f69c30.dbb4b","type":"delay","z":"be3bb942.e19898","name":"","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":760,"y":720,"wires":[["fc082e89.5ab46"]]},{"id":"4d669c9b.93f444","type":"comment","z":"be3bb942.e19898","name":"LOGOUT","info":"","x":700,"y":360,"wires":[]},{"id":"7f911944.835d48","type":"mqtt in","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","datatype":"auto","broker":"6193c04a.31dd2","nl":false,"rap":true,"rh":0,"x":370,"y":1020,"wires":[["ab61e541.d0e138"]]},{"id":"81e9cb66.bac5e8","type":"comment","z":"be3bb942.e19898","name":"Integração com Adafruit IO via MQTT","info":"","x":270,"y":920,"wires":[]},{"id":"61cdfb40.08de04","type":"mqtt in","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","datatype":"auto","broker":"6193c04a.31dd2","nl":false,"rap":true,"rh":0,"x":370,"y":1060,"wires":[["fba45296.8d26f"]]},{"id":"f43c6a28.3c1888","type":"mqtt in","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","datatype":"auto","broker":"6193c04a.31dd2","nl":false,"rap":true,"rh":0,"x":370,"y":1100,"wires":[["de83b31c.add57"]]},{"id":"b4091e44.3d82","type":"mqtt in","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","datatype":"auto","broker":"6193c04a.31dd2","nl":false,"rap":true,"rh":0,"x":370,"y":1140,"wires":[["d114c7e8.9554b8"]]},{"id":"f2360f64.14806","type":"comment","z":"be3bb942.e19898","name":"Status Reles","info":"","x":190,"y":980,"wires":[]},{"id":"7aea6c7a.2fd284","type":"ui_text","z":"be3bb942.e19898","group":"826135f6.525068","order":1,"width":0,"height":0,"name":"","label":"Status Relé 1 - Lâmpada","format":"{{msg.payload}}","layout":"row-spread","x":1010,"y":1020,"wires":[]},{"id":"fbf3f4e6.63b318","type":"ui_text","z":"be3bb942.e19898","group":"826135f6.525068","order":5,"width":0,"height":0,"name":"","label":"Status Relé 2 - Ventilador","format":"{{msg.payload}}","layout":"row-spread","x":1010,"y":1060,"wires":[]},{"id":"9e39203e.a3b7","type":"ui_text","z":"be3bb942.e19898","group":"826135f6.525068","order":9,"width":0,"height":0,"name":"","label":"Status Relé 3 - Lâmpada 2","format":"{{msg.payload}}","layout":"row-spread","x":1020,"y":1100,"wires":[]},{"id":"fb426f3d.15cfd","type":"ui_text","z":"be3bb942.e19898","group":"826135f6.525068","order":13,"width":0,"height":0,"name":"","label":"Status Relé 4","format":"{{msg.payload}}","layout":"row-spread","x":980,"y":1140,"wires":[]},{"id":"cb49215c.99709","type":"comment","z":"be3bb942.e19898","name":"Controle Reles","info":"","x":200,"y":1220,"wires":[]},{"id":"32867205.e7c22e","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":2,"width":0,"height":0,"passthru":false,"label":"Desligar Relé 1 - Lâmpada","tooltip":"Clique aqui e desligue o relé 1","color":"","bgcolor":"","icon":"","payload":"0","payloadType":"str","topic":"topic","topicType":"msg","x":240,"y":1260,"wires":[["e666da95.39d7a8"]]},{"id":"e0a35f0.7c2a7a","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":6,"width":0,"height":0,"passthru":false,"label":"Desligar Relé 2 - Ventilador","tooltip":"Clique aqui e desligue o relé 2","color":"","bgcolor":"","icon":"","payload":"0","payloadType":"str","topic":"topic","topicType":"msg","x":240,"y":1360,"wires":[["8d19c326.0c048"]]},{"id":"55450ad4.3d61e4","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":10,"width":0,"height":0,"passthru":false,"label":"Desligar Relé 3 - Lâmpada 2","tooltip":"Clique aqui e desligue o relé 3","color":"","bgcolor":"","icon":"","payload":"0","payloadType":"str","topic":"topic","topicType":"msg","x":240,"y":1460,"wires":[["f227cf32.bf9e6"]]},{"id":"f9b39945.ff63f8","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":14,"width":0,"height":0,"passthru":false,"label":"Desligar Relé 4","tooltip":"Clique aqui e desligue o relé 4","color":"","bgcolor":"","icon":"","payload":"0","payloadType":"str","topic":"topic","topicType":"msg","x":200,"y":1560,"wires":[["dd04cb44.98ed18"]]},{"id":"e666da95.39d7a8","type":"mqtt out","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"6193c04a.31dd2","x":650,"y":1280,"wires":[]},{"id":"8d19c326.0c048","type":"mqtt out","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"6193c04a.31dd2","x":650,"y":1380,"wires":[]},{"id":"f227cf32.bf9e6","type":"mqtt out","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"6193c04a.31dd2","x":650,"y":1480,"wires":[]},{"id":"dd04cb44.98ed18","type":"mqtt out","z":"be3bb942.e19898","name":"","topic":"seu_Username_em_Adafruit_IO/feeds/nome_do_feed_em_Adafruit_IO","qos":"2","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"6193c04a.31dd2","x":570,"y":1580,"wires":[]},{"id":"85f56556.26f798","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":3,"width":0,"height":0,"passthru":false,"label":"Ligar Relé 1 - Lâmpada","tooltip":"Clique aqui e ligue o relé 1","color":"","bgcolor":"","icon":"","payload":"1","payloadType":"str","topic":"topic","topicType":"msg","x":230,"y":1300,"wires":[["e666da95.39d7a8"]]},{"id":"1f83728f.c65e0d","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":7,"width":0,"height":0,"passthru":false,"label":"Ligar Relé 2 - Ventilador","tooltip":"Clique aqui e ligue o relé 2","color":"","bgcolor":"","icon":"","payload":"1","payloadType":"str","topic":"topic","topicType":"msg","x":230,"y":1400,"wires":[["8d19c326.0c048"]]},{"id":"105e4b15.3fc595","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":11,"width":0,"height":0,"passthru":false,"label":"Ligar Relé 3 - Lâmpada 2","tooltip":"Clique aqui e ligue o relé 3","color":"","bgcolor":"","icon":"","payload":"1","payloadType":"str","topic":"topic","topicType":"msg","x":230,"y":1500,"wires":[["f227cf32.bf9e6"]]},{"id":"1b818a29.9de726","type":"ui_button","z":"be3bb942.e19898","name":"","group":"826135f6.525068","order":15,"width":0,"height":0,"passthru":false,"label":"Ligar Relé 4","tooltip":"Clique aqui e ligue o relé 4","color":"","bgcolor":"","icon":"","payload":"1","payloadType":"str","topic":"topic","topicType":"msg","x":190,"y":1600,"wires":[["dd04cb44.98ed18"]]},{"id":"ab61e541.d0e138","type":"function","z":"be3bb942.e19898","name":"Filtro para verificar status","func":"if(msg.payload == \"w:cloud-refresh\"){\n msg.payload = \"Atualizando...\";\n}else if(msg.payload == \"star\"){\n msg.payload = \"Lâmpada Ligada\"\n}else if(msg.payload == \"star-o\"){\n msg.payload = \"Lâmpada Desligada\"\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":1020,"wires":[["7aea6c7a.2fd284"]]},{"id":"fba45296.8d26f","type":"function","z":"be3bb942.e19898","name":"Filtro para verificar status","func":"if(msg.payload == \"w:cloud-refresh\"){\n msg.payload = \"Atualizando...\";\n}else if(msg.payload == \"w:wind-beaufort-1\"){\n msg.payload = \"Ventilador Ligado\"\n}else if(msg.payload == \"w:wind-beaufort-0\"){\n msg.payload = \"Ventilador Desligado\"\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":1060,"wires":[["fbf3f4e6.63b318"]]},{"id":"de83b31c.add57","type":"function","z":"be3bb942.e19898","name":"Filtro para verificar status","func":"if(msg.payload == \"w:cloud-refresh\"){\n msg.payload = \"Atualizando...\";\n}else if(msg.payload == \"star\"){\n msg.payload = \"Lâmpada Ligada\"\n}else if(msg.payload == \"star-o\"){\n msg.payload = \"Lâmpada Desligada\"\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":1100,"wires":[["9e39203e.a3b7"]]},{"id":"d114c7e8.9554b8","type":"function","z":"be3bb942.e19898","name":"Filtro para verificar status","func":"if(msg.payload == \"w:cloud-refresh\"){\n msg.payload = \"Atualizando...\";\n}else if(msg.payload == \"check\"){\n msg.payload = \"Relé Ligado\"\n}else if(msg.payload == \"power-off\"){\n msg.payload = \"Relé Desligado\"\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":1140,"wires":[["fb426f3d.15cfd"]]},{"id":"7218d749.0c8698","type":"ui_group","name":"Entrar","tab":"d99f7698.7698a8","order":1,"disp":true,"width":"6","collapse":false},{"id":"2841a806.b30388","type":"ui_group","name":"Sair","tab":"d99f7698.7698a8","order":3,"disp":true,"width":"3","collapse":false},{"id":"4506115d.9f004","type":"ui_group","name":"Narração","tab":"d99f7698.7698a8","order":4,"disp":true,"width":"3","collapse":false},{"id":"6193c04a.31dd2","type":"mqtt-broker","name":"Servidor Adafruit IO","broker":"io.adafruit.com","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"826135f6.525068","type":"ui_group","name":"Gerenciamento dos Reles","tab":"d99f7698.7698a8","order":2,"disp":true,"width":"6","collapse":false},{"id":"d99f7698.7698a8","type":"ui_tab","name":"Dashboard Controle Reles","icon":"","disabled":false,"hidden":false}]
Para se conectar ao servidor da Adafruit IO, é necessário alterar algumas coisas. Mais antes, você deve pegar as credencias da sua conta em Adafruit IO. Para isso, siga os passos abaixo:
Com conhecimento de suas credenciais, continue os passos abaixo para o desenvolvimento da plataforma em Node-RED.
Processo de preenchimento com os Feeds para Status Reles
Agora iremos preencher com os feeds os botões, localizados na parte Controle Reles. Para isso, siga os passo abaixo:
Processo de preenchimento com os Feeds para Controle Reles
Ficará assim:
Agora você deve criar um usuário e uma senha para acessar o painel Node-RED. Para isso, siga os passos abaixo:
Após terminar todas estas alterações, o painel ficou pronto. Mas antes devemos implantá-lo. Para isso, clique no botão Deploy, localizado no canto superior direito da página.
Antes de prosseguirmos, devemos ver o endereço web em que estamos. Pegue o endereço eletrônico atual e retire tudo depois da barra / . Então coloque a sigla ui e aperte Enter no Teclado. Exemplo: Se o endereço eletrônico atual é https://node-red-controle-de-cargas.mybluemix.net/red/#flow/4gt5re0w.o25e6f então ficará https://node-red-controle-de-cargas.mybluemix.net/ui.
Para mais detalhes da plataforma Node-RED, acesse site da IBM Cloud sobre Node-RED.
Visualização em Desktop
Visualização em Dispositivo Mobile
Com a plataforma para Dispositivos Mobile Node-RED concluída, podemos prosseguir.
Veja o vídeo abaixo para ver o funcionamento final.
Com este exemplo de controle de cargas pela internet, abre-se portas para projetos mais complexos, até mesmo automação residencial. Caso ficou alguma dúvida, nos contate através dos comentários. Espero que o tenha ajudado e até a próxima.
Tenha a Metodologia Eletrogate na sua Escola! Conheça nosso Programa de Robótica Educacional.
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Tenha a Metodologia Eletrogate dentro da sua Escola! Conheça nosso Programa de Robótica nas Escolas!