Building a Raspberry Pi IOT Garage Door Opener - Part 4 (Software Setup - Steps 4-7)

Step 4 - Starting our program

We have all our dependencies ready, so we are now ready to start writing our garage door opener program. We will start with a very simple server and build it up into the final program.

First, let's move into our root directory, create and edit our new file.

cd /root
nano garage.py


Here is the first lot of code we will try. This simply imports the bottle web-server classes that we will use and starts a web-server. It also imports the Python GPIO library so we can make sure that is working. We have also set the GPIO library to use the board pin numbering.
 from bottle import route, run import RPi.GPIO as GPIO GPIO.setmode(GPIO.BOARD) @route('/activate') def activate(): return 'activated' run(host='0.0.0.0', port=8080)
Copy this code into the nano editor, Ctrl-X, Y, Enter to Save.
Let's now take it for a spin. 

python garage.py

Type the above command into your terminal and the server should start.


Now, open your internet browser, and type in http://[PI IP]/activate
For me, the address is http://192.168.2.254:8080/activate

You should see our "activated" message in your browser window.


Congratulations, you are now running a tiny web-server on your Raspberry Pi!

To stop the server, simply press Ctrl-C in the terminal.

Step 5 - Making our program activate our relay

Our next step it to make our program switch on and off our relay.

from bottle import route, run from time import sleep import RPi.GPIO as GPIO GPIO_PIN = 11 GPIO.setmode(GPIO.BOARD) GPIO.setup(GPIO_PIN, GPIO.OUT, initial=GPIO.LOW) @route('/activate') def activate(): GPIO.output(GPIO_PIN, GPIO.HIGH) sleep(1) GPIO.output(GPIO_PIN, GPIO.LOW) return 'Garage switch activated' run(host='0.0.0.0', port=8080)
What we have done here is set a variable to hold the value of our GPIO output pin (Pin 11), and then setup that Pin as an output pin.

In the activate function we set the pin high which will switch on the relay, then we sleep (delay) for 1 second and then set the pin low again.

With the relay connected as outlined in Part 2 (Hardware Setup), we are now finally ready to see it in action.
Ctrl-X, Y, Enter to save the new code and exit.
Then run the program again using the below. 

python garage.py

Visit the page in your browser (http://192.168.2.254:8080/activate) and you should hear the relay activate, then after 1 second, turn off. Great!

This is now a fully working code that could be used to open/close your garage.
However, there a few more changes we will make

1) Stop the relay being activated for 15 seconds after an activation (allows for garage to open / close)
2) Move the opening / delay code into a new thread to allow the web-server to return an instant response.
3) Make our code return JSON responses (ready for communicating with our Android app)

from bottle import route, run from time import sleep import RPi.GPIO as GPIO from threading import Thread, Lock from json import dumps as json_encode GPIO_PIN = 11 LOCK = Lock() GPIO.setmode(GPIO.BOARD) GPIO.setup(GPIO_PIN, GPIO.OUT, initial=GPIO.LOW) def do_activate(): LOCK.acquire() try: GPIO.output(GPIO_PIN, GPIO.HIGH) sleep(1) GPIO.output(GPIO_PIN, GPIO.LOW) sleep(15) finally: LOCK.release() @route('/activate') def activate(): if LOCK.locked(): return json_encode({"result":False, "message":"Already in progress"}) thread = Thread(target=do_activate) thread.start() return json_encode({"result":True, "message":"OK"}) run(host='0.0.0.0', port=8080)
We have created a new function which activates the relay and also gives us the 15 second delay.
We then call this function in a new thread so our activate function is free to return a response straight away (otherwise our browser would sit loading until after the 15 second delay).

The way we stop other calls from activating the relay is by using a Thread lock.
Only one thread can obtain this lock at a time until it is released.

So, you could have 100x calls to our server but only the first will go through and others will be blocked until the first call is finished.

That is our finished code!

Let's test it out...

python garage.py

Visit the page in your browser (http://192.168.2.254:8080/activate) and the relay should activate and instantly you should get a response {"message": "OK", "result": true}.

Now refresh the page and it should give you a response {"message": "Already in progress", "result": false} and the relay should not activate.

After 15 seconds, try again and you should get an OK response and the relay activates.

Perfect!

Step 6 - Network monitor script

We will add one more script to our system. This script will monitor the WiFi connection and reboot the Pi if it is lost. This way if you reset your router the Pi will reboot and re-connect.

We will use a simple bash script to accomplish this.
This script will ping our router every minute and if it doesn't get a response - it will reboot.

We will need to install fping for this to work, so let's install that now

apt-get install -y fping

Let's create and edit the new script

nano network-monitor.sh

And the below code to the file

#!/bin/bash sleep 120 while true; do itest=$(fping 192.168.2.1 | grep alive) if [ "$itest" == "" ]; then echo "ERROR" reboot fi echo "OK" sleep 60 done
Change 192.168.2.1 to the IP address of your router.

Make this file executable

chmod +x network-monitor.sh

Let's test it

./network-monitor.sh 

After the inital wait of 2 minutes, you should see a OK message displayed. Then a minute later another OK message and so on. You can try unplugging your router or unplugging the WiFi dongle to see if the Pi reboots, but doing either of these will probably disconnect your SSH session so you won't see the ERROR message.

That's the network monitor script finished.

Step 7 - Make the scripts run on boot

We have two commands that need to be run on boot

1) python /root/garage.py &
2) /bin/bash /root/network-monitor.sh &

The & at the end of each line makes the command execute in a subshell and therefore won't wait for them to complete before moving on to the next line.

To make these commands run on boot, we add them to the rc.local file.

nano /etc/rc.local 

We need to insert our two lines between /root/boot/boot.sh and exit 0.

The file should now look like this


Save and exit (Ctrl-X, Y, ENTER)

Now, we can test by rebooting the Pi.
It should boot up and start our python script and also the network monitor script.

That is our software complete.
In our next part we will install our Android app to talk to our server.

Part 5 (the final) is now up HERE