Thursday, June 6, 2019

Raspberry Pi garage door, part 2

In case I forgot to put it in the last post, here is how to setup the camera to take pictures at regular intervals.

Now on to setting up the webserver.  This was more painful than I thought it would be.  But, it finally worked.  I went to /var/www/html and did this:
npm init to use the node package manager (NPM) to setup a new node project. You can press enter to accept the default settings, but when you get to entry point type in webserver.js
Now, do this:
sudo apt-get update

sudo apt-get dist-upgrade

npm install socket.io --save

npm install express --save


npm install onoff
A quick note here - some of these were added as I tested various methods for making this work.  I am not 100% positive that all of them are needed, but it can't hurt to have some extra code installed that's unused.

There are two files you will need:


sudo nano /public/index.html
<!DOCTYPE html>
<html>
<body>
<!--<p><input type="checkbox" id="light"></p> -->
<input type="image" id="light" src="http://yoursever/opener.jpg">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> 
<script>
var socket = io(); //load socket.io-client and connect to the host that serves $
window.addEventListener("load", function(){ //when page loads
  var lightbox = document.getElementById("light");
  lightbox.addEventListener("click", function() {
    socket.emit("light", Number(this.checked)); //send button status to server
  });
});
socket.on('light', function (data) { //get button status from client
  document.getElementById("light").checked = data; //change checkbox accordin$
  socket.emit("light", data); //send push button status to back to server
});

</script>

<br><br>

<img src='yourserver/doorpic.jpg'>

</html>
</body>
</html>




And sudo nano webserver.js

var http = require('http').createServer(handler); //require http server
var fs = require('fs'); //require filesystem module
var io = require('socket.io')(http) //require socket.io module and pass the http server
var Gpio = require('onoff/').Gpio; //include onoff 
var sensor = new Gpio(17, 'out'); //use GPIO pin 17, to check reed sensor 
var pushButton = new Gpio(4, 'high'); //use GPIO pin 4 as input, set to 1/high (off)
var mycounter=0;

http.listen(8080); //listen to port 8080


function handler (req, res) { //create server
  fs.readFile(__dirname + '/public/index.html', function(err, data) { 
    if (err) {

      res.writeHead(404, {'Content-Type': 'text/html'}); //display 404 if needed
   return res.end("404 Not Found");
    } 
    res.writeHead(200, {'Content-Type': 'text/html'}); //write HTML
    res.write(data); //write data from index.html
       if (sensor.readSync()==0) { res.write ("<h2>Garage sensor sez: Open!</h2>")}
       if (sensor.readSync()==1) { res.write ("<h2>Garage sensor sez: Closed.</h2>")}

    return res.end();
  });
}
}

io.sockets.on('connection', function (socket) {// WebSocket Connection
socket.on('light', function(data) { //get light switch status from client
console.log("Engage! " + mycounter);

pushButton.writeSync(1);
pushButton.writeSync(0);
// Turn off after 3 seconds
setTimeout(_ => {
pushButton.writeSync(1);
}, 3000);
mycounter++;


});
});

process.on('SIGINT', function () { //on ctrl+c
  sensor.writeSync(0); // Turn LED off
  sensor.unexport(); // Unexport LED GPIO to free resources
  pushButton.unexport(); // Unexport Button GPIO to free resources
  process.exit(); //exit completely
});

Doorpic is the picture the camera takes
Opener is a picture of the opener that I want to display in the app.
--put both in the folder noted above

Run node webserver.js and you are ready to go!

Now all you have to do is point to the IP address of your Pi and with the port 8080 (ie, http://192.168.0.123:8080) and you should be good to go!