An Introduction to IoT (Internet of Toilets)
Joe KarlssonPublished Feb 07, 2022 • Updated Sep 23, 2022
Rate this code example
Another reason IoT developers use Node is it's ease in updating your code base. With other programming languages commonly used for IoT projects (C or C++), if you want to update the code, you need to physically connect to the device, and reflash the device with the most up-to-date code. However, with an IoT device running Node, all you have to do is remotely run
npm install. Now that's much easier.
One of the major innovations of Node is the event loop. The event loop enables servers running Node to handle events from the outside world (i.e. requests from clients) very quickly. Node is able to handle these events extremely efficiently and at scale.
Now, consider how an IoT device in the wild is built to run. In this thought experiment, let's imagine that we are designing an IoT device for a farm that will be collecting moisture sensor data from a cornfield. Our device will be equipped with a moisture sensor that will send a signal once the moisture level in the soil has dropped below a certain level. This means that our IoT device will be responding to a moisture event (sounds a lot like an event loop ;P). Nearly all IoT use cases are built around events like this. The fact that Node's event-based architecture nearly identically matches the event-based nature of IoT devices is a perfect fit. Having an event-based IoT architecture means that your device can save precious power when it does not need to respond to an event from the outside world.
Lastly, it's important to note that there is a mature community of IoT developers actively working on IoT libraries for Node.js. My favorites are Johnny-Five and CylonJS. Let's take a look at the "Hello World" on IoT devices: making an LED bulb blink. Here's what it looks like when I first got my IoT "Hello World" code working.
Just be careful that your cat doesn't try to eat your project while you are getting your Hello World app up and running.
This leads me to my personal IoT project, the IoT Kitty Litter Box. For this project, I opted to use Johnny-Five. So, what the heck is this IoT Kitty Litter Box, and why would anyone want to build such a thing? Well, the goal of building an internet-connected litter box was to:
- Help track my feline friend's health by passively measuring my cat's weight every time he sets foot in the litter tray.
- Monitor my cat's bathroom patterns over time. It will make it easy to track any changes in bathroom behavior.
- Explore IoT projects and have some fun!
Also, personally, I like the thought of building something that teeters right on the border of being completely ridiculous and kinda genius. Frankly, I'm shocked that no one has really made a consumer product like this! Here it is in all of its completed glory.
- 1 x Raspberry Pi - I used a Raspberry Pi 3 Model B for this demo, but any model will do.
- 1 x Breadboard
- 2 x Female to male wires
- 1 x 3D printer [Optional] - The 3D printer was used for printing the case where the electronics are enclosed.
- 1 x PLA filament [Optional] - Any color will work.
- 1 x Solder iron and solder wire
- 8 x M2x6 mm bolts
- 1 x HX711 module - This module is required as a load cell amplifier and it converts the analog load cell signal to a digital signal so the Raspberry Pi can read the incoming data.
- 4 x 50 kg load cell (x4) - They are used to measure the weight. In this project, four load cells are used and can measure a maximum weight of 200kg.
- 1 x Magnetic door sensor - Used to detect that the litter box is opened.
- 1 x Micro USB cable
- 1 x Cat litter box
So how does this IoT Kitty Litter Box work? Let's take a look at the events that I needed to handle:
- When the lid of the box is removed, the box enters "maintenance mode." When in maintenance mode, I can remove waste or refresh the litter.
- When the lid of the box is put back on, it leaves maintenance mode, waits one minute for the litter to settle, then it recalibrates a new base weight after being cleaned.
- The box then waits for a cat-sized object to be added to the weight of the box. When this event occurs, we wait 15 seconds for the cat to settle and the box records the weight of the cat and records it in a MongoDB database.
- When the cat leaves the box, we reset the base weight of the box, and the box waits for another bathroom or maintenance event to occur.
You can also check out this handy animation that walks through the various events that we must handle.
For this project, I opted to work with a Raspberry Pi 3 Model B+ since it runs a full Linux distro and it's easy to get Node running on it. The Raspberry Pi is larger than other internet-enabled chips on the market, but its ease of use makes it ideal for first-timers looking to dip into IoT projects. The other reason I picked the Raspberry Pi is the large array of GPIO pins. These pins allow you to do three things.
- Power an external sensor or chip.
- Read input from a sensor (i.e. read data from a light or moisture sensor).
- Send data from the Raspberry Pi to the outside world (i.e. turning a light on and off).
I wired up the IoT Kitty Litter Box using the schema below. I want to note that I am not an electrical engineer and creating this involved lots of Googling, failing, and at least two blown circuit boards. It's okay to make mistakes, especially when you are first starting out.
We will be using these GPIO pins in order to communicate with our sensors out in the "real world."
I want to start with the most simple component on the box, the magnetic switch that is triggered when the lid is removed, so we know when the box goes into "maintenance mode." If you want to follow along, you can check out the complete source code here.
You can see the event and asynchronous nature of IoT plays really nicely with Node's callback structure. Here's a demo of the magnetic switch component in action.
Okay, now let's talk about my favorite component, the load cells. The load cells work basically like any bathroom scale you may have at home. The load cells are responsible for converting the pressure placed on them into a digital weight measurement I can read on the Raspberry Pi. I start by taking the base weight of the litter box. Then, I wait for the weight of something that is approximately cat-sized to be added to the base weight of the box and take the cat's weight. Once the cat leaves the box, I then recalibrate the base weight of the box. I also recalibrate the base weight after every time the lid is taken off in order to account for events like the box being cleaned or having more litter added to the box.
In regards to the code for reading data from the load cells, things were kind of tricky. This is because the load cells are not directly compatible with Johnny-Five. I was, however, able to find a Python library that can interact with the HX711 load cells.
In order to use this code, I had to make use of Node's Spawn Child Process API. The child process API is responsible for spinning up the Python process on a separate thread. Here's what that looks like.
This was the first time I have played around with the Spawn Child Process API from Node. Personally, I was really impressed by how easy it was to use and troubleshoot. It's not the most elegant solution, but it totally works for my project and it uses some cool features of Node. Let's take a look at what the load cells look like in action. In the video below, you can see how pressure placed on the load cells is registered as a weight measurement from the Raspberry Pi.
Okay, so as a software engineer at MongoDB, I would be remiss if I didn't talk about what to do with all of the data from this IoT device. For my IoT Litter Box, I am saving all of the data in a fully managed database service on MongoDB Atlas. Here's how I connected the litter box to the MongoDB Atlas database.
There are a lot of places to store your IoT data these days, so I want to talk about what you should look for when you are evaluating data platforms.
First thing when selecting a database for your IoT project, you need to ensure that you database is able to handle a massive amount of concurrent writes. Most IoT architectures are write-heavy, meaning that you are writing more data to your database then reading from it. Let's say that I decide to start mass manufacturing and selling my IoT Kitty Litter Boxes. Once I deploy a couple of thousand boxes in the wild, my database could potentially have a massive amount of concurrent writes if all of the cats go to the bathroom at the same time! That's going to be a lot of incoming data my database will need to handle!
You should also consider a database that is able to handle a flexible schema. This is because it is common to either add or upgrade sensors on an IoT device. For example, on my litter box, I was able to easily update my schema to add the switch data when I decided to start tracking how often the box gets cleaned.
Lastly, you will want to select a database that natively handles time series data. Consider how your data will be used. For most IoT projects, the data will be collected, analyzed, and visualized on a graph or chart over time. For my IoT Litter Box, my database schema looks like the following.
What's next? Well, if I have inspired you to get started on your own IoT project, I say, "Go for it!" Pick out a project, even if it's "crappy," and build it. Google as you go, and make mistakes. I think it's the best way to learn. I hereby give you permission to make stupid stuff just for you, something to help you learn and grow as a human being and a software engineer.
When you're ready to build your own IoT device, check out MongoDB Atlas, MongoDB's fully managed database-as-a-service. Atlas is the easiest way to get started with MongoDB and has a generous, forever-free tier.
Check out the following resources for more information: