Programmazione visiva con Node-RED: cablare l'Internet delle cose con facilità

Pubblicato: 2022-03-11

Attraverso la programmazione, facciamo in modo che le macchine imitino comportamenti complessi seguendo sequenze di semplici istruzioni. L'uso di linguaggi di programmazione testuale come Assembly, C, Python e JavaScript è uno dei modi principali per farlo. I progettisti di questi linguaggi di programmazione hanno trascorso innumerevoli ore cercando di rendere l'esperienza di scrittura di programmi il più semplice possibile attraverso una sintassi espressiva, robusti costrutti di programmazione e potenti toolchain. Tuttavia, tutti questi linguaggi di programmazione condividono un tratto comune: il codice sorgente testuale.

Scrivere programmi nel testo funziona e nella maggior parte dei casi funziona bene. Tuttavia, la capacità di esprimere i programmi visivamente è spesso desiderabile. Essere in grado di progettare il flusso di informazioni attraverso i vari componenti di un sistema più ampio è spesso tutto ciò che serve. Gli strumenti di programmazione visiva sono anche indulgenti nei confronti di chiunque sia nuovo alla programmazione e abbia difficoltà a gestire vari concetti come variabili, puntatori, segnali, ambiti e così via.

Connetti i dispositivi hardware con le API utilizzando Node-RED

Node-RED è uno strumento per la programmazione visiva. Visualizza relazioni e funzioni visivamente e consente all'utente di programmare senza dover digitare una lingua. Node-RED è un editor di flusso basato su browser in cui puoi aggiungere o rimuovere nodi e collegarli insieme per farli comunicare tra loro.

In Node-RED, ogni nodo è uno dei due tipi seguenti: un nodo di iniezione o un nodo di funzione . I nodi Inject producono un messaggio senza richiedere alcun input e inviano il messaggio al nodo successivo ad esso collegato. I nodi funzione, d'altra parte, prendono un input ed eseguono un po' di lavoro su di esso. Con una pletora di questi nodi tra cui scegliere, Node-RED rende il cablaggio insieme di dispositivi hardware, API e servizi online più semplice che mai.

Iniziare con Node-RED

Node-RED è basato su Node.js. Per installare Node-RED, dovrai avere installato sia Node.js che NPM. Con NPM, è semplicissimo installare Node-RED:

 npm install -g node-red

L'editor di flusso di Node-RED è un'applicazione basata su browser web. Per poterlo utilizzare, esegui Node-RED:

 node-red

&hellip e vai a http://localhost:1880.

Ciao mondo!

Quale tutorial di programmazione per principianti è completo senza imparare a dire "Hello, world"? Iniziamo provando esattamente questo:

  1. Trascina e rilascia un nodo di iniezione nell'editor di flusso. Quindi fare doppio clic e impostare il payload come stringa e scrivere "Hello world".
  2. Trascina e rilascia un nodo di debug , nello stesso modo in cui hai fatto con quello di iniezione.
  3. Collegali insieme.
  4. Fare clic sul pulsante "Distribuisci" nell'angolo destro.
  5. Fare clic sul pulsante blu appena a sinistra del nodo di iniezione .

Provalo. Vedrai qualcosa del genere:

Solo JavaScript

Con Node-RED, non sei limitato a semplici nodi e funzionalità. Poiché Node-RED è basato su Node.js, è tutto basato su JavaScript. I nodi sono, infatti, moduli Node.js. Possono essere trovati in http://flows.nodered.org/, quindi per aggiungerli al pannello di sinistra puoi semplicemente "installarli npm". In effetti, puoi sviluppare il tuo flusso e caricarlo nel repository del flusso. Le applicazioni possono essere complesse quanto vuoi, perché puoi digitare JavaScript nei nodi funzione all'interno dell'editor di codice fornito da Node-RED.

Poiché la piattaforma è basata su Node.js, sfrutta lo stesso modello guidato da eventi e non bloccante. Quindi un'applicazione basata su Node-RED può essere eseguita su hardware a basso costo come Raspberry Pi, oltre che nel cloud.

