Node Js – Interfacciarsi ai pin GPIO del Raspberry Pi
Mostriamo come utilizzare i pin GPIO del Raspberry Pi, con Node JS, creando un web server e gestendo gli entrypoint.
Prepariamo il Raspberry Pi
Dopo aver seguito la guida su come installare Node.js sul Rpi, installiamo la libreria che ci permette di interfacciarci ai pin GPIO del Raspberry.
Ne esistono svariate nella repository ufficiale di Node.js, quella che attualmente andremo ad usare si chiama ‘onoff’: https://www.npmjs.com/package/onoff, questa libreria è un pacchetto npm, per utilizzarla semplicemente definiamo ‘onoff’ nelle dipendenze su package.json oppue lanciamo il comando:
npm install onoff --save
Il modo più comodo e corretto per iniziare è forse quello di usare direttamente il node package manager (npm), quindi semplicemente andiamo a creare il package.json nella cartella di lavoro corrente, non manualmente, ma inizializzando il nuovo progetto con il comando: npm init
.
Lanciato il comando ci chiederà il nome che vogliamo dare al progetto ed altre informazioni. Inseriamone un paio e completiamo la procedura.
Adesso possiamo si dare il comando npm install onoff --save
che scaricherà il modulo specificato e lo aggiungerà come dipendenza nel file package.json creato con il comando npm init.
Ogniqualvolta andremo ad eseguire con node uno script che interagisce con i GPIO non dimentichiamo di far precedere la voce sudo per eseguire l’app con i permessi di root (Ex. sudo node app.js
).
Un altra dipendenza necessaria è express, installiamo la libreria come visto per la precedente: npm install express --save
.
Scriviamo lo script per Node.js
A seconda di come vogliamo strutturare l’app possiamo optare per differenti scelte organizzative.
L’app che segue è pensata per pilotare un singolo pin del RPi, restando in ascolto su una porta prefissata, il tutto è definito nel file config.json:
{"porta": 5000, "pin": 17} |
Ricordo che il numero del pin segue quella che è la notazione GPIO mostrata in questa foto:
Dunque per pilotare il pin 11, dovremo riferirci ad esso con il numero 17.
Questo file di configurazione viene letto da altre due pagine per implementare la logica dell’applicazione.
Gli altri due file che compongono l’applicativo sono:
app.js:
var express = require('express'); // Usiamo libreria express per facilitarci il routing // npm install express --save var app = express(); var relay = require('./gpio-onoff.js'); var config = require('./config.json'); // file di configurazione var porta = config.porta; app.get('/toggle', function (req, res) { // processiamo richiesta get verso /toggle // risposta in JSON res.json(relay.toggle()); }); app.get('/on', function (req, res) { // processiamo richiesta get verso /toggle // risposta in JSON res.json(relay.on()); }); app.get('/off', function (req, res) { // processiamo richiesta get verso /toggle // risposta in JSON res.json(relay.off()); }); app.get('/get', function (req, res) { // processiamo richiesta get verso /toggle // risposta in JSON res.json(relay.get()); }); // Express route for any other unrecognised incoming requests app.get('*', function(req, res) { res.status(404).send('Unrecognised API call'); }); var server = app.listen(porta, function () { // server in ascolto sulla porta var host = server.address().address; var port = server.address().port; console.log('App in ascolto su http://%s:%s', host, port); }); |
gpio-onoff.js:
var Gpio = require("onoff").Gpio; // npm install onoff --save var config = require('./config.json'); // file di configurazione var pin = config.pin; // pin fisico 11, ma header 17, occhio alla differenza. // FUNZIONI PER INTERAGIRE CON IL RELAY COLLEGATO AD UN GPIO pin led = new Gpio(pin, 'out'); exports.get = function(pin){ // perchè questo file gpio-onoff.js è incluso esternamente var value = led.readSync(); var stato = (value == 1) ? "on": "off"; console.log("Get status: "+stato); return {response_code: 200, new_state: stato, path: "/get"}; }; exports.on = function(pin){ led.writeSync(1); console.log("Pin ON"); return {response_code: 200, new_state: "on", path: "/on"}; }; exports.off = function(pin){ led.writeSync(0); console.log("Pin OFF"); return {response_code: 200, new_state: "off", path: "/off"}; }; exports.toggle = function(pin){ var stato = 0; /* led.read(function (err, value) { // Asynchronous read. if (err) throw err; led.write(value ^ 1, function (err) { // Asynchronous write. if (err) throw err; stato = value ^ 1; console.log('Pin new value: '+stato); }); }); */ stato = led.readSync() ^ 1; led.writeSync(stato); console.log("Toggle: "+stato); if (stato == 1) return {response_code: 200, new_state: "on", path: "/toggle"}; else return {response_code: 200, new_state: "off", path: "/toggle"}; }; |
Potete scaricare i sorgenti direttamente dalla repository ufficiale su github, la cartella è node_rele_server.
Nella root della repository c’è anche l’equivalente di quanto mostrato, però scritto in Python.
Lanciare l’app all’avvio del sistema
Qualora vorreste far in modo che il server venga eseguito all’avvio del Raspberry dovete inserire una voce nel file /etc/rc.local che avvii il server con permessi di root:
sudo node /home/pi/Desktop/node_rele_server/app.js &
(non dimenticate il percorso assoluto! – la & commerciale serve a eseguire il comando in un nuovo processo, così che un eventuale loop infinito all’interno del nostro programma non blocchi la fase di boot, l’esecuzione di comandi all’avvio del RPi è ben documentato sul sito ufficiale).
Commenti