Project Loo: the best time-wasting, amazing, over-engineered project of my life
Tags: raspberrypi, vue, firebase, javascript
Published: 2020-10-18 17:51:05


At my previous company, BreezoMeter, we had a problem, but it wasn’t a software architecture one, a code plight, or a cultural issue.

The problem was... [cue Scooby-Doo sound effect - DAM DAM DAM] - the bathroom.


## THE PROBLEM

Our offices were great back when we were 8 people, but over time we grew to over 40 employees in the same offices having to share only TWO BATHROOM STALLS.

Now, I know what you're thinking, those spoiled engineers probably expect a personal stall each; but I assure you, that was not the case, and to make matters worse, there was no direct line of sight from our desks to the bathroom doors, so we couldn’t tell when they were vacant.

We decided that we have to find a remedy to this situation, so that people may relieve themselves when they please or at least be notified whenever the bathroom is vacant.

> *Not every invention needs to change the world; sometimes, it’s enough to change one person’s world.*
__-- Shahar Polak__

## THE SOLUTION

Every couple of months we used to have "Lab Days" - mini hackathons in which we could try new technologies, fiddle with ideas, and do so in teams that we did not have too much interaction with in our day-to-day.

My fellow teammate, Simon, and I played with the idea of connecting those stalls to the internal network, as every stall should be.

We knew that time was of the essence; we had two days to come up with a plan, buy all the equipment we needed, install the hardware, write the software, and make sure everything was working as expected.

## THE ARCHITECTURE

After thinking it over, we decided to go with Google Firestore’s real-time database for the bathroom doors’ state.

We created a Vue.js web application to present users with the doors' status and connected to Firestore.

We added Cloud Functions so we could integrate it with Slack as well.

And lastly, we created workers so users would be able to subscribe and get a notification whenever the status changed.

Did I mention that we had two days to pull this off? Ambitious, I know.


![alt text](https://storage.googleapis.com/shahar-data/blog/over-engineering-post/over%20engineering%20architecture.png "over-engineered project")

## THE PROCESS

On the day of the Lab Day, we both arrived at the office at 7:00 after a weekend of excitement and anticipation.

We decided to go with Raspberry Pi 3 with a microswitch as we thought it would be our best bet.

The microswitch is an on/off clip that connects to the Raspberry Pi 3 and can send a boolean signal.

![alt text](https://storage.googleapis.com/shahar-data/blog/over-engineering-post/microswitch.jpg "Raspberry Pi 3 with a microswitch")

Simon took the drill and started making holes so we could run the wires to the restroom. Not the most elegant way, but hey, it worked.

We installed [Raspbian OS](https://www.raspberrypi.org/downloads/raspberry-pi-os/) and Python 3 on the Raspberry Pi and then the coding began.

We had to build a small program that would sample the microswitch every X seconds and, once the status changed, update the database.

The first problem we encountered was false positives. The microswitch that we installed on the door was extremely sensitive, so every couple of seconds, even if someone only touched the door, it would send through a signal. We decided to change strategy and update our server only after 5 times that the microswitch sent the same signal.

The Python program would check every second what the microswitch's status is; once it detects the same signal 5 times and the status is different from the current one, it would update the database's state.

A small code sample, just to explain the Raspberry Pi part without too many tedious details:

```python 
class Queue:
    def __init__(self, limit):
        self._limit = limit
        self._items = []

    def is_empty(self):
        return self._items == []

    def append(self, value):
        should_remove_first = (self.size() >= self._limit) and not self.is_empty()
        if should_remove_first:
            self._items.pop(0)
        self._items.append(value)

    def size(self):
        return len(self._items)

    def all_same(self):
        if self.is_empty():
            return False
        return all(elem == self._items[0] for elem in self._items)
    
    @property
    def items(self):
        return self._items

def get_door_status():
    # reads the data from the Raspberry pi micro-switch


def update_door_server_status(door_id, status):
    # update firebase with the new status

def main():
    status = False
    q = Queue(5)
    door_id = 1 
    while True:
        time.sleep(1)
        door_status = get_door_status()
        q.append(door_status)
        all_same = q.all_same()
        if not all_same:
            continue
        if status == door_status:
            continue
        update_door_server_status(door_id, door_status)
        status = door_status
```

Now that we had code that updates the database, we had to create a web client, so users could access it.

We decided to go with a lean application using [Vue.js](https://vuejs.org/) hosted on [Firebase Hosting](https://firebase.google.com/products/hosting) - why you ask? Well, it's free.

We hustled our way into our designer’s heart and convinced him that designing the restroom's web pages is probably the best use of his time. The designs came out great!


## THE FINAL RESULTS

This is the final result: 

![alt text](https://storage.googleapis.com/shahar-data/blog/over-engineering-post/loo-cloud%20website%20-%20side%20by%20side.png "over-engineered project final results")

We even had a favicon that changed according to the status, so people could collapse the browser tab and see by the icon if the restrooms are available or not.

We added a button to subscribe and get a notification the second that the restrooms are vacant.

## CONCLUSION

Not every application is meant to change the world. This is one of those applications that did one thing and did it well, and it was a heck of a lot of fun building it.

So after building [loo.cloud](https://loo.cloud/) (yes, we actually bought this domain, but we do not use it anymore), we pondered these questions.
Was it perfect? Far from it!
Was it over-engineered? Like 10 levels too much for the task at hand.
Was it awesome? Sure as hell was.

Building fun stuff is part of what makes being a software engineer so much fun.