REST API on a Pi, Part 2: control your GPIO I/O ports over the internet
In Part 1 of this series, we built a simple REST API in JavaScript on our Raspberry Pi.
One of the most useful reasons for providing your Raspberry Pi with a REST API is to expose its input and output ports via the Internet for remote monitoring and control. This will allow you to control your RPi’s inputs and outputs from the browser on any smartphone or PC wherever you are in the world.
So now we will do just this, extending our REST API implementation from part 1 to read and display digital input ports.
The GPIO
A useful feature of the Raspberry Pi is the GPIO ports, made available through the header marked P1 on the PCB. These pins are a physical interface between the Pi and the outside world. Think of them as inputs you can connect to a sensor to send your RPi a digital on/off signal, such as a button press; or that the Pi can turn on or off to control a digital output – the simplest being an LED. 17 of the 26 pins of header P1 are GPIO pins; the others are power or ground pins.
A Note of GPIO Numbering
When programming the GPIO pins there are two different ways to refer to them: GPIO port numbering and physical pin numbering.
GPIO PORT NUMBERING
These are the GPIO ports as the CPU sees them.
PHYSICAL PIN NUMBERING
The other way to refer to the pins is by simply counting across and down from pin 1 at the top left of header P1 (nearest to the SD card). This is ‘physical numbering’. E.g.: GPIO port 23 is found on P1 header pin 16.

