IoT Series: Connecting Raspberry Pi to Parse Server with NodeJS

prancheta-1-1

In our previous tutorial on IoT, we explained how to setup your Raspberry Pi and to write values to the GPIO pins. In this part, we will take a step towards a real IoT application, by opening a connection between Raspberry Pi and Parse Server and letting events on each side trigger actions on the other.

Here you will learn how to connect your Raspberry Pi to Parse Server using Back4App and to perform actions such as Queries, Live Queries and writing objects, and how the events on Parse Server may trigger real-world events!

We also provide our codes as a first step for you to develop your desired IoT Apps.

Prerequisites

Of course, you need some electronic components. Three LEDs, three resistors (1k works fine), a breadboard and jumpers are sufficient.

You have to set up a Raspberry Pi environment. We strongly recommend you to follow our tutorial on Raspberry Pi, in the following link:

https://blog.back4app.com/2017/10/16/raspberry-pi-setup/

You must have a working app on Back4App. Follow Step 3 on the following tutorial if you still do not have.

https://www.back4app.com/docs/pages/android/how-to-build-an-android-app-on-back4app

You will also need to enable Live Query on your app. You may follow step 1 on the following tutorial if you have not enabled Live Query.

https://docs.back4app.com/docs/android/live-query/

This code was designed to interact with the Android App described in this series of tutorials. However, you may choose to develop it independently and interact directly with Parse Dashboard to create/inspect objects.

Section 1: Responding to Real-Time events on Parse Server

We will use Live Query functionality, made easy in our Back4App dashboard, to listen to real-time events. The real-world response is an interaction with the pins on Raspberry using the onoff package. Make sure you have installed it using npm.

Import Gpio class to initialize each pin.

var Parse = require('parse/node');
var onoff = require('onoff');
var Gpio = onoff.Gpio;

var ledPower = new Gpio(4, 'out'), output1 = new Gpio(17, 'out');

ledPower is a LED that will always be on to indicate the application is running. output1 is the LED that will be turned on/off as a response to Live Query.

Please note our Raspberry Pi has the following the pin diagram, extracted from here.

raspberry-pi-gpio-layout-model-b-plus-rotated-2700x900

There is a physical numbering corresponding to the numbers inside the circles and a GPIO specific numbering. For example, pin number 7 is GPIO4 and pin number 11 is GPIO17.

The integer argument on the constructor in the code above corresponds to the GPIO specific numbering! The second argument just sets it as an output pin. Please note that Raspberry Pi 2B outputs 3.3 V!

To turn on the power LED for the rest of the application, just add the following code.

ledPower.write(1,function(){
   console.log('Application is ON');
});

We want the second LED to respond whenever a new object from “CommandGPIO1” class is created on Parse Server. It will turn on/off depending on its “content” attribute. Since we want it to respond in real-time, we will have to use LiveQuery.

Add the following code to start LiveQuery on NodeJS.

var LiveQueryClient = Parse.LiveQueryClient;
var client = new LiveQueryClient({
   applicationId: 'YOUR_APP_ID',
   serverURL: 'wss:YOUR_SUBDOMAIN_NAME.back4app.io/', // defined on LiveQuery section on Back4App dashboard
   javascriptKey: '',
   masterKey: ''
});
console.log("pre client.open");
client.open();
console.log("post client.open");

The App ID can be found on “Core Settings” -> “Features” in your app dashboard. The serverURL is the same subdomain that you defined on LiveQuery in the app dashboard.

Now we have to define the query to be used with LiveQuery, and add the code to run when the event happens. Add the code below.

var query1 = new Parse.Query("CommandGPIO1");
var sub1 = client.subscribe(query1);
console.log("post sub1");
var count1 = 0;
sub1.on('create', (object) => {
   if(object.get("content") == 'off') count1 = 0;
   if(object.get("content") == 'on') count1 = 1;

   output1.write(count1, function(){
      console.log('Output 1 status changed to ' + count1);
   });
});

Object query1 corresponds to a new query for objects from “CommandGPIO1” class. Make sure you allowed Live Query for this class on your app dashboard!

The following lines create the subscription and activate it for the creation of a new object of the corresponding class. The function called whenever this event happens sets the variable count1 as 0 or 1 for off or on contents, and it writes this logic voltage value to output1.

We are almost done with this part of the tutorial! Add the following code to turn off our application properly when the process is interrupted.

process.on('SIGINT', function (){
   ledPower.writeSync(0);
   output1.writeSync(0);
   ledPower.unexport();
   output1.unexport();
   console.log('Bye, bye! Turning off LEDs');
   process.exit();
});

Section 2: Watching for Real-World Events and Acting on Parse Server

WARNING!!!: THE MAXIMUM INPUT VOLTAGE ON A PIN IS 3.3V! SOME PINS ON RASPBERRY PI SUPPLY 5V! BE CAREFUL NOT TO DAMAGE YOUR RASPBERRY WITH A WRONG CONNECTION!

We will define a pin on Raspberry Pi as an input. When the voltage in the input becomes high or low, we will turn on/off a LED and write an object on Parse Server with content as “high” or “low”.

var input1 = new Gpio(21, 'in', 'rising'), output2 = new Gpio(23, 'out');

Note, for the input pin, we have to define a second argument to specify on which edge of the signal the pin will operate. 

Now we have to initialize Parse Server. Add the code below

Parse.initialize('YOUR_APP_ID','YOUR_JAVASCRIPT_KEY');
Parse.serverURL = "https://parseapi.back4app.com";

We want to create “InputGPIO” class objects. The following code has a key role.

// Name of the class to be saved on Parse Server when event happens
var InputGPIO = Parse.Object.extend("InputGPIO");

// asynchronously reading from GPIO 21 (pin 40) on RPi 2B
// "value" can be either 0 (0 V) or 1 (3.3 V)

// Often multiple readings may come at once, even when the voltage on the pin is kept constant
// Therefore, the variable "valuePrev" is introduced to store the last voltage
// read from the pin and to trigger the desired actions only when it changes.
var valuePrev = -1;
input1.watch( function (err, value) {
   if(err){
      throw err;
   }

   if(value != valuePrev){
      valuePrev = value;

     // Turning on/off a LED when another voltage is read in the input pin
     output2.write(value, function(){
        console.log('Output2 changed to: ' + value);
     });

     // Creating new object
     var inputGPIO = new InputGPIO();
     inputGPIO.set("type","interrupt");

     if (value == 0){
        inputGPIO.set("content", "low");
        console.log("written low: " + value);
     }
     
     else{
        inputGPIO.set("content", "high");
        console.log("written high: " + value);
     }

     // Saving object to Parse Server
     inputGPIO.save().then( function(m){
        console.log(m);
     }).catch( function(err){
        console.error(err);
     });
   }
});

We start by extending Parse Object to the desired class, “InputGPIO”. Whenever a reading comes from the pin corresponding to input1, if it has a value different from the previous one:

  • This value is written to the pin corresponding to output2
  • An “inputGPIO” object with a proper content and type fields is created
  • The object is saved to Parse Server.

The logic involving value and valuePrev is useful because even when the voltage in the input pin is kept constant, multiple readings with the same state may continue to arrive.

We have almost finished! As in Section 1, we have to update the code to manage interruptions to the process.

process.on('SIGINT', function (){
   (...)
   output2.writeSync(0);
   output2.unexport();

   process.exit();
});

To test this process, connect and later disconnect the pin on Raspberry that supplies 3.3 V to the pin defined as input.

To have a real IoT device, these node processes need to run automatically when the device boots. Please refer to the pm2 package, already mentioned in our Setting up Raspberry Pi tutorial.

We provide a working code for this tutorial. If you prefer, you may write separated codes for each task and run both simultaneously with pm2. Here is the link for our GitHub repository.

https://github.com/back4app/iot-raspberry-node

Our next tutorial will cover how to write an Android App that works with the code described here. The code is also available in the repository.

References

Setting up Raspberry Pi

Onoff library documentation on npm

Using onoff package

 

How will we respond to real time events on real time events on Parse server?

Live query functionality is being used. It is developed in the back4app dashboard and is easily accessible. The real world response is a sort of interaction between pins of Raspberry by using the “on” and “off” response. For doing this, you need to make sure that npm is installed already.

What are the Prerequisites required?

You need following things before starting.

-3 LEDs
-3 Resistors
-Breadboard
-Jumpers

These are some of the main things which are required before starting it out.

Where can you find an Apple ID and what is the server URL?

You need to go to your app dashboard and go to core settings> Features. The server URL is the sub domain you have defined on live query.

The code is provided above in the article which you need to add after defining the query to be used in Live Query.


Leave a reply

Your email address will not be published.