Está precisando de uma ferramenta para criar sistemas supervisórios para os seus projetos de IoT? O Node-red é uma excelente ferramenta, gratuita, para resolver esse e muitos outros problemas.
Neste post vamos conhecer o Node-red, aprender como instalá-lo, criar uma aplicação que permite ler dados vindos via ethernet por um Arduino e exibir eles em um dashboard.
Agora vamos lá para mais um excelente aprendizado aqui no blog.
Sumário
1. O que é Node-red?
O Node-red é uma ferramenta gratuita de código aberto que permite, através de um ambiente visual, utilizar nós para realizar eventos http, tcp, comunicação serial, websocket, twitter, mqtt e além de muitas outras, como já mencionado, conectar com dispositivos IoT.
Na próxima figura podemos ver um exemplo de fluxo de dados implementado no Node-red, nele realiza-se uma requisição http para obter dados de sensores que são tratados e exibidos no dashboard.
Vamos entender o funcionamento básico desse fluxo, o nó 1 é responsável por disparar o próximo, isso pode ser feito manualmente ou configurado para realizar automaticamente, 2 realiza a requisição dos dados do web server, criado pelo Arduino, recebidos em forma de string são enviados para o nó 3 que realiza algumas alterações nessa string para adequada ao padrão JSON(visto com mais detalhes mais a frente), o 6 é utilizado para debug, com ele podemos ver o dados que está trafegando. O bloco 4 converte o dado de string para JSON e por fim os nós finais, sem numeração, são responsáveis por enviar os dados para o dashboard.
Esse foi somente um exemplo de aplicação, similar com o que vamos implementar nesse post, porém, temos a disposição cerca de 40 nós padrão, mas muitos outros podem ser adicionados, os do dashboard são um exemplo desses nós adicionais.
Para mais informações sobre o Node-red acesse o site oficial.
2. Instalando Node-red no Windows.
Agora vamos ver como realizar a instalação do Node-red no Windows. A base desse passo-a-passo foi retirada do site oficial, em caso de dúvida ele pode ser consultado.
Passo 1- Instalar o Node.js
O download da última versão do node.js pode ser realizada através do seu site oficial. Estará disponível a melhor versão para o teu sistema operacional.
Após realizar o download basta executar o instalador, a instalação requer direitos de administrador, no geral basta somente prosseguir com a instalação sem necessidade de alterar nada.
Ao longo do processo ele pode abrir o prompt de comandos. Espere a instalação terminar por completo e feche todas as janelas abertas, depois abra o prompt de comandos, Powershell ou cmd, e vamos verificar se a instalação está correta. Execute o seguinte comando:
Usando Powershell:
node --version; npm --version
Usando cmd:
node --version && npm --version
Deve aparecer algo parecido com isso:
Para remover o warning vá até a pasta onde está instalado o node.js, copie esses dois arquivos para a área de trabalho e abra eles com o bloco de notas.
Substitua o -g por --location=global nos dois arquivos, após salvar copie eles de volta para a pasta original, substituindo os originais pelos novos.
Passo 2- Instalar o Node-red
A instalação do Node-red é nem simples, abra o prompt de comandos e digite a seguinte linha:
npm install -g --unsafe-perm node-red
Após finalizar a instalação, para executar o Node-red basta escrever node-red no prompt de comandos, essa janela deve permanecer aberta para que o programa seja executado. Para abrir a interface do programa deve-se digitar o IP do servidor no navegador, 127.0.0.1:1880 ou localhost:1880.
3. Enviando os dados do Arduino.
Agora vamos deixar o Node-red de lado um pouco e vamos preparar o arduino para enviar os dados. Para essa implementação foi utilizada a placa CPB Mini, junto com o shield ethernet W5500. A CPB Mini possui um ATmega1280, portanto, comporta-se como um Arduino mega.
A figura a seguir representa a topologia do sistema, a CPB comunica ethernet com o modem que envia os dados por wifi para o Node-red.
Na tabela a seguir podemos ver os pinos que foram utilizados para a comunicação com o shield ethernet, vale destacar que dessas podemos alterar somente o Chip Select (CS).
A base utilizada no desenvolvimento desse código foi o exemplo WebServer, disponível na IDE do Arduino, Arquivo -> Exemplos -> Ethernet -> WebServer. Nosso objetivo é primeiro estabelecer a comunicação com o Arduino usando o exemplo, para isso precisamos fazer duas alterações iniciais, ajustar o IP e definir o pino de Chip Set.
Para escolher o IP primeiro precisamos saber qual o IP dos dispositivos da rede, para isso basta abrir o cmd e digitar o seguinte comando arp -a, O resultado será algo assim:
Como podemos ver na imagem o IP do meu roteador é 192.168.8.1, então os demais dispositivos na rede será alterado somente o último número, ficando por exemplo 192.168.8.2, 192.168.8.3, 192.168.8.4 e assim até 192.168.8.255. Portanto, deve-se escolher um endereço disponível para o Arduino utilizar, ou seja, não podemos utilizar o do roteador, nem de qualquer outro dispositivo que está na rede.
Então o primeiro passo é substituir o IP do exemplo, 192.168.1.177, por um endereço válido na minha rede, vou usar 192.168.8.100. IPAddress ip(192, 168, 8, 100).
Agora devemos definir qual o pino de inicialização do shield Ethernet, Chip Select, para isso devemos colocar na primeira linha do setup a função Ethernet.init(PINO), onde devemos informar o pino do Arduino que está ligado no pino CS do shield, no nosso caso será o 53, portanto, Ethernet.init(53).
Agora podemos carregar o código no Arduino e conectar ele na porta ethernet do roteador. Para acessar os dados é necessário digitar o IP do dispositivo no navegador, o resultado deve ser esse:
Agora que já estamos comunicando vamos modificar o código para enviar os dados em um formato mais adequado, JSON, mas primeiro vamos entender um pouco sobre esse formato de dados.
JSON
De uma forma simplificada, JSON é um formato bem simples e leve de troca de informações entre sistemas. Além disso, ele é muito simples de ler, sendo tratado pelo node-red como um objeto JavaScript. A seguir veja um exemplo de declaração de objetos JASON.
{
“temperatura”:30,
“velocidade”:80,
“nome”:“Thales”
}
No exemplo estamos declarando três objetos, temperatura, velocidade e nome, atribuímos também um valor a cada um deles, 30, 80 e Thales, respectivamente. Isso significa que, na hora de processar esse pacote de dados, para ler a temperatura eu posso me referir a ela diretamente, como um objeto da minha mensagem, veja o exemplo.
temperatura_atual = mensagem.temperatura;
Desta forma a variável “temperatura_atual” receberá o valor da temperatura. O mesmo pode ser feito para os outros objetos. Podemos também ter um objeto raiz e seus atributos como o exemplo a seguir:
{
“usuario”:{
“nome”:”Thales”,
“idade”:29,
“cidade”:”Pelotas”
}
}
Agora o objeto usuário possui três atributos, nome, idade e cidade, que podem ser lido individualmente da seguinte forma:
nome_usuario = mensagem.usuario.nome;
idade_usuario = mensagem.usuario.idade;
Podemos ter também um vetor de objetos, nesse caso vamos ver o formato do JSON que vamos enviar com o Arduino, vamos transmitir a leitura de dois sensores analógicos e duas entradas digitais, para isso será usado os seguintes vetores de objetos:
{
“analogData”:[
{
“type”:”Tensão”,
“value”:5
},
{
“type”:”Temperatura”,
“value”:16
}
],
“booleanData”:[
{
“type”:”Botão”,
“value”:0
},
{
“type”:”Motor”,
“value”:1
}
]
}
Agora temos dois vetores de objetos, um para valores analógicos e outro para dados binários, dessa forma cada posição do meu vetor armazena um valor e a sua descrição, assim podemos facilmente identificar do que trata-se aquela informação, além de agrupar os valores semelhantes.
Nesse projeto vamos utilizar os dados da mesma forma que no último exemplo, com a diferença que o valor será definido pelo Arduino na hora de enviar os dados.
Enviando os dados JSON
Para enviar os dados vamos modificar a parte do código responsável por montar a página que vemos quando acessamos o IP do Arduino. A figura a seguir mostra o código original do exemplo, nele a página é construída utilizando html. A parte destacada será substituída por application/json, assim definimos que o dado enviado será um JSON.
Do código da figura vamos manter somente as primeiras três linhas, o resto será deletado para dar espaço para os dados que serão enviados, no formato JSON. Então o cabeçalho do código será o seguinte:
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println();
A partir daqui será implementado os códigos para enviar os dados no formato JSON. Vamos enviar a temperatura lida por um sensor, a tensão medida por uma entrada analógica e dois pinos digitais. O código é o seguinte:
client.println("{ 'analogData':[");
client.println("{ 'type': 'Tensão','value':");
client.println((analogRead(0)*5.0)/1023.0);
client.println("},");
client.println("{ 'type': 'Temperatura','value':");
client.println((analogRead(1)*5.0)/10.23);
client.println("}],");
client.println(" 'booleanData':[");
client.println("{ 'type': 'botao','value':");
client.println(digitalRead(2));
client.println("},");
client.println("{ 'type': 'motor','value':");
client.println(digitalRead(3));
client.println("}");
client.println("]}");
Carregando esse código no Arduino, quando acessamos o IP pelo navegador vamos acessar os dados no formato JSON, o resultado deve ser assim:
É importante ressaltar que o JSON deve ser feito com aspas duplas, porém, no Arduino é necessário utilizar aspas simples, devido a sintaxe da função, portanto, o dado não está totalmente correto, porém, vamos resolver esse problema no Node-red.
4. Criando aplicação no node-red
Agora podemos desenvolver a aplicação no Node-red, mas primeiro vamos precisar baixar alguns nós que vamos utilizar no dashboard. Para isso é necessário abrir o prompt de comando e digitar as seguintes linhas no terminal, com o Node-red fechado:
npm i node-red-dashboard
npm install node-red-contrib-ui-led
Agora devemos executar o Node-red e acessar ele pelo navegador, usando o IP localhost:1880.
1º Passo - Montar as ligações dos nós
O primeiro passo é montar o fluxo que será executado, na figura a seguir podemos ver as ligações e os nós utilizados, monte as ligações da mesma forma que na figura.
2º Passo - Configuração dos nós
O próximo passo é configurar cada um dos nós, começaremos da esquerda para direita.
Inject
Este é o nó responsável por disparar o sistema, sempre que ele for acionado o fluxo será executado, porém, vamos configura-lo também para disparar automaticamente, na figura a seguir temos como ele foi configurado, para abrir as configurações do nó basta dar um clique duplo nele.
Http request
Este nó é responsável por fazer a requisição dos dados no Arduino, devemos configurá-lo com o IP do dispositivo, ele irá enviar para o próximo bloco uma string com os dados recebidos.
Change
Esse nó será responsável por trocar as aspas simples por duplas, para deixar a string no formato JSON corretamente. Será simplesmente uma troca de caracteres da string.
JSON
Esse é responsável por converter a string em JSON, a partir daqui o pacote de dados será interpretado como um JSON e não mais uma string.
Gauge
Esses são nós do dashboard, serão usados para exibir a tensão e a temperatura, nas figuras a seguir temos as configurações deles, note que a parte destacada é o código responsável por definir o dado da mensagem que será exibido.
Function
Esse nó permite inserir uma função desenvolvida em javascript, assim podemos processar a mensagem para enviar somente o dado desejado para o próximo bloco, nesse caso ele seleciona o dado e manda verdadeiro ou falso com base no valor da variável. As figuras mostram o código usado.
Nesse outro function, estamos selecionando para enviar somente o valor da temperatura.
Led
Esses dois nós também são do dashboard, são dois leds para indicar o estado dos dois pinos do Arduino. Eles não permitem ajustar o dado que será usado, igual o gauge, por isso é necessário utilizar o function.
Chart
Esse é o último nó do dashboard, ele é capaz de criar um gráfico com os dados que ele recebe, da mesma forma que o LED, não permite selecionar o dado na mensagem, por isso é necessário utilizar o function.
O nó que sobra, sem descrição, é o debug, com ele podemos visualizar os dados que chegam nele, utilizando a tela de debug. Veja na imagem a seguir como acessar a janela de debug.
3º Passo - Layout do dashboard
A figura a seguir mostra onde pode-se acessar o dashboard. Clicando na seta na lateral direita abrirá o menu, depois basta acessar o dashboard.
Na aba home o menu layout estará disponível. Após acessar o layout basta posicionar os dispositivos como desejar, para acessar o dashboard utilize localhost:1880/ui.
Para acessar o dashboard de outro computador, da mesma rede, deve-se colocar o IP do computador que está executando o node-red seguido de :1880, por exemplo 192.168.8.105:1880.
Gostou do conteúdo? tenta fazer esse exemplo aí, quando conseguir compartilha nas redes sociais e marca a gente @crescer_automacao!
ANEXO - Código exemplo
/*Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
Ethernet shield attached to pins 10, 11, 12, 13
Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 8, 100);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(8080);//8080 para acesso externo
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
Ethernet.init(53);
pinMode(2, INPUT);
pinMode(3, INPUT);
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println();
client.println("{ 'analogData':[");
client.println("{ 'type': 'Tensão','value':");
client.println((analogRead(0) * 5.0) / 1023.0);
client.println("},");
client.println("{ 'type': 'Temperatura','value':");
client.println((analogRead(1) * 5.0) / 10.23);
client.println("}],");
client.println(" 'booleanData':[");
client.println("{ 'type': 'botao','value':");
client.println(digitalRead(2));
client.println("},");
client.println("{ 'type': 'motor','value':");
client.println(digitalRead(3));
client.println("}");
client.println("]}");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
Avalie-nos no Google para que possamos alcançar e auxiliar cada vez mais pessoas a fazerem seus projetos e produtos! Contamos com você!
Autor: Thales Ferreira