For my inaugural post, I thought I'd share one of my favorite recent-ish projects: my automated doorbell notification system.
For the past couple of years, I've been getting pretty heavily into home automation. I use a system that implements one of the main automation standards, called Z-Wave. The core of my system is a little box called VeraLite which is basically just a small computer running a stripped-down version of Linux. It hooks into your home network but also speaks the proprietary Z-Wave radio protocol to all the Z-Wave enabled devices in the house (door sensors, light switches, garage door opener, etc) which together form a "mesh network". Pretty cool stuff.
Anyway, I realized that, after building my very-well-soundproofed basement theater (which will be detailed in a series of posts at a later date), when I was down there I couldn't hear the doorbell when it rang.
I ask you: what is the point of watching the big game in your ultimate man cave if you can't hear it when the pizza delivery kid rings the doorbell?
Enter home automation.
My first thought was to simply buy a Z-Wave compliant doorbell and call it a day. Problem was, there didn't seem to be such a device on the market (this was about a year ago, I now see there are products like this one available).
So I decided to make my own.
My first thought was to use a Raspberry Pi to wire up something fancy. I had been looking for an excuse to play around with one of them for a while and this seemed like a great project for it. Only problem was, there was no way to power the Pi near where the wires that came off the doorbell transformer terminated, ie. at my doorbell, which is mounted in a hallway 6 feet off the ground.
Technically, in the hole-in-the-wall behind the doorbell where the wires attached to the actual bell unit, there was an electrical conduit which fed a bathroom on the other side of the wall, but I eventually had to admit that my meager electrical skills were not up to the task of cutting into a conduit and splicing in power for a small computer embedded in the wall.
Moving on from that near-disaster, I remembered that a standard Z-Wave door sensor, which triggers open/close events whenever a magnet gets close enough to or far enough away from the sensor, can also be triggered by cracking open the unit and connecting or disconnecting two contact points inside it. This means that an electrical signal, like one from a button being pressed, can fire events! Here's a picture of what I'm talking about on the sensor side:
When the two wires touch, the sensor fires an event saying the door is closed. If they're not touching, the door is considered open. Of course, a doorbell isn't a door, but an event that says the door is closed in this case could be interpreted to mean the doorbell had been rung. All I had to do was get the signal that the doorbell button had been pressed to complete this circuit, and then my VeraLite would know about it and it could alert me however I wanted it to that someone was at the door, namely on my phone as well as other places (more on this in Part 2).
The next step was to get the signal from the wires leading from the doorbell button to affect the sensor. Talking this over with some coworkers who are much smarter than I am, I learned that to do that, you need a device called a relay. Here's the one I bought:
This one can technically open or close two circuits at once, even though I only needed one. The two leads on the bottom (7 and 8) connect to the power supply, and when a current is applied, the relay opens or closes a circuit (depending on how you wire it) on leads 1, 3, and 5 as well as on 2, 4 and 6. It's actually much simpler than it sounds. I started experimenting with configurations, resulting in abominations like this:
It actually kind of worked, but I soon faced a problem: there was only enough current in the line coming off the doorbell transformer (the red and white wires in the picture above) to trip the relay, or ring the doorbell, but never both. One or the other would work, but never both at the same time. Obviously, to make this project worthwhile in any way, I had to keep the sensor hooked up, but could we live with only getting notifications on our phones when the doorbell was rung? The wife decreed: definitely not.
Then I thought: if I now have an event on the network somewhere that says that someone just pressed the doorbell button, surely I can make use of that information to simulate a doorbell sound somewhere in the house! Who needs an actual bell to be rung these days?
As luck would have it, we have an always-on computer centrally located on our main floor, right in the kitchen. It's an old-as-dirt Mac Mini which we mostly use to run Kodi on, thereby making it the kids' primary TV since they can watch it during meals much to the adults' consternation.
I figured this ought to be easy: just whip up a quick web service that plays a doorbell sound, install it on the Mini, have the VeraLite hit the service's URL, and problem solved!
Warning: Programming Talk Ahead!
That is actually what I ended up doing, sort of. I had been looking for an excuse to use Spring Boot for some kind of personal project, and this was an easy one. Using Spring Boot's crazy easy tutorial, I wrote a quick RESTful service running at on localhost at "/doorbell" and tried to get it running on the Mini. After futzing about for a while, I realized that the Mini was too old to be running Spring Boot applications. My configuration required a fairly new version of Java and the Mini literally couldn't be upgraded any further than it already was, and no version of Java beyond 1.6 was available. Bummer!
Of course the internet has all the answers, so I set my sights on figuring out a way to get a simple microservice running on an older version of Java.
I can now hear many people screaming at me: "Use Python/Ruby/whatever, you moron!" - yes I almost did go the Python route but I ran into some other issues with that along the way (can't remember what they were just now), and in any case I'm not too ashamed to admit my Python skills aren't what they once were.
Turning back to Java, a quick search revealed that there's a little-known class in the Java SDK since Java 6 called, simply enough, HttpServer. It lets you create a very lightweight server without needing an embedded one like Tomcat or Jetty like Spring Boot uses. Using this, I was able to whip up something simple and install it as a service on the Mac, so that the VeraLite could hit the URL it was listening on, and the Mac would instantly raise the volume to 80% of max, play a doorbell sound, and then lower it back to whatever the previous volume setting was. In addition to this, the VeraLite would notify my phone and trigger other notification events - which again are detailed in Part 2.
If you're interested in the source code for playing the doorbell sound, you can grab it here. Not the most complex thing in the world, but the code is clean and it's guaranteed to run on practically any machine.
That's it for now. In Part 2, I'll show you how the whole thing fits together, and how the various notifications work.