Ora Let's Go Pro: tempo per la domotica

Per dimostrare come Node-RED si inserisce nel regno dell'Internet delle cose, creiamo un'applicazione per cambiare il colore di una lampadina intelligente. Non tutti potrebbero avere a disposizione lo stesso sistema di illuminazione intelligente, ma non c'è nulla di cui preoccuparsi, poiché puoi trovare il modulo Node-RED appropriato dal repository ufficiale del flusso. Tuttavia, per rendere le cose ancora più semplici, scegliamo qualcosa di più intelligente.

Incontra Netbeast. È una piattaforma open source per lo sviluppo di applicazioni per dispositivi e dispositivi Internet of Things senza doversi preoccupare di dettagli come protocolli wireless, compatibilità del marchio o dover sapere come gestire ogni specifica API disponibile. Ci consente di utilizzare dispositivi virtuali che si comportano come quelli reali! Quindi, anche se non hai una lampadina intelligente, ne hai una virtuale disponibile.

Possiamo installare il pacchetto npm Netbeast for Node-RED a livello globale in questo modo:

 npm install -g node-red-contrib-netbeast

Il nodo netbeast-red rappresenterà il Netbeast Dashboard, che tradurrà le sue primitive API in tutti i tuoi dispositivi intelligenti che hai a casa. Fortunatamente è disponibile anche come modulo!

Avvia Netbeast:

 npm install -g netbeast-cli netbeast start

Ciò renderà la dashboard disponibile sulla porta 8000 e SSL su 8443. Quindi apri il browser su http://localhost:8000 e vai a Esplora. Lì saremo in grado di trovare molte app e plugin. Cerca le marche delle tue lampadine intelligenti (Philips Hue, LIFX, WeMo) o se non ne hai una prova a scaricare il plug-in della lampadina. Verifica che i plug-in della dashboard contengano uno di questi!

Il badge giallo indica che i plug-in sono in esecuzione, ma non riescono a trovare alcun dispositivo. Fare clic sul plug-in della lampadina per creare una lampadina virtuale. Tutti gli altri dispositivi rilevati dovrebbero apparire in Rete.

Con tutto a posto, torniamo al lavoro. Faremo un semplice flusso:

  1. Trascina e rilascia un nodo di iniezione.
  2. Trascina e rilascia il nodo Netbeast.
  3. Trascina e rilascia un nodo di debug.
  4. Collega il tutto come mostrato di seguito:

Ora inviamo una richiesta HTTP al Dashboard. Utilizzando l'API Netbeast dovremo inviare tramite il nodo inject un JSON contenente i valori che vogliamo attivare sulla nostra lampadina.

Premi il pulsante per iniettare il colore e l'alimentazione a tutte le tue lampadine intelligenti!

Ogni argomento rappresenta un diverso tipo di dispositivo. Quindi ci sono argomenti per le luci ma anche per la musica, il riscaldamento e il video; oltre ai sensori di umidità, presenza, temperatura e l'elenco continua. Puoi trovare nella loro documentazione un elenco di argomenti e la loro struttura consigliata da tradurre su tutti i tipi di dispositivi. Questo motore IoT è immaturo, ma potente. Open source che permette agli sviluppatori di riutilizzare le informazioni per creare scenari realmente connessi, essendo così intelligenti.

Andiamo più a fondo

Successivamente, creeremo un secondo flusso utilizzando un altro plug-in, un rilevatore di rumore ambientale, per usarlo come trigger per cambiare il colore della lampadina come semaforo di rumore. In questo tutorial ne utilizzeremo uno virtuale, quindi non è necessario acquistare nuovo hardware. Iniziamo facendo clic sul pulsante "più" nell'editor Node-RED.

Vai di nuovo sulla Dashboard http://localhost:8000/explore alla sezione Esplora e cerca Volume-Plugin. È un'app Web molto rudimentale che sfrutta getUserMedia() all'interno del browser per acquisire file multimediali da una semplice app HTML. Quindi probabilmente funzionerà solo sui browser moderni!

