Recently I was tempted to add an Amazon Echo Spot to my home automation setup. It has a lot going for it: voice activation, music streaming, calendar highlights and even video calling. What’s not to like?
It’s creepy. That’s what’s not to like.
Lacking any sort of desire to put a camera and microphone in one of the most personal spaces in my home I set out to do things my own way. I wanted to prototype my own bedside assistant that had all of the functionality I required without a creepy microphone listening to my snoring.
I wrote down a short list of the most desirable features for a first attempt:
• On/off control for my bedroom lights
• On/off control of my thermostat
• Temperature control for my thermostat
• The ability to set a wake time for both the lights and the thermostat
It’s worth mentioning that I also made my own thermostat (with on/off switch, but no temperature control) using around £5 worth of parts – something I’ll discuss more in a future article!
Picking my tools
I already had a number of bits and pieces lying around from previous projects and prototypes, so I assembled a short list of what I expected I’d need.
• Raspberry Pi 3As always with prototypes I prefer to stick with the devil I know. Pi 3 may be a little overpowered but it was less limiting
• Waveshare 3.2-inch screenI’d bought one of these a while ago for a similar project that never quite came to fruition.
• All-in-one caseOne of Banggood’s finest! I snapped part of it within about 10 minutes of getting it but it all stayed together once the pi and screen were in place.
With all the pieces assembled and Raspbian installed – thanks to the excellent PiBakery, which I cannot recommend enough – I started to consider software options.
The Pi 3 is fairly powerful and it felt a shame not to use some of that power for the UI … so I decided to write a web app using React!
I should mention that this was pure self-induldgence and gave little thought to stability or performance. Plus, it’s my prototype … if you don’t like it go and stand in line for a Qt license 😛
I used Facebook’s excellent create-react-app tool to bootstrap a deployable app and started coding.
Designing a UI
I’d already kind of decided that my UI was going to have an 8 bit feel to it, so I started looking for some pre-existing controls I could pilfer. I found some in a neat JSFiddle here that fitted the bill.
For all it’s flaws, one benefit to using a web app was that I had a wide choice of approaches to layout. With the screen being so small (320×240 resolution in 3.2 inches!), I opted for the flexbox model.
Flexbox made sense because it’s designed to work largely with layout axes and size ratios, rather than classical pixel based layouts. Working with a small screen, I wanted to just throw everything in and be able to rearrange quickly if it didn’t fit. Having tried to do this with CSS and old style box and border-box layouts in the past, I wasn’t keen to make the same mistake again.
I added three columns to the design with a JS controller class for each (in order): Lights, Main, and Thermostat.
I added some buttons and text and had a reasonably responsive UI in under an hour. It looks like this:
It’s hardly modern art but it does the job and has that retro feel that I wanted.
Connecting the dots
Pretty Uis are all good and well but it needed to connect to something. I initially thought about creating a small proxy server to live alongside the react server on the Pi, but this seemed like a bigger job than I wanted to take on – plus, eventually I knew I’d need two of these devices so any server would need to live somewhere accessible by both.
Thankfully I was able to avoid this entirely thanks to two facts:
1. I was using Phillips Hue lights and the Hue Hub comes with it’s own API with an open CORS policy. Thanks Phillips!
2. My thermostat was running on a small Arduino ESP8266 – the simple server running on there seemingly doesn’t know what CORS or access policies are – er, thanks Arduino?
Glaring security risks aside (this is all contained within my home network with no external exposure), I was able to write some simple JS services to turn my lights and thermostat on and off.
Automation means automatic
Pressing buttons doesn’t really scream “automation”.
To make things more reactive I wanted to allow the heating to turn on using a schedule (the lights already do this via the Hue app). I put together a small utility for scheduling at a given time using the setInterval function.
The utility does a couple of things: caches the token for any interval against a string and ensures that only one active callback exists for that interval; and converts the hour/minute inputs to a millisecond offset from the current time (which is what setInterval/setTimeout expect)
Honestly, I haven’t really tested this very thoroughly in real life but my jerry-rigged test harness showed that it seemed to work fine.
Finally I added some setInterval calls with hard-coded timeouts of around 30 seconds to fetch the most recent state of the lights and thermostat so they didn’t become too out of sync.
Is it ugly? Sure; does the screen look like a Gameboy Color? Absolutely. But, does it voyeuristically listen in on you and your significant other whispering sweet nothing to each other in the night? Nope!
It’s not without its share of issues and rough edges but it’s wholeheartedly my own digital minion and not Amazon’s, Google’s or anyone else’s!
• Kill the backlight – the waveshare light is always on and seems to be embedded in the internal circuitry rather than exposed via pin (which is weird because it connects to the entirity of the Pi header). It looks like either the LED will need to be desoldered, or I’ll need to start looking at alternative screens.
• Web hooks server – the Hue API doesn’t provide anything reactive for getting light states (e.g. notifications), so I’ll eventually need an alternatively way to manage them. At the moment I’m thinking a server that sits entirely in front of the API but this requires a lot of work as well as some changes in how we use our lights (i.e. abandoning the Hue app).
• Per-day scheduler – a single screen app is easier to maintain but it would be nice to set the start time per day, as well as introducing a configurable end time. This is the task I’m keenest to do next as It means playing with React and SASS more!
• Time/weather based backgrounds – because why not? 😆
That’s all folks!