Simple Hardware Hacking: Auto "On Air" VC Indicator - Chapter 1

Even before the COVID-19 pandemic (although especially since then), I would pretty regularly take meetings from my room. I’m currently living with my parents who want to be respectful of my space but also want to get my attention for various reasons. As such, they’ve asked for some indication of when I’m in a meeting.

My current system is to put a post-it note on the door before the meeting starts. This system works okay but has two, fairly obvious, pitfalls:

  • I forget to put the post it note before meeting

  • I forget to remove it after meeting

It would be great if I didn’t have to worry about remembering to set and unset this flag. Luckily we live in a marvelous era of magic and machinery. As such, all things are possible.

In order to satisfy the constraints, we need two parts:

  • A Notifier, in other words the part of the system that notifies the outside world of the meeting status

  • An Updater, the part that observes the meeting status and updates the notifier

Solution

Notifier:

For our notifier, we’ll keep it simple in terms of aesthetics and use an LED as a placeholder for some sweet future sign:

On_Air_white_sign.gif

That LED will be controlled by a Raspberry Pi 2B. In addition to just driving the LED, we’ll need a way to accept commands to change the LED. For this purpose, we’ll run a web server which surfaces an api on our local network to control the LED.

Updater:

Things get slightly more interesting here. We need something that can tell whether or not I’m currently video chatting. I’m sure there are many different ways we could have approached this. For me in particular, there’s an important bit of context which is that 90% if not more of my video chats happen over in browser over Google Hangouts. One easy way to do this, then, is to add a chrome extension which listens for my browser visiting the hangouts video chat URL and calls the corresponding API on the web server depending on the state.

Overview:

Fig 1: Diagram of the planned solution

Fig 1: Diagram of the planned solution

Part 1: LED circuit

What you’ll need:

  • raspberry pi (any model should do) with raspbian on it

  • red (or any other color for that matter) LED

  • 330 ohm resistor

  • a breadboard

  • jumper wires (these will connect your raspberry pi header pins to your bread board)

This is about as basic as it gets with raspberry pi electronics. We’ll use a circuit from a hello world-esque LED blink tutorial:

Fig 2: Our Simple LED Circuit

Fig 2: Our Simple LED Circuit


Before you wire this up, confirm the pinout diagram for your specific Raspberry Pi. You’ll need to make sure that the black wire is going to a ground pin and the blue wire is going to one of the General Purpose Input/Output pins (GPIO). In addition, you’ll need to know which of the GPIO pins your circuit is wired to when we start to write the code to control it.

Once you have that wired, open a terminal and run the following commands:

sudo apt install python3 python3-pip
sudo pip3 install gpiozero

These will install the required dependencies for this project. Now, go back to your terminal and enter the following to test out your circuit:

$ python3
>>> from gpiozero import LED
>>> led = LED(YOUR_GPIO_PIN)
>>> led.on()

If you’ve wired your circuit correctly, your LED should light up! If it’s not working as expected, try moving the one connection from the GPIO pin to a +3.3 volts pin and confirm that it lights up. If it lights up you may have been referencing the wrong GPIO pin. If it doesn’t light up, there may be a problem with your circuit. Go through each element and make sure they’re connected and that it’s not touching any other part of the circuit (causing a short). Also keep in mind that the LED only works in one direction. If in doubt, look at the leg lengths; the shorter one should be connected to the ground.

If you can control your LED, then congratulations! You’ve completed the hardware portion of the project (leaving aside aesthetic improvements of the resulting signal).

Part 2: Webserver

What you’ll need:

  • nothing else! you should have everything already if you’ve made it this far!

Now that we have an LED we can control, we need a way to tell it what to do.

We’ll do this with a simple web server. For this we’re going to be using a python library called flask. First, we’ll install flask by running this command:

sudo pip3 install flask

Next, we’ll create a new file called server.py. I recommend Thonny, the built in Raspberry Pi python IDE. which will give you the ability to quickly run, stop and debug your code.

This is the code we’ll start with for the server:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
  return ‘hello world!’

app.run()


and run your code. In Thonny, you can just press the play button in the toolbar. Otherwise, in a terminal, you can run:

$ python3 server.py

Try visiting localhost:5000 in your browser. You should see ‘hello world!’ in your browser. If so, that means it worked and you have your very own webserver up and running.

To explain what’s happening here:

  • We’ve imported Flask and created an “app”

  • Then, we created a “route” on our app which is really just a function that should be called when someone visits “/” on our webserver (which is the default route).

  • Finally, we call app.run() which actually tells the server to start.

Now we have the two pieces, we can control our LED from Python and have a server (written in Python as well) that we can call from a browser, now we just need to weave these two together.

Part 3: Combining the Raspberry Pi and Flask server

If you’re familiar with programming, you may be way ahead of me but, now we just need to add a new route to our server that will turn our LED on or off.

First, we should import the gpiozero library we used before to turn our LED on and off:

from flask import Flask
from gpiozero import LED

app = Flask(__name__)

@app.route('/')
def hello_world():
return 'hello world!'

app.run()

Next underneath the creation of the flask app, we’ll initialize our LED variable:

from flask import Flask
from gpiozero import LED

app = Flask(__name__)
led = LED(YOUR_GPIO_PIN)

@app.route('/')
def hello_world():
return 'hello world!'

app.run()

 

Now, we’ll copy our route from before and create two new ones, updating the string within the @app.route decorator and changing the name of the function. Add the routes “/on” and “/off” each with a corresponding function. Your code should look like this:

from flask import Flask
from gpiozero import LED

app = Flask(__name__)
led = LED(YOUR_GPIO_PIN)

@app.route('/')
def hello_world():
return 'hello world!'

@app.route('/on')
def on():
  return 'hello world!'

@app.route('/off')
def off():
  return 'hello world!'

app.run()

Finally, we’ll actually make these methods actually modify the LED:

from flask import Flask
from gpiozero import LED

app = Flask(__name__)
led = LED(YOUR_GPIO_PIN)

@app.route('/')
def hello_world():
return 'hello world!'

@app.route('/on')
def on():
  led.on()
  return 'Turned LED on successfully!'

@app.route('/off')
def off():
  led.off()
  return 'Turned LED off successfully!'

app.run()

Now, if you run your server again and visit localhost:5000/on in your browser, TADA! your LED should magically illuminate!

But I’m not video conferencing from my Raspberry Pi! I need to be able to contact this webserver from my laptop. Let’s give that a shot. First we need to know what the LAN IP address is for our raspberry pi. This IP is how any other device on your local network will contact your raspberry pi. Luckily you can just run this simple command to see what the LAN IP of your Raspberry PI is:

$ hostname -I 

[YOUR_IPV4_LAN_IP_ADDRESS] [YOUR_IPV6_LAN_IP_ADDRESS] 

Now, using another device that’s connected via WiFi or ethernet to the same router as the one that the Raspberry Pi is, you should be able to go to the IP that the hostname command returned and see the result for example you should be able to enter “[YOUR_IPV4_LAN_IP_ADDRESS]:5000/on” in your browser and contact your server, EXCEPT for one last thing!

If you try that, you’ll notice that it doesn’t connect. This is because we need to explicitly tell our flask server to listen for requests on that LAN ip address. By default, it will just listen to requests coming from the local host (127.0.0.1)

Luckily, the app.run() command accepts a host parameter which you can specify which IP address you should be listening for requests from. We have two options here. We could explicitly write our LAN IP address in the host:

app.run(host=”[YOUR_IPV4_LAN_IP_ADDRESS]”)

and that would work fine but there’s a nifty shorthand that can save us from needing to update that line of code every time we have a different LAN IP address. You can specify “0.0.0.0” and it will have the same effect:

app.run(host=”0.0.0.0”)

So our final server code is:

from flask import Flask
from gpiozero import LED

app = Flask(__name__)
led = LED(YOUR_GPIO_PIN)

@app.route('/')
def hello_world():
return 'hello world!'

@app.route('/on')
def on():
  led.on()
  return 'Turned LED on successfully!'

@app.route('/off')
def off():
  led.off()
  return 'Turned LED off successfully!'

app.run(host='0.0.0.0')

So there you have it! An IP-addressed linux machine whose sole job is to turn an LED on and off:

ricknmorty0001.gif

Conclusion

We’ve built our “notifier” out of a RaspberryPi, a simple circuit and a flask server. In the next post, we’ll move onto how we can go about operating our notifier with our “updater” browser extension!

References