Appliances Control System using Raspberry Pi and Node.js

RPi GPIO Programming using Arduino Web IDE

This is a Raspberry Pi based project using Raspberry Pi and Node.js which lets the user control appliances connected to the Raspberry Pi. Node.js acts as a server which serves a UI for the user to control the desired appliances. According to the input by the user, the node.js script running on Raspberry Pi toggles the GPIO required and the state of the device connected to the GPIO, gets changed.As most appliances operate from AC supply, mechanical or solid state Relays has to be used to control the appliances. The demonstrated project uses 4 appliances but you can add as many appliances as required (Of course limited by nos of GPIO of Raspberry Pi). The application is completely developed in NodeJS, without using any other framework and can be extended by using frameworks like ExpressJS. The UI communicates with the NodeJS script using AJAX calls. To interact with the GPIOs of Raspberry Pi ‘rpio’ library has been used.You can change the appliance’s name in the UI as per your requirement.

Configuration:

Connect the Relay board to the GPIOs of Raspberry Pi as shown below using jumpers. If you don’t have Relay board around, you can test it out even by using LEDs. Pin mapping used by the rpio package in this project is the physical pin layout of the GPIOs and correspond to their physical position in the GPIO header.

 

Raspberry Pi 4 Ch. Relay Board Connections
______________________________________________
5V (Pin 1) —————– Vcc Pin (If high current is required, consider using an external power supply.)
Gnd.(Pin 6) —————– Gnd. Pin
GPIO04 (Pin 7) —————– Relay 1
GPIO17 (Pin 11) —————– Relay 2
GPIO27 (Pin 13) —————– Relay 3
GPIO22 (Pin 15) —————– Relay 4

Steps:

If the Raspberry Pi is being used in Headless mode i:e. no Display is connected, it can be accessed from other PC using SSH but both should have to be on the same network and the IP address of the Pi has to be known.Plug in the SD card to any PC and create an empty file named SSH to boot folder to enable SSH connection. If the file is not created, as per the new Raspbian OS Raspberry Pi will not accept SSH connection. Connect to the Pi using SSH, if that is being used or otherwise open up the terminal in Raspberry Pi in the connected display by using Keyboard and mouse.After we have access to the terminal of Pi by using SSH or Display we then need to add the packages required for the project. We have used NOOBS_v2_4_5 with Raspbian Strech, which comes preloaded with node.js 4.8. But we need to install other libraries as required and also NPM has to be installed for that. NPM is used to install packages for node.js.

1. Install npm:
To install npm use the command,

$sudo apt-get install npm

2. Install rpio package:

After installation of npm completes, we need to install ‘rpio’ (Raspberry Pi GPIO access library for node.js link: www.npmjs.com/package/rpio) and to do that use the command,

$sudo npm install rpio

If everything goes fine your terminal should look something like this, as shown in the image below

After installation of the required packages, Create the main.js and ui_content.html (Both files should have to be in the same folder or the path to the ui_content.html file has to be changed in the main.js script.). Copy the codes provided below to the respective files. The ui_content.html file contains the UI for the user which is served by the web-server created in the main.js file. It also contains javascript to make ajax calls in the background to interact with the nodejs script, whenever the user presses any button in the UI.

http.createServer(function (req, res) {
///our code
}).listen(80);

The above code snippet shows the creation of a web-server using node.js and is opened on port 80. You can use any port as you want, but make sure that the particular port is not used by any other applications.  The 4 loads as demonstrated in this project are mapped as 4 diff pages served by the server, so as to access them individually. Whenever a particular page is requested, the relay associated with the page gets toggled.

Now run the main.js script using the command,

$sudo node main.js

This should start the web-server created in the script and we can control the loads using the web-page served by the server on port 80. Open up any browser on a machine (it should have to be on the same network as the pi is in.) and type in the IP address of the Raspberry Pi into the address bar and it will open up a webpage like this

Now you can click on the buttons on the UI and the corresponding relay state should get toggled. Circle over the buttons shows the state of the loads in real-time.

Code: main.js
console.log('NodeJS Automation Project');
var http = require('http');
var url = require('url');
var fs = require('fs');
var rpio = require('rpio');#Use rpio for GPIO access.

var content_ui = ""
var load_one = 0;
var load_two = 0;
var load_thr = 0;
var load_for = 0;

var pin_one = rpio.open(7, rpio.OUTPUT, rpio.LOW);#open(PIN_NUMBER, MODE, INITIAL_STATE)
var pin_two = rpio.open(11, rpio.OUTPUT, rpio.LOW);
var pin_three = rpio.open(13, rpio.OUTPUT, rpio.LOW);
var pin_four = rpio.open(15, rpio.OUTPUT, rpio.LOW);

fs.readFile('ui_content.html', function(err, data) {#static HTMl content for UI
    console.log(err);
    content_ui = data;
});

function changeLoadStatus() {#refresh status of teh loads based on current status.
    rpio.write(7, load_one);#write(PIN_NUMBER, STATE) STATE: 0 / 1
    rpio.write(11, load_two);
    rpio.write(13, load_thr);
    rpio.write(15, load_for);

}

http.createServer(function(req, res) {
    if (req.method == 'POST') {#To identify POST call made by the ajax script
        // Handle post info...
        var q = url.parse(req.url, true);
        // console.log(q.pathname);
        if (q.pathname == '/0') {# Request handeled for initial status of loads when teh server serves the UI.
            console.log('init status requested.');
        }
        if (q.pathname == '/1') {
            load_one = 1 - load_one;
            console.log('Bulb 1 clicked');
            changeLoadStatus();
        }
        if (q.pathname == '/2') {
            load_two = 1 - load_two;
            console.log('Bulb 2 clicked');
            changeLoadStatus();
        }
        if (q.pathname == '/3') {
            load_thr = 1 - load_thr;
            console.log('Bulb 3 clicked');
            changeLoadStatus();
        }
        if (q.pathname == '/4') {
            load_for = 1 - load_for;
            console.log('Bulb 4 clicked');
            changeLoadStatus();
        }
        res.writeHead(200, {
            'Content-Type': 'text/html'
        });
        res.write('' + load_one + load_two + load_thr + load_for);
        res.end();
    } else {

        res.writeHead(200, {
            'Content-Type': 'text/html'
        });
        res.write(content_ui);
        res.end();
    }
    //console.log(req);
    res.end();
}).listen(80);
Code: ui_content.html
<html>
   <head>
      <style>
         .circle {
         border-radius: 50%;
         width: 50px;
         height: 50px;
         float: none;
         background: red;
         border: 1px solid black;
         /* width and height can be anything, as long as they're equal */
         }
      </style>
   </head>
   <body onLoad="pressed(0);" >
      <h1 align="center">NodeJS based Appliances Control System on Raspberry Pi</h1>
      </br>
      </br>
      </br>
      <table width="50%" align="center">
      <tr>
         <td align="center" width="25%">
            <div id='0' class="circle"></div>
         </td>
         <td align="center" width="25%">
            <div id='1' class="circle"></div>
         </td>
         <td align="center" width="25%">
            <div id='2' class="circle"></div>
         </td>
         <td align="center" width="25%">
            <div id='3' class="circle"></div>
         </td>
      </tr>
      <tr>
         <td align="center">
            <button onClick="pressed(1);" id="1_button">Appliance 1</button>
         </td>
         <td align="center">
            <button onClick="pressed(2);" >Appliance 2</button>
         </td>
         <td align="center">
            <button onClick="pressed(3);" >Aplliance 3</button>
         </td>
         <td align="center">
            <button onClick="pressed(4);">Aplliance 4</button>
         </td>
      </tr>
      <table>
   </body>
   <script>
      function pressed(id){
      //alert();
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
      //alert('Hello');
      for (i=0;i<this.responseText.length;i++){
      if(this.responseText.charAt(i)=='1')
      document.getElementById(i).style.backgroundColor="green";
      // document.getElementById(i).innerHTML = "ON";
      else
      document.getElementById(i).style.backgroundColor="red";
      }
      //document.getElementById(id).color="#0F0000";
      //document.getElementById("console").
      }
      };
      xhttp.open("POST", "/"+id, true);
      xhttp.send();
      }
   </script>
</html>

Suvendu Swain
Catch Me On

Suvendu Swain

Blogger/ Educationist at WeArGenius
A person passionate about tech stuffs.
Suvendu Swain
Catch Me On

Latest posts by Suvendu Swain (see all)

Related posts