Fare clic su di esso per aprire, come con la lampadina virtuale. Ti chiederà il permesso di registrare dal tuo microfono. Quindi invierà i messaggi al broker MQTT di Netbeast, che sarà condiviso su tutta la Dashboard, e così potremo iscriverci. Per fare una cosa del genere dovremo solo trascinare e rilasciare un nodo netbeast-trigger nell'editor di node-red. Quindi inseriremo una funzione tra il trigger e il nodo Netbeast in modo da decidere quando è troppo rumoroso o meno. Inoltre, dovremmo usare alcuni nodi di debug per verificare se tutto è a posto. Lo schema ora sarà simile al seguente:

Ora, inseriamo del codice nel nodo della funzione tooLoud. Sì, lo so che ti avevo promesso che potevi programmare senza dover programmare, ma ho già dimostrato che puoi! E puoi provare a combinare i diversi elementi disponibili o altri nodi dal registro per ottenere quanto segue.

 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'}} }

Questo frammento di codice piuttosto semplice restituisce uno dei tre payload per il nodo successivo con un codice colore specifico, a seconda del livello di volume riportato dal nodo precedente.

Ora siamo pronti per partire! Premiamo di nuovo il pulsante Distribuisci e facciamo un po' di rumore. Vediamo come la lampadina cambia immediatamente da un colore all'altro!

Poiché il microfono e il browser Web che stai utilizzando potrebbero essere diversi, sentiti libero di regolare i valori e le soglie delle funzioni e gioca anche con i valori del colore per vedere come cambia le lampadine.

Creare i tuoi plugin

Questa lampadina in puro CSS è stata ispirata da questo cssdeck.

Come avrai notato, la lampadina virtuale di prima è molto rudimentale, quindi potresti volerla modificare. O ancora meglio, puoi creare i tuoi controller per la casa intelligente. Quindi esamineremo il processo di creazione di un plug-in virtuale per Netbeast, che ti consentirà di creare i tuoi controller per dispositivi intelligenti.

Puoi usare il pacchetto netbeast-cli per generare automaticamente del codice. Eseguendo netbeast create myplugin --plugin ci ritroveremo con un progetto di base come il seguente:

 myplugin ├── README.md ├── index.js ├── package.json └── test.js

Il Fronte

Ora, iniziamo a mimetizzare la lampadina con un frontend. I controller di dispositivo in genere non ne hanno uno, quindi nel comando scaffold non è ancora inclusa alcuna cartella pubblica . Creiamo una directory public all'interno del progetto e vi posizioniamo i seguenti file HTML, CSS e JS.

indice.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>

lampadina.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; }

Con questi file HTML e CSS, dovresti già essere in grado di vedere una forma a bulbo nel tuo browser. Vai avanti e apri il tuo file HTML per vederlo dal vivo! Funziona? Ottimo, ora diamogli un po' di funzionalità.

bulb.js

Questo file imiterà il comportamento di una lampadina con un semplice clic su, clic su off e imposterà un paio di funzioni che verranno utilizzate tra poco per cambiarne il colore tramite 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}) }

Dopodiché, i campi e il pulsante Esegui dovrebbero avere tutti un senso. Puoi iniziare a provare i diversi colori sulla tua nuovissima lampadina virtuale. Tuttavia, il motivo per cui abbiamo fatto tutta questa strada è stato per renderlo un altro dispositivo del nostro ecosistema Internet of Things.

hw-api.js

L'ultimo dei nostri JS front-end self-made. Deride una connessione wireless con il server, come farebbe una lampadina WiFi o Bluetooth con il suo telecomando, come un telefono, un server o un hub. È l'interfaccia che il codice del plugin effettivo utilizzerà per controllarlo!

 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) })

Infine, abbiamo bisogno che la libreria WebSocket sia inclusa dal nostro HTML, quindi il frontend è pronto. Puoi copiare il sorgente da https://raw.githubusercontent.com/netbeast/bulb-plugin/master/public/socketio.js e incollarlo in un file chiamato socketio.js . Da un terminale con curl o wget , puoi farlo semplicemente:

 curl https://raw.githubusercontent.com/netbeast/bulb-plugin/master/public/socketio.js > public/socketio.js

Avremmo ormai una struttura di file simile a questa:

 myplugin ├── README.md ├── index.js ├── package.json ├── public │ ├── bulb.css │ ├── bulb.js │ ├── hw-api.js │ ├── index.html │ └── socketio.js └── test.js

Il backend

Ora implementeremo l'interfaccia con il dispositivo e la registreremo nel motore Netbeast. Ascolterà i WebSocket per rilevare che una lampadina è stata installata sulla rete, quindi eseguirà un POST all'API Dashboard in modo che le nuove risorse siano disponibili.

Per questo, diamo un'occhiata ai file che abbiamo generato prima:

pacchetto.json

Questo file contiene tutte le dipendenze e le informazioni necessarie per eseguire l'app. Netbeast usa il normale package.json anche per recuperare alcune informazioni, come il nome o il tipo. È importante specificare che questo pacchetto è un 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

Questo è il codice che viene chiamato dalla dashboard di Netbeast per avviare il plugin! Dovrà accettare la porta tramite argomenti della riga di comando per sapere dove accettare le richieste in arrivo. Verrà avviato come se avessimo digitato node myplugin.js --port <a free port number> . Si prega di notare anche l' hashbang all'inizio! #!/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)

Come puoi vedere ci mancava un file per avviarlo, quello che implementa effettivamente i controller socket.io . Nulla di bello!

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 }

Avvia la tua app

Ora è il momento di testare la tua app. Puoi farlo impacchettandolo in un formato tar.gz e caricandolo sulla dashboard nella sezione drag-and-drop http://localhost:8000/install.

 beast package # Compresses your app when ran in myplugin dir

Ecco! Ora puoi andare ai tuoi plugin e provarlo. Vai alla sezione di rete (http://localhost:8000/devices) per vederlo in esecuzione e cambiarne il colore da lì.

Se qualcosa va storto o pensi di aver perso un dettaglio, prova a eseguirlo localmente con node index.js , e forse sarà più facile eseguire il debug che all'interno del registro di netbeast start .

Pubblica il tuo lavoro

Se vuoi che la tua app venga visualizzata nella sezione Esplora del dashboard di Netbeast, devi creare un repository in GitHub con l'app Netbeast o il plug-in Netbeast, entrambi inclusi nella descrizione e README.md .

Per trovare le app utilizziamo l'API di ricerca di GitHub. Vediamo gli stessi risultati che appaiono quando si effettua una richiesta GET a: https://api.github.com/search/repositories?q=netbeast+language:javascript

Saprai che la tua app verrà mostrata se appare lì!

Qual è il prossimo?

Entrambi i progetti sono open source e hanno davvero coinvolto le comunità. Se vuoi iniziare a creare i tuoi flussi o nodi su Node-RED, dai un'occhiata alla loro documentazione ufficiale. Segui i passaggi come descritto lì e dovresti essere in grado di pubblicare il tuo nodo o flusso in pochissimo tempo.

D'altra parte, se vuoi tuffarti all'interno di Netbeast, puoi seguire anche la loro documentazione o dare un'occhiata al repository Dashboard. Utilizzando l'API Netbeast non devi più concentrarti su singoli dispositivi, marchi o tecnologie, quindi provalo. Puoi saperne di più qui o unirti al loro canale Slack e discutere di Node-RED, IoT o Node.js.

Se vuoi installare questa roba su un Raspberry Pi, Beagle Bone o un vecchio server, li trasformerai in uno Smart Hub hackerabile, senza codice! Ci sono build premade per loro in entrambi i siti.

Buon hackeraggio.

Correlati: Stiamo creando un Internet of Things (IoT) insicuro?