The Gertboard
You can implement this example directly on the P1 header pins of your Pi using but we will be using the Gertboard – an extended I/O interface board specially designed as a multi-purpose prototyping board for the Raspberry Pi. It features a range of additional I/Os, all driven off the RPi’s GPIO ports. For our purposes here, it has LEDs which usefully indicate the logic level of the ports set up as inputs.
The Gertboard comes with a C library for accessing all its many features, but for the purposes of our JavaScript REST API we’ll simply be driving the GPIO with the pi-gpio Node module.
The pi-gpio Node Library Module
We will be using the pi-gpio module, as described in this blog post
First, install the pi-gpio module
$ npm install pi-gpio
Modifications to our REST API source code from Part 1
We will need to make a number of changes to implement the GPIO interface.
MYAPI.JS: The Server(Pi)-side code
First, add the call to load the pi-gpio module
var wpi = require(' pi-gpio');
Recall we already defined an array for storing I/O values, which is set up for two GPIO ports. We will be using GPIO ports 23 and 25, the physical pins 16 and 22 :
var inputs = [{ pin: ‘16′, gpio: ‘23′, value: null },
{ pin: ‘22′, gpio: ‘25′, value: null }];.
We first need to initialise the GPIO and open the ports as inputs
var i; for (i in inputs) { console.log('opening GPIO port ' + inputs[i].gpio + ' on pin ' + inputs[i].pin + ' as input'); gpio.open(inputs[i].pin, "input", function (err) { if (err) { throw err; } }); }
We now need to add a timer loop to read each GPIO input and store the latest value in our inputs array. For this, we use the pi-gpio library function gpio.read.
setInterval( function () { // read GPIO input port gpio.read(inputs[0].pin, function (err, value) { if (err) { throw err; } console.log('read pin ' + inputs[0].pin + ' value = ' + value); // update the inputs object inputs[0].value = value.toString(); // store value as a string });
Now when our API receives a request for one of the inputs, it will be sent the latest value read from the port.
MYCLIENT.JS: the client-side code
We can add a timer loop to call to our API server running on the Raspberry Pi to retrieve and display the input states at one-second intervals, passing a callback function to a setInterval library function call.
setInterval( function () {
for (i in ports) {
// call the API for each input port here
}
}, 1000); // setInterval to 1 second
Download the Source Code
You can download the full source code (client, server and html) for this part 2 example from github here https://github.com/fatkahawai/rpi-webapp-gpio
If you’ve installed the wiring-pi module as described above, then you can now just download the three source files into a new folder on your RPi using the git command, and you’re ready to go.
$ git clone https://github.com/fatkahawai/rpi-webapp-gpio
Running your Raspberry Pi Web App Server
Start up your web server on your RPi by invoking your application with node, from the folder you have saved these source files in. Note because you can only access the GPIO with root privileges, you’ll need to invoke node with sudo.
$ sudo node myapi.js
App Server running at port 3000
Now open your browser and navigate to your App Server hosted on the RPi.
If you’re in luck, this should appear in your browser window:

Accessing your API from beyond your LAN
One of the most useful reasons for providing your Raspberry Pi with a RESTful API is to expose its input and output ports beyond your LAN to the wider internet for remote monitoring and control.
To access your RPi’s new web API from the internet, you could open the port on your LAN router to allow inbound requests through, but this can expose your LAN to external attack, so its safer to use a service like weaved.com. You’ll need to sign up for an account, and install the weaved package on your RPi. Follow the instructions on their RPi page here
What’s Next ?
Now you’ve got digital inputs implemented, you can use the same technique to expose the other features of the Gertboard – digital outputs and analog I/O.
I hope this exercise has been useful. If you have any feedback or spot any errors or omissions, feel free to leave a note in the comments section below.
Great articles. Follow your blog.
Have an errors in launchig myapi.js
root@PiHome:/usr/local/auto/rpi-webapp-gpio# node myapi.js
opening GPIO port 23 on pin 16 as input
opening GPIO port 25 on pin 22 as input
App Server is listening on port 3000
Error when trying to open pin 22
gpio-admin: could not flush data to /sys/class/gpio/export: Device or resource busy
/usr/local/auto/rpi-webapp-gpio/myapi.js:39
throw err;
^
Error: Command failed: /bin/sh -c gpio-admin export 25
gpio-admin: could not flush data to /sys/class/gpio/export: Device or resource busy
at ChildProcess.exithandler (child_process.js:744:12)
at ChildProcess.emit (events.js:110:17)
at maybeClose (child_process.js:1008:16)
at Socket. (child_process.js:1176:11)
at Socket.emit (events.js:107:17)
at Pipe.close (net.js:476:12)
looks like the GPIO is still open from a previous session. just reboot your Pi, that will clear it.
If you terminate the server application by hitting Ctl-C, that interrupt will be processed in myapi.js by the “process.on(SIGINT….” code, closing the GPIO ports and exiting gracefully, preventing you getting this “resource busy” error when next starting it.
I’m getting the same problem – How do I fix it ?
I cannot run it the next time as the export file is in that state is already present in that folder – so running ‘sudo node myapi.js’ the next time around is not helping. Is there a way to flush it, or resolve it ?
Thanks
Same error, would be great if you could help us beginners fix it
Looks like became a little bit better, but still no success. I start JS from root and from user with sudo, but the same result, no such file or directory.
Here console.log
sudo node /usr/local/auto/rpi-webapp-gpio/myapi.js
opening GPIO port 23 on pin 16 as input
opening GPIO port 25 on pin 22 as input
App Server is listening on port 3000
Error when trying to open pin 22
gpio-admin: failed to change group ownership of /sys/devices/virtual/gpio/gpio25/direction: No such file or directory
/usr/local/auto/rpi-webapp-gpio/myapi.js:39
throw err;
^
Error: Command failed: /bin/sh -c gpio-admin export 25
gpio-admin: failed to change group ownership of /sys/devices/virtual/gpio/gpio25/direction: No such file or directory
at ChildProcess.exithandler (child_process.js:744:12)
at ChildProcess.emit (events.js:110:17)
at maybeClose (child_process.js:1008:16)
at Socket. (child_process.js:1176:11)
at Socket.emit (events.js:107:17)
at Pipe.close (net.js:476:12)
That’s why it closes abnormally and don’t turn off GPIO
Actually i don’t have this folder /sys/devices/virtual/gpio
I’m using my Pi like a doorbell with python script and switch GPIO from Serial to Software Access Mode
Taken from this guide – http://www.expertreviews.co.uk/accessories/gadgets/1401477/raspberry-pi-projects-make-your-doorbell-smart
Next you need to convert the Pi’s GPIO (General-Purpose Input/Output) connection (the double line of bare pins near the SD card slot) from Serial mode to Software Access mode. To do this you need to edit a boot file. Type ‘sudo nano /boot/cmdline.txt’ and hit Enter. You’ll need to edit the current line:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
Maybe it’s the root of problem?
did you ever get passed this problem ^^ I’m running into the same exact thing starting from
Error when trying to open pin 22
gpio-admin: failed to change group ownership of /sys/devices/virtual/gpio/gpio25/direction: No such file or directory
…
all the way down to
…
at Pipe.close (net.js:476:12)
even my line numbers are identical, how did you solve this?
This worked for me:
https://github.com/rexington/quick2wire-gpio-admin/commit/e1974dd197573a0a846a9fbe35d9f3ff1cbb3884
Thanks for the tip, I had the same problem !
I think you should update the blog, I was having a hard time wrapping my head around this one. I was trying to figure out where you put the port variable was, until I went to the source and it all made sense.
I think you should update the blog, I was getting confused with the port variable, until I looked at the source.
Hello, thank you very much for the tutorial. I’ve learned a lot while making it work on my Raspberry Pi.
Imho the gpio inputs should be read in a loop, in the same manner as they are initialized:
for (i in inputs) {
gpio.read(inputs[i].pin, function (pin, err, value) {
…
There is a catch, though: as the function will be called asynchronously, the value of i (and subsequently inputs[i].pin) may be already changed at the time of function call.
The callback will need an additional ‘pin’ parameter to be able to correctly report the pin along with its value, something like:
for (i in inputs) {
gpio.read(inputs[i].pin, function (pin, err, value) {
if (err) {
throw err;
}
console.log(‘read pin ‘ + pin + ‘ value = ‘ + value);
inputs[i].value = value;
}.bind(undefined, inputs[i].pin));
}
which works for me.
Followed your blog, removed all the errors after reading all the comments. But still the problem persist with the new error:
opening GPIO port 23 on pin 16 as input
opening GPIO port 25 on pin 22 as input
App Server is listening on port 3000
/home/pi/myapp/myapi.js:49
throw err;
^
Error: ENOENT, open ‘/sys/class/gpio/gpio23/value’
Help me resolve this problem…
I am having the exact same error as you and am debugging right now. In the meanwhile, does anyone have an answer? I will let you know if I figure it out.
anything on this topic? I have the same issue. I got it working to some level but still have myopia.js:49 issue. Please Help!
anybody solve this problem
Do the following on your raspberry pi:
git clone git://github.com/quick2wire/quick2wire-gpio-admin.git
cd quick2wire-gpio-admin
make
sudo make install
sudo adduser $USER gpio
After this, you will need to logout and log back in.
Yes you should do this but with following changes.
https://github.com/rexington/quick2wire-gpio-admin/commit/e1974dd197573a0a846a9fbe35d9f3ff1cbb3884
myapi.js:49 issue*.
Hi,
thanks for this great tutorial! I am loving this.
Any chance you could give a hint how to emebed gpio.write in the API ?
Cheers
Nice tutorial, thank you very much for that tutorial….
But now I have ultrasonic sensor connected to raspberry pi 3 and that sensor data, i have to show to the application (Android or web page)
And which sensor data code is wrote in javascript
So how i use their ports and send continusley my mesure distance to web page or apllication
plzzz plzzz guide me this concept as soon possible
Thank you.
We must do this exercise below first before proceed to this one to reduce time troubleshooting
http://www.robert-drummond.com/2013/06/06/raspberry-pi-gpio-inputoutput-in-javascript/
Clone this project:
https://github.com/quick2wire/quick2wire-gpio-admin
Then make the following changes as mentioned here:
https://github.com/rexington/quick2wire-gpio-admin/commit/e1974dd197573a0a846a9fbe35d9f3ff1cbb3884
Then follow the make command as mentioned here for the project:
http://www.robert-drummond.com/2013/06/06/raspberry-pi-gpio-inputoutput-in-javascript/
The above solutions worked for me.
Thank you!!!
Regards,
shaun-dev
Hi, Thanks for this cool tutorial!
I created a REST API on my Raspberry Pi and made it accessible over remote.it (developer.weaved package). Accessing directly from remote.it works well.
Now I would like to access this API over a VueJS web app. However I struggle making the requests over remote.it. Somehow it does not transfer me to the right URL. (Also I think the URL keeps changing – how do I deal with that?)
Do you have experience with this service? I could really need some help. 🙂
Thanks