This is our first installation of WillowTree Labs, a recurring blog post series in which we will discuss the details of our quarterly internal research projects. Each project is voted on by our team, and designers and developers share updates at our weekly Research & Development meetings. We conduct these research projects in an effort to stay on top of the latest technology trends, continue learning, and contribute new innovative mobile solutions for our clients.
Good startups grow fast. While WillowTree is outgrowing its ‘startup’ moniker, we still have our share of growing pains. We have moved and renovated several times over the past few years, all to make room for new hires. As a rapidly growing company, our biggest problem is not the struggling wifi network or the contractors bustling around…it is the ever-growing bathroom line. Since last year, we have doubled our staff without adding any new bathrooms. Renovations plans are in the works, but we were not willing to wait. Since bathrooms can’t be built overnight, we built a tool to tell us if one is available. Enter: “Bathroom Monitor”.
Our primary goal was to detect and broadcast the bathroom status throughout the office, using whatever technology was available. After several iterations, we elected to use magnetic contact switches and a Raspberry Pi. Each contact switch would be mounted on a bathroom door and wired to a central RPi. The RPi would then broadcast the switch values through an API. The end goal is to have desktop/mobile clients that consume the API and report the status in real-time.
Here is how we built it.
- Raspberry Pi, Amazon
- 3 Magnetic contact switches, Amazon
- Prototyping board, Amazon
- Adafruit PermaProto Pi Breadboard, Amazon
- Wire strippers
- 16-18 gauge wire (10-30 ft.)
- Banana connectors, Wikipedia
- USB Wi-Fi dongle, ModMyPi.com
- 5V 2A micro-usb power supply (optional, to power the wifi dongle), Amazon
Configuring Raspberry Pi
If this is your first exercise with a Raspberry Pi, use this guide to get familiar with the device.
We set up our RPi using a Wheezy Raspbian image from an SD card. Another option would be to use a NOOBS installer, but we found that NOOBS takes a very long time to install on large (32GB) SDCards. Both of these installers can be found here. After downloading and copying the OS to the SD card, insert the card into the RPi and connect the power adapter. The RPi will automatically boot the OS. Depending on the image, there may be some one-time configuration.
Configuring Wifi Dongle (optional)
Our setup required the RPi to be mounted in a room without an ethernet connection. If you have an ethernet connection available, you can skip this step.
Some issues we encountered:
- Plugging/unplugging USB cables while the RPi is switched on can reset the device, so avoid doing this.
- Our RPi power adapter could not provide enough power for the Wi-fi dongle. We switched to a 2 amp power adapter, which solved the problem. Alternatively, the dongle could be connected through a powered USB hub.
Connecting the Contact Switches
The magnetic switches work as simple pull down switches. They connect to the GPIO ports on the RPi, shown in the below diagram. We are using GPIO pins #4, 17 and 27. Before soldering the components to the board, we prototyped one circuit on a breadboard. This image shows the circuit powering an LED: The circuit for one sensor on the prototyping board is as follows. It references the image below of the top of the prototype board:
- Connect the 3.3V power from pin 1 on the RPi to power the positive column on the board (the leftmost column).
- Run a 10K Resistor from the positive column to current GPIO row.
- Connect the contact sensor’s lead to the current GPIO row. Ensure that the resistor connects between the contact sensor’s lead and the GPIO pin.
- Ground the contact sensor using the negative column (the second leftmost column).
- Connect the bottom of the negative column to the ground pin. Above: The complete breadboard, top and bottom.
Communicate with the Contact Switches
We used a Python library called RPi.GPIO to directly read the GPIO pins on the RPi. Though the RPi.GPIO documentation warns that it is not suited for timing critical applications, it worked well for our setup.
Raspberry Pi as a Server
The API was built in Python using the Flask micro web framework. When the API endpoint is called, we read the state of the GPIO pins and report the status of each door in a JSON formatted response.
One side effect of our current network and DNS setup is that the RPi is only reachable by devices connected to the same wifi. Future improvements would have the bathroom monitor connect to an external server that makes its API available globally through an http API.
There are also plans to use the edge detection feature of RPi.GPIO to record when each of the bathroom doors open and close. From this we could generate a history API allowing app developers to generate things like graphs, usage statistics, average use, peak use, etc.
Mounting the Monitor and Switches
We gave ourselves as much flexibility as possible to revise our wiring and mounting. The magnetic switches and wires were secured to doors and walls with gaffer tape. The wires connecting the magnetic switches to the RPi were stripped and fitted with banana connectors from the local hardware store. They cost about $0.50 each and allow us to easily unplug the main monitor from the wiring for updates or servicing.
We built several clients to deliver the bathroom status to employees. Each client polls the JSON API in some fashion.
- The iOS/Android client uses colored human silhouettes to indicate availability: Green for available and red for unavailable.
- The Mac app places a three-leaf status icon in the menu bar indicating which bathrooms are available. Also allows OS X system notifications for when a bathroom becomes available. The app runs as an “agent,” so it is windowless and doesn’t have an app running in the dock. This is more discreet than having an app called “Bathroom Monitor” visibly running with your other applications.
- A command line tool that outputs the bathroom status:
- A “say” ruby script that announces the number of bathrooms available on a status change: “There are 2 bathrooms available.” Sound Clip