Avete la necessità di accendere un led o in generale leggere/impostare un qualsiasi pin del GPIO del Raspberry Pi via web? La soluzione più semplice e comoda è probabilmente utilizzare un server REST in Javascript con Node.js.
Esistono sicuramente anche altre valide alternative, io ho scelto questa perché negli ultimi mesi mi sono trovato diverse volte a lavorare con Node.Js e l’ho apprezzato veramente tanto per la sua semplicità e al contempo grossa potenza modulare, con un’infinità di pacchetti ed estensioni NPM.
Lo scopo di questa guida è quindi quello di accendere un led attaccato al gpio (con una resistenza e un mosfet, che non sono oggetto di questo post ma di cui potete trovare già tantissima documentazione) attraverso una semplice chiamata web http://indirizzo.ip/led/on.

Due led incastonati nel case del Raspberry, comandati da NodeJs
Parto dal presupposto che il Raspberry sia già stato configurato con la Raspbian installata ed attiva e che quindi abbiate già una conoscenza base generale del sistema.
Installare i pacchetti necessari con
[bash]curl -sLS https://apt.adafruit.com/add | sudo bashsudo apt-get install node[/bash]
Verificate che node sia installato correttamente:
[bash]pi@raspberrypi node -vv0.12.0[/bash]
creiamo un nuovo progetto ed installiamo le librerie necessarie
[bash]mkdir /home/pi/raspiledjscd /home/pi/raspiledjs
npm init[/bash]
E rispondere alle domande per creare il package del progetto
Adesso possiamo installare le dipendenze necessarie: Express (per creare il server REST), rpi-gpio (per gestire i GPIO del Rpi)
[bash]npm install express rpi-gpio –save[/bash]Io ho inoltre voluto creare una pagina html semplice con dei bottoni per accendere e spegnere il led. Anche questa pagina sarà servita da node che funzionerà da web server.
Per creare l’interfaccia velocemente ho utilizzato boostrap e jquery, anch’esse installate con NPM:
[bash]npm install bootstrap jquery cors –save[/bash]Adesso che abbiamo installato il necessario, passiamo al codice dell’applicazione. Io ho creato un “index.js” con questo contenuto:
[javascript title=”index.js”] var http = require(‘http’);var express = require(‘express’);
var gpio = require(‘rpi-gpio’);
var exec = require(‘child_process’).exec;
var cors = require(‘cors’);
var app = express();
app.use(express.static(__dirname + ‘/public’));
app.use(‘/node_modules/bootstrap’, express.static(__dirname + ‘/node_modules/bootstrap’));
app.use(‘/node_modules/jquery’, express.static(__dirname + ‘/node_modules/jquery’));
app.use(cors());
var LEDPIN = 8;
var SERVERPORT = 80;
app.get(‘/led/:on’, function (req, res) {
console.log(‘led request = ‘ + req.params.on);
if (req.params.on == ‘on’) {
setLed(LEDPIN,1, function(err){
if (err) {
res.status(500).send(‘Oops, Something went wrong! ‘ + err);
} else {
res.status(200).send("LED 1 ON");
}
});
} else if (req.params.on == ‘off’) {
setLed(LEDPIN,0, function(err){
if (err) {
res.status(500).send(‘Oops, Something went wrong! ‘ + err);
} else {
res.status(200).send("LED 1 OFF");
}
});
}
else if (req.params.on == ‘read’) {
readStatus(LEDPIN, function(err, value){
if (err) {
res.status(500).send(‘Oops, Something went wrong! ‘ + err);
} else {
res.status(200).send(value);
}
});
} else {
res.status(404).send("Bad Request. Use /led1/on or /led1/off or /led1/read");
}
});
app.post(‘/shutdown’, function (req, res) {
res.status(200).send("Raspberry is shutting down…");
unexportPins();
execute("halt");
});
app.post(‘/restart’, function (req, res) {
res.status(200).send("Raspberry is restarting…");
unexportPins();
execute("restart");
});
// Express route for any other unrecognised incoming requests
app.get(‘*’, function (req, res) {
res.status(404).send(‘Unrecognised API call.’);
});
// Express route to handle errors
app.use(function (err, req, res, next) {
if (req.xhr) {
res.status(500).send(‘Oops, Something went wrong!’);
} else {
next(err);
}
});
function setLed(PIN, value, callback) {
console.log("Setting pin "+PIN+" to " + value);
gpio.write(PIN, value, function(err) {
if (err) {
console.log("error writing " + err);
callback("error writing " + err);
return;
}
callback();
});
}
function readStatus(PIN, callback) {
console.log("reading pin "+PIN);
gpio.read(PIN, function(err,value) {
if (err) {
console.log("error reading pin " + err, null);
callback("error reading pin " + err, null);
return;
}
callback(null,value);
});
}
//catches ctrl+c event
process.on(‘SIGINT’, function(){
unexportPins();
});
function unexportPins() {
gpio.destroy(function() {
console.log(‘All pins unexported’);
process.exit();
});
}
function execute(command) {
exec(command, function (error, stdout, stderr) {
console.log(‘exec: ‘ + stdout);
console.log(‘stderr: ‘ + stderr);
if (error !== null) {
console.log(‘exec error: ‘ + error);
}
});
}
//init pin and app
gpio.setup(LEDPIN, gpio.DIR_OUT, function(err){
if (err) {
console.log("Error opening pin " + err);
return;
}
app.listen(SERVERPORT);
console.log(‘GPIO setup completed and server listening on port ‘ + SERVERPORT);
});
[/javascript]
L’unica configurazione da fare sono le variabili LEDPIN e SERVERPORT che trovate alle righe 12 e 13 dello script:
- LEDPIN è il numero del GPIO che volete pilotare (segue la numerazione standard del Raspberry Pi, con il pin 1 in alto a sinistra, il secondo in alto a destra e così via. Riferimento completo qui.)
- SERVERPORT è la porta sulla quale starà in ascolto il server. La porta 80 permette di accedere agli indirizzi semplicemente con http://ipraspberry/led/on
Una volta salvato il file, possiamo testarlo con un’unica accortezza: eseguirlo con i permessi di root, altrimenti il raspberry non riuscirà a gestire i GPIO
[bash]sudo node index.js[/bash]se tutto è andato bene dovreste leggere una frase del tipo
[bash]GPIO setup completed and server listening on port 80[/bash]a questo punto potete provare ad attivare il vostro GPIO semplicemente da un qualsiasi browser in rete con il raspberry (anche da smartphone), aprendo l’indirizzo
http://192.168.1.10/led/on
dove 192.168.1.10 è l’ip del Raspberry in questo caso. (vi consiglio di impostarlo statico…)
Nella consolle di Node dovreste leggere contemporaneamente
[bash] led request = on Setting pin 8 to[/bash]Gli endpoint che questo script rende disponibili sono i seguenti:
- [GET] http://192.168.1.10/led/on – Attiva il pin
- [GET] http://192.168.1.10/led/off – Disattiva il pin
- [GET] http://192.168.1.10/led/read – Legge lo stato del pin
- [POST] http://192.168.1.10/shutdown – Spegne il Raspberry
- [POST] http://192.168.1.10/reboot – Riavvia il Raspberry
Ovviamente al pin comandato potrete collegare qualsiasi cosa, non solo un led !
Se infine volete eseguire uno script node in automatico all’avvio, vi consiglio l’ottimo Forever.
Interfaccia web
Lascio qua anche la paginetta web che ho creato per testare i servizi. Sia il file index.html che functions.js vanno salvati nella cartella “public” dell’applicazione node appena creata (ovvero /home/pi/raspiledjs/public ) e saranno raggiungibili semplicemente all’indirizzo http://ipdelraspberry/
nota: all’inizio del file functions.js inserire l’ip del raspberry nella variabile url.
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RASPiLedJs</title>
<!– Bootstrap –>
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<script type="text/javascript" src="./functions.js"></script>
</head>
<body>
<h1>RASPiLedJs</h1>
<label>Last response: </label>
<input type="text" id="response">
<h2>LED</h2>
<div class="btn-group" role="group" aria-label="…">
<button type="button" class="btn btn-default" onclick="setLed(‘on’)">LED ON</button>
<button type="button" class="btn btn-default" onclick="setLed(‘off’)">LED OFF</button>
</div>
<h2>SYSTEM</h2>
<div class="btn-group" role="group" aria-label="…">
<button type="button" class="btn btn-default" onclick="restart()">RESTART</button>
<button type="button" class="btn btn-default" onclick="shutdown()">SHUTDOWN</button>
</div>
<!– jQuery (necessary for Bootstrap’s JavaScript plugins) –>
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<!– Include all compiled plugins (below), or include individual files as needed –>
<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
</body>
</html>
[/html]
[javascript title=”functions.js”]
var url = "http://192.168.1.125/";
function setLed (status) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", url+"led/"+status , true );
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4) {
var serverResponse = xmlHttp.responseText;
output(serverResponse);
}
};
xmlHttp.send( null );
}
function shutdown () {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "POST", url+"shutdown" , true );
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4) {
var serverResponse = xmlHttp.responseText;
output(serverResponse);
}
};
xmlHttp.send( null );
}
function restart () {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "POST", url+"restart" , true );
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4) {
var serverResponse = xmlHttp.responseText;
output(serverResponse);
}
};
xmlHttp.send( null );
}
function output(text) {
var elem = document.getElementById("response");
if (elem!= null)
elem.value = text;
}
[/javascript]





