Programando Visualmente com Node-RED: Conectando a Internet das Coisas com Facilidade
Publicados: 2022-03-11Por meio da programação, fazemos com que as máquinas imitem comportamentos complexos seguindo sequências de instruções simples. Usar linguagens de programação textuais como Assembly, C, Python e JavaScript é uma das principais maneiras de fazer isso. Os designers dessas linguagens de programação passaram inúmeras horas tentando tornar a experiência de escrever programas o mais fácil possível por meio de sintaxe expressiva, construções de programação robustas e poderosas cadeias de ferramentas. No entanto, todas essas linguagens de programação compartilham um traço comum: código-fonte textual.
Escrever programas em texto funciona e, na maioria dos casos, funciona bem. No entanto, a capacidade de expressar programas visualmente é muitas vezes desejável. Ser capaz de projetar o fluxo de informações através de vários componentes de um sistema maior geralmente é tudo o que é necessário. As ferramentas de programação visual também são tolerantes para quem é novo em programação e está lutando para lidar com vários conceitos, como variáveis, ponteiros, sinais, escopos e assim por diante.
Node-RED é uma ferramenta para programação visual. Ele exibe relações e funções visualmente e permite que o usuário programe sem precisar digitar um idioma. O Node-RED é um editor de fluxo baseado em navegador onde você pode adicionar ou remover nós e conectá-los para que eles se comuniquem entre si.
No Node-RED, cada nó é um dos dois tipos a seguir: um nó de injeção ou um nó de função . Os nós de injeção produzem uma mensagem sem exigir nenhuma entrada e enviam a mensagem para o próximo nó conectado a ela. Os nós de função, por outro lado, recebem uma entrada e realizam algum trabalho nela. Com uma infinidade desses nós para escolher, o Node-RED torna a conexão de dispositivos de hardware, APIs e serviços online mais fácil do que nunca.
Introdução ao Node-RED
O Node-RED é construído em Node.js. Para instalar o Node-RED, você precisará ter o Node.js e o NPM instalados. Com o NPM, é super fácil instalar o Node-RED:
npm install -g node-red
O editor de fluxo do Node-RED é um aplicativo baseado em navegador da web. Para poder usá-lo, execute o Node-RED:
node-red
&hellip e navegue até http://localhost:1880.
Olá Mundo!
Que tutorial de programação para iniciantes está completo sem aprender a dizer “Olá, mundo”? Vamos começar tentando exatamente isso:
- Arraste e solte um nó de injeção no editor de fluxo. Em seguida, clique duas vezes e configure o payload como string e escreva “Hello world”.
- Arraste e solte um nó de depuração , da mesma forma que você fez com o de injeção.
- Ligue-os juntos.
- Clique no botão “Implantar” no canto direito.
- Clique no botão azul à esquerda do nó de injeção .
Tente. Você verá algo assim:
Apenas JavaScript
Com o Node-RED, você não está limitado apenas a nós e funcionalidades simples. Como o Node-RED é construído no Node.js, ele é todo desenvolvido com JavaScript. Os nós são, de fato, módulos Node.js. Eles podem ser encontrados em http://flows.nodered.org/, então, para adicioná-los ao seu painel esquerdo, você pode simplesmente “instalá-los npm”. Na verdade, você pode desenvolver seu próprio fluxo e carregá-lo no repositório de fluxo. Os aplicativos podem ser tão complexos quanto você quiser, porque você pode digitar JavaScript em nós de função dentro do editor de código que o Node-RED fornece.
Como a plataforma é baseada em Node.js, ela aproveita o mesmo modelo sem bloqueio e orientado a eventos. Assim, um aplicativo construído em Node-RED pode ser executado em hardware de baixo custo como o Raspberry Pi, bem como na nuvem.
Agora Let's Go Pro: Hora da Automação Residencial
Para demonstrar como o Node-RED se encaixa no reino da Internet das Coisas, vamos construir um aplicativo para alterar a cor de uma lâmpada inteligente. Nem todos podem ter o mesmo sistema de iluminação inteligente à sua disposição, mas não há com o que se preocupar, pois você pode encontrar o módulo Node-RED apropriado no repositório oficial de fluxo. No entanto, para tornar as coisas ainda mais fáceis, vamos para algo mais inteligente.
Conheça o NetBeast. É uma plataforma de código aberto para desenvolver aplicativos para dispositivos e dispositivos da Internet das Coisas sem precisar se preocupar com detalhes como protocolos sem fio, compatibilidade de marcas ou ter que saber lidar com cada API específica existente. Ele nos permite usar dispositivos virtuais que agem como reais! Portanto, mesmo se você não tiver uma lâmpada inteligente, terá uma virtual disponível.
Podemos instalar o pacote npm Netbeast for Node-RED globalmente assim:
npm install -g node-red-contrib-netbeast
O nó netbeast-red representará o Netbeast Dashboard, que traduzirá suas primitivas de API para todos os seus dispositivos inteligentes que você tem em casa. Felizmente também está disponível como módulo!
Inicie o NetBeast:
npm install -g netbeast-cli netbeast start
Isso tornará o painel disponível na porta 8000 e SSL na 8443. Em seguida, abra seu navegador em http://localhost:8000 e navegue até Explorar. Lá poderemos encontrar muitos aplicativos e plugins. Procure as marcas de suas lâmpadas inteligentes (Philips Hue, LIFX, WeMo) ou, se você não tiver uma, tente baixar o plug-in da lâmpada. Verifique se seus plugins do Dashboard contêm um desses!
O emblema amarelo indica que os plug-ins estão em execução, mas não conseguem encontrar nenhum dispositivo. Clique no plug-in da lâmpada para criar uma lâmpada virtual. Quaisquer outros dispositivos descobertos devem aparecer em Rede.
Com tudo no lugar, vamos voltar ao trabalho. Faremos um fluxo simples:
- Arraste e solte um nó de injeção.
- Arraste e solte o nó Netbeast.
- Arraste e solte um nó de depuração.
- Ligue tudo como mostrado abaixo:
Agora vamos enviar uma solicitação HTTP para o Dashboard. Usando a API Netbeast, teremos que enviar pelo nó de injeção um JSON contendo os valores que queremos acionar em nosso bulbo.
Pressione o botão para injetar a cor e a energia em todas as suas lâmpadas inteligentes!
Cada tópico representa um tipo diferente de dispositivo. Portanto, há tópicos para luzes, mas também para música, aquecimento e vídeo; bem como sensores de umidade, presença, temperatura, e a lista continua. Você pode encontrar em sua documentação uma lista de tópicos e sua estrutura recomendada para ser traduzida para todos os tipos de dispositivos. Esse mecanismo de IoT é imaturo, mas poderoso. Código aberto que permite aos desenvolvedores reutilizar informações para criar cenários verdadeiramente conectados, sendo assim inteligentes.
Vamos mais fundo
Em seguida, criaremos um segundo fluxo usando outro plugin, um detector de ruído ambiente, para usá-lo como gatilho para alterar a cor da lâmpada como semáforo de ruído. Neste tutorial, usaremos um virtual, portanto, não há necessidade de comprar um novo hardware. Vamos começar clicando no botão “mais” no editor Node-RED.
Vá novamente no Dashboard http://localhost:8000/explore para a seção Explore e procure por Volume-Plugin. É um aplicativo da web muito rudimentar que aproveita getUserMedia()
no navegador para capturar mídia de um aplicativo HTML simples. Portanto, provavelmente só funcionará em navegadores modernos!
Clique nele para abrir, como acontece com a lâmpada virtual. Ele pedirá permissão para gravar do seu microfone. Em seguida, ele enviará as mensagens para o broker MQTT da Netbeast, que serão compartilhadas em todo o Dashboard, e assim poderemos assinar. Para fazer isso, precisamos apenas arrastar e soltar um nó netbeast-trigger no editor do node-red. Em seguida, inseriremos uma função entre o gatilho e o nó Netbeast para decidirmos quando está muito alto ou não. Além disso, devemos usar alguns nós de depuração para verificar se está tudo bem. O esquema agora será mais ou menos assim:
Agora, vamos inserir algum código no nó de função tooLoud. Sim, eu sei que prometi que você poderia programar sem precisar codificar, mas já mostrei que você pode! E você pode tentar combinar os diferentes elementos disponíveis ou outros nós do registro para realizar o seguinte.
var volume = msg.payload.volume node.log(volume) if (volume < 50) { return { topic: 'lights', payload: { power: 1, color: '#00CC00'}} } else if (volume < 75) { return { topic: 'lights', payload: { power: 1, color: '#CCCC00'}} } else { return { topic: 'lights', payload: { power: 1, color: '#FF0000'}} }
Esse trecho de código bastante simples está retornando uma das três cargas úteis para o próximo nó com um código de cor específico, dependendo do nível de volume relatado pelo nó anterior.
Agora estamos prontos para ir! Vamos chutar o botão Deploy novamente e fazer barulho. Vamos ver como a lâmpada muda de uma cor para outra imediatamente!
Como o microfone e o navegador da Web que você está usando podem ser diferentes, sinta-se à vontade para ajustar os valores e limites da função e também brincar com os valores de cor para ver como ele muda suas lâmpadas.
Criando seus próprios plugins
Esta lâmpada em CSS puro foi inspirada neste cssdeck.
Como você deve ter notado, a lâmpada virtual de antes é muito rudimentar, então você pode querer ajustá-la. Ou melhor ainda, você pode criar seus próprios controladores domésticos inteligentes. Assim, passaremos pelo processo de criação de um plugin virtual para o Netbeast, que permitirá que você crie seus próprios controladores para dispositivos inteligentes.
Você pode usar o pacote netbeast-cli
para gerar automaticamente algum código. Ao executar netbeast create myplugin --plugin
, acabaríamos com um projeto básico como o seguinte:
myplugin ├── README.md ├── index.js ├── package.json └── test.js
O Front-end
Agora, vamos começar a mimetizar a lâmpada com um frontend. Os controladores de dispositivo geralmente não terão um, portanto, nenhuma pasta pública está incluída no comando scaffold ainda. Vamos criar um diretório public
dentro do projeto e colocar lá os seguintes arquivos HTML, CSS e JS.
index.html
<head> <title>Netbeast Bulb Plugin</title> <link rel="stylesheet" href="bulb.css" media="screen" charset="utf-8"> </head> <body> <div class="top-decoration"></div> <div> </div> <div class="bulb-container small"> <div class="bulb light"> <div> <div class="bulb top"></div> <div class="bulb middle-1"></div> <div class="bulb middle-2"></div> <div class="bulb middle-3"></div> <div class="bulb bottom"></div> </div> <div> <div class="screw-top"></div> <div class="screw a"></div> <div class="screw b"></div> <div class="screw a"></div> <div class="screw b"></div> <div class="screw a"></div> <div class="screw b"></div> <div class="screw c"></div> <div class="screw d"></div> </div> </div> </div> <div class="code-container"> <pre><i class="txt-red">beast</i>(<i class="txt-green">'lights'</i>).<i class="txt-blue">set</i>({ <i class="txt-green">color</i>: <i class="txt-green">"<input type="text" class="color" name="color" value="00fea5">"</i>, <i class="txt-green">power</i>: <i class="txt-green">"<input type="text" class="power" name="power" value="on">"</i> })</pre> <button> RUN </button> </div><!-- wrapper --> <!-- declares bulb features and methods --> <script type="text/javascript" src="bulb.js"></script> <!-- real time comms library --> <script type="text/javascript" src="socketio.js"></script> <!-- simulates hardware communication --> <script type="text/javascript" src="hw-api.js"></script> </body>
bulb.css
section { float: left; padding: 20px 50px 20px 50px; } .bulb-light { border: 0; background: transparent; margin: 0 auto !important; padding: 0 !important; display: block; z-index: 1; } #bulb { opacity: 1; z-index: 3; display: block;} .bulb.top { border: 0; width: 300px; height: 300px; margin: 0 auto; padding: 0; border-radius: 999px; background: #E7E7E7; } .bulb.middle-1 { margin: -75px auto 0 auto; width: 190px; border-left: 35px solid transparent; border-right: 35px solid transparent; border-top: 55px solid #E7E7E7; } .bulb.middle-2 { margin: -22px auto 0 auto; width: 178px; border-left: 19px solid transparent; border-right: 19px solid transparent; border-top: 50px solid #E7E7E7; } .bulb.middle-3 { margin: -20px auto 0 auto; width: 182px; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 30px solid #E7E7E7; } .bulb.bottom { width: 184px; height: 65px; margin: -8px auto 0 auto; padding: 0; border-radius: 0 0 999px 999px; background: #E7E7E7; } #base { position:relative; z-index: 2; } .screw { transform: rotate(-3deg); -ms-transform: rotate(-3deg); -webkit-transform: rotate(-3deg); padding: 0; } .screw-top { margin: -18px auto -4px auto; padding: 0; width: 132px; height: 0; border-left: 15px solid transparent; border-right: 15px solid transparent; border-top: 21px solid #D3D3D3; border-radius: 999px; } .screw.a { background: #DDD; width: 150px; height: 15px; border-radius: 999px; margin: -1px auto 0px; } .screw.b { background: #D9D9D9; width: 135px; height: 15px; margin: -1px auto 0px; } .screw.c { margin: -1px auto 0px; width: 78px; height: 0; border-left: 30px solid transparent; border-right: 30px solid transparent; border-top: 20px solid #DDD; border-radius: 8px; } .screw.d { margin: 0 auto; width: 15px; height: 0; border-left: 30px solid transparent; border-right: 30px solid transparent; border-top: 15px solid #444; } .on #light { -moz-opacity: 1; -khtml-opacity: 1; opacity: 1; } .bulb.top, .bulb.bottom { transition: all 0.5s ease-in-out; } .bulb.middle-1, .bulb.middle-2, .bulb.middle-3 { transition: all 0.5s ease-in-out; }
Com esses arquivos HTML e CSS, você já deve conseguir ver uma forma de bulbo em seu navegador. Vá em frente e abra seu arquivo HTML para vê-lo ao vivo! Está funcionando? Ótimo, agora vamos dar algumas funcionalidades.

bulb.js
Este arquivo irá imitar o comportamento de uma lâmpada com um simples clique em, clique em desligar e configurará algumas funções que serão usadas em breve para alterar sua cor através do Netbeast.
var color = document.getElementById('color') var power = document.getElementById('power') var bulb = document.getElementById('bulb') var button = document.getElementById('run-btn') var light = document.getElementById('light') button.onclick = function toggleBulbState () { changeBulbParams({ color: color.value, power: power.value }) } function setBulbParams (params) { if (params.power === 'off') { params = { color: 'E7E7E7' } } console.log('set params', params) var bulb_parts = ['.bulb.middle-1', '.bulb.middle-2', '.bulb.middle-3'] document.querySelector('.bulb.top').style.boxShadow = '0px 0px 98px #' + params.color document.querySelector('.bulb.top').style.backgroundColor = params.color document.querySelector('.bulb.bottom').style.backgroundColor = params.color bulb_parts.forEach(function (className) { document.querySelector(className).style.borderTopColor = params.color }) } function changeBulbParams (params) { console.log('change params', params) /* Overwrite html fields if necessary */ color.value = params.color || color.value power.value = params.power || power.value setBulbParams({color: color.value, power: power.value}) }
Depois disso, os campos e o botão de execução devem fazer sentido. Você pode começar a experimentar as diferentes cores em sua nova lâmpada virtual. No entanto, a razão pela qual viemos até aqui foi para torná-lo outro dispositivo do nosso ecossistema da Internet das Coisas.
hw-api.js
O último de nosso JS front-end feito por nós mesmos. Ele zomba de uma conexão sem fio com o servidor, como uma lâmpada WiFi ou Bluetooth faria com seu controle remoto, como um telefone, servidor ou hub. É a interface que o código real do plugin usará para controlá-lo!
var socket = io.connect() socket.on('connect', function () { console.log('ws:// bulb is online') }) socket.on('disconnect', function () { console.log('ws:// connection with bulb lost') }) socket.on('set', function (params) { changeBulbParams(params) // uses functions from bulb.js! }) socket.on('get', function () { const params = { power: power.value, color: color.value } socket.emit('params', params) })
Finalmente, precisamos que a biblioteca WebSocket seja incluída em nosso HTML, para que o frontend esteja pronto. Você pode copiar a fonte de https://raw.githubusercontent.com/netbeast/bulb-plugin/master/public/socketio.js e colá-la em um arquivo chamado socketio.js . A partir de um terminal com curl
ou wget
, você pode fazer isso simplesmente:
curl https://raw.githubusercontent.com/netbeast/bulb-plugin/master/public/socketio.js > public/socketio.js
Teríamos agora uma estrutura de arquivos que se parece com isso:
myplugin ├── README.md ├── index.js ├── package.json ├── public │ ├── bulb.css │ ├── bulb.js │ ├── hw-api.js │ ├── index.html │ └── socketio.js └── test.js
O back-end
Agora vamos implementar a interface com o dispositivo e registrá-lo no mecanismo Netbeast. Ele ouvirá os websockets para detectar que uma lâmpada foi instalada na rede e, em seguida, fará um POST
para a API do painel para que os novos recursos estejam disponíveis.
Para isso, vamos dar uma olhada nos arquivos que geramos antes:
pacote.json
Este arquivo contém todas as dependências e informações necessárias para executar seu aplicativo. O Netbeast usa o package.json
regular também para recuperar algumas informações, como nome ou tipo. É importante especificar que este pacote é um plugin!
{ "name": "myplugin", "version": "0.0.0", "description": "Netbeast plugin for... <your description>", "main": "index.js", "netbeast": { "bootOnLoad": true, "type": "plugin" }, "dependencies": { "bluebird": "^3.3.5", "body-parser": "^1.15.0", "express": "^4.13.4", "minimist": "^1.2.0", "mocha": "^2.3.2", "morgan": "^1.6.1", "netbeast": "^1.0.6", "socket.io": "^1.4.5", "superagent": "^1.8.3" }, "devDependencies": {}, "scripts": { "test": "node test.js", "start": "node index.js" }, "repository": { "type": "git", "url": "GITHUB_REPOSITORY" }, "keywords": [ "iot", "netbeast", "plugin" ], "author": "YOUR_EMAIL", "license": "GPL 3", "bugs": { "url": "ISSUES_CHANNEL" }, "homepage": "HOMEPAGE" }
index.js
Este é o código que é chamado do painel Netbeast para iniciar o plugin! Ele precisará aceitar a porta por argumentos de linha de comando para saber onde aceitar solicitações recebidas. Ele será lançado como se tivéssemos digitado node myplugin.js --port <a free port number>
. Observe o hashbang no início também! #!/usr/bin/env node
.
#!/usr/bin/env node var io = require('socket.io')() var express = require('express') var bodyParser = require('body-parser') var app = express() // Netbeast apps need to accept the port to be launched by parameters var argv = require('minimist')(process.argv.slice(2)) app.use(express.static('public')) // will serve our app in an HTTP server app.use(bodyParser.json()) // will parse JSON API calls app.use('/api', require('./plugin')(io)) var server = app.listen(argv.port || 31416, function () { console.log('Bulb plugin listening at http://%s:%s', server.address().address, server.address().port) }) // we need websockets to push updates to browser view io.listen(server)
Como você pode ver, estava faltando um arquivo para iniciá-lo, aquele que realmente implementa os controladores socket.io . Nada chique!
plugin.js
var express = require('express') var netbeast = require('netbeast') var router = express.Router() var bulbParams // auxiliar variable, nasty way to transmit changes, but works module.exports = function (io) { io = io // Create resource that works on lights topic and listens on /api route netbeast('lights').create({ app: 'myplugin', hook: '/api' }) io.on('connection', function () { console.log('ws:// bulb has connected to plugin') }) io.on('disconnection', function () { console.log('ws:// bulb has disconnected from plugin') }) io.on('connect_failure', function (err) { console.trace(err) }) router.post('/', function (req, res) { io.emit('set', { power: req.body.power, color: req.body.color, }) res.status(200).json(req.body) }) router.get('/', function (req, res) { io.emit('get') var timerReference = setTimeout(function () { if (bulbParams) { res.json(bulbParams) } else { res.status(200).json({ error: 'No bulb available' }) } }, 3000) }) return router }
Inicie seu aplicativo
Agora é hora de testar seu aplicativo. Você pode fazer isso empacotá-lo em um formato tar.gz
e carregá-lo em seu painel na seção de arrastar e soltar http://localhost:8000/install.
beast package # Compresses your app when ran in myplugin dir
Voilá! Agora você pode ir para seus plugins e testá-lo. Vá para a seção de rede (http://localhost:8000/devices) para vê-lo em execução e altere sua cor a partir daí.
Se algo der errado ou você achar que pode ter perdido um detalhe, tente executá-lo localmente com o node index.js
e talvez seja mais fácil depurar do que no log de netbeast start
.
Publique seu trabalho
Se você deseja que seu aplicativo seja exibido na seção Explorar do painel Netbeast, você deve criar um repositório no GitHub com o aplicativo Netbeast ou o plug-in Netbeast, ambos incluídos na descrição e no README.md .
Para encontrar os aplicativos, usamos a API de pesquisa do GitHub. Vemos os mesmos resultados que aparecem quando você faz uma solicitação GET para: https://api.github.com/search/repositories?q=netbeast+language:javascript
Você saberá que seu aplicativo será exibido se aparecer lá!
Qual é o próximo?
Ambos os projetos são de código aberto e têm comunidades realmente envolvidas. Se você quiser começar a criar seus próprios fluxos ou nós para o Node-RED, dê uma olhada na documentação oficial deles. Siga as etapas descritas lá e você poderá publicar seu próprio nó ou fluxo rapidamente.
Por outro lado, se você quiser mergulhar dentro do Netbeast, você também pode seguir a documentação deles ou dar uma olhada no repositório do Dashboard. Usando a API Netbeast, você não precisa mais se concentrar em dispositivos, marcas ou tecnologias individuais, então experimente. Você pode saber mais sobre isso aqui ou participar do canal Slack e discutir Node-RED, IoT ou Node.js.
Se você quiser instalar essas coisas em um Raspberry Pi, Beagle Bone ou servidor antigo, você os transformaria em um Smart Hub hackeável, sem código! Existem compilações pré-fabricadas para eles em ambos os sites.
Feliz hack.