Hybrid local/cloud style home automation

When I first started automating items in my home I used a local (“on-prem” if you like) point solution for security lighting. This had a connection to an internet service (Google Calendar) but only in a “pull” manner, and only for that specific use-case. As time went on I wanted to enable a broader set of use-cases, some of which required other internet-connected services in both pull and push directions. I experimented with using Octoblu, with the local LightwaveRF controller being connected to it – all the automation therefore was being performed in the cloud. As I looked at adding additional devices (PIR detectors, reed switches, IR blasters, and so on) I encountered a number of failures and delays caused by this reliance on my domestic internet connection and the (at the time) patchy reliability of Octoblu (it’s far more solid now).

My solution was to use a “hybrid” model with a local message broker and set of services running inside the home, and a connection to Octoblu for cases when external services were involved. Overall this means that truly local operations, such as PIRs turning on lights depending on the position of various reed switches, can be kept within my home network with no reliance on my internet connection or any external service. In cases where external stimuli are used (e.g. for connecting Amazon Echo’s smart home stuff) or external actions are required (e.g. sending a text message using Twilio) the bridge between the two worlds allows a message to be forwarded in either direction.

The on-prem piece

homeautopiThe local system is based on a MQTT broker running on a Raspberry Pi. This provides a publish-subscribe messaging system that various services connect to. The broker and many of the services run on the same Raspberry Pi however the broker also listens on a TCP port to allow other Raspberry Pis (and potentially other devices) in the home to join the party. I also have a Redis key-value-pair (KVP) store which is used to store state such as presence information or whether it’s day or night.

As an illustration of how the system is used: the LightwaveRF radio-controlled lighting system is connected via a small node.js service that subscribes to lighting messages (e.g. “Light/Kitchen/Main=on“) and sends the appropriate command to the local LightwaveRF hub which then emits the 433MHz radio command. When I later added a Philips Hue system alongside the LightwaveRF one I created a similar node.js service that also subscribes to lighting messages and makes calls to the Hue hub’s API as necessary. In both cases the services ignore messages about lights they don’t control. This all means other services, such as the PIR detector, or the rules engine, can simply publish a lighting control message without worrying about whether it’s a LightwaveRF, Hue, or (perhaps in the future) other system managed locally or via a cloud service.

Other services that publish and/or subscribe to MQTT messages include:

  • A Bluetooth Low Energy (BLE) advertisement monitor – this is used to determine the presence of absence of various things
  • A Google calendar interface that can update local KVP state, or generate messages, based on scheduled events
  • A GPIO service that enables things like PIRs and push buttons to be attached to Raspberry Pis
  • A timer service that other services and rules can use to provide timeouts, e.g. to turn off PIR-controlled lights after a set delay
  • Plug-ins for the Kodi media player to control Kodi itself as well as IR emitters for nearby TVs and other devices (stay tuned for a blog post on this)

homeautoruleA core part of the whole system is the rules engine. This is a service that subscribes to MQTT messages, implements rules, and publishes MQTT messages as necessary. It doesn’t directly interface to any device. An example of a rule is managing lighting for the basement stairs: inputs to the rule are two PIRs (via the GPIO service), the value of the day/night KVP, and the timeout message from a named timer (from the timer service). If a PIR triggers and it is night (from the KVP) then a lighting message (“Light/Stairs/Basement=on“) is published; when the PIR stops detecting, a timer control message is published (“Timer/basement_stairs_lighting/reset=<time in 60s>“) to start the timer; receipt of the timer’s timeout message causes the rule to emit an “off” lighting message.

The Octoblu bridge

homeautodiagram

So, what if I want to control stuff in the home from somewhere else? Or if I need to send a message to a cloud-connected device or service? That’s where the Octoblu connector comes in. I built a basic connector that runs as a node.js service on the main MQTT Raspberry Pi. This subscribes to a subset of MQTT topics and has the ability to publish arbitrary messages into the on-prem system. It also acts as an Octoblu connector, maintaining a bidirectional connection into Octoblu. This allows my entire home automation world to appear as a thing in Octoblu so I can send messages to it, which leads to MQTT published messages, and receive messages from it, which came from MQTT subscribed messages.

As an example, I can remote-control a light using a button on a web page by connecting an Octoblu “trigger” (a thing that can respond to a HTTPS POST and then emit a message into the Octoblu platform) to the home automation thing, and ensure the message payload includes the right MQTT topic (e.g. “Light/Kitchen/Main“) and message (e.g. “on“). The connector routes this message into my home as a published MQTT message that the LightwaveRF or Hue service will act on. This is the core mechanism I used when connecting my home lighting up to Amazon Echo using an Alexa smart home skill adapter.

In the other direction an on-prem service, such as the rules engine, can send a message to Octoblu just by publishing to a suitable topic (currently this means it has a “Octoblu/” prefix) via the local MQTT broker. An example of this is a security feature that sends me a text message if a particular combination of stimuli are seen. The rules engine publishes a message “Octoblu/alert/<detail>=<status>“, the Octoblu connector receives this via its MQTT subscription and sends it into Octoblu. The Octoblu flow then decides how to process this message which may end up with a call to the Twilio thing to send a text message.

Other examples of using the Octoblu connection include:

  • Sending events for sunrise and sunset, based on pulling data from a weather API (saves having to drill walls to install a light sensor)
  • Routing messages from Alexa skills handlers (these run in the cloud as AWS Lambda functions so I need a way to route the message back across my firewall)

In closing

I’ve ended up with a hybrid-cloud style of IoT management for my home automation, not by design, but by evolution. I find that being able to combine local automation – with its low latency and lack of reliance on external connectivity and services, with a powerful cloud-based automation platform able to send and receive from a variety of cloud/internet services, is a best-of-both-worlds solution.

homeautooctoblu

Using LightwaveRF switches to control other stuff

img_9028I’ve been using LightwaveRF‘s range of wirelessly controlled lighting and power outlets for some time and I’ve built up a collection of switches and remote controls for them. These switches broadcast control messages, formed of a command (e.g. on/off) and a unique identifier for the transmitter, using a simple on-off keying modulation on 433.92MHz with each light fitting or other device being “paired” to one or more transmitters. In reality the pairing is actually just telling the device which command(s) to respond too – the transmitter units can’t receive anything which prevents a bidirectional pairing. This all runs in parallel with the LightwaveRF network bridge which is really just an IP-controlled 433.92Mhz transmitter.

With my home automation system now growing to include Philips Hue and various homemade devices I’d like the LightwaveRF switches and remote controls to be able to control more than just LightwaveRF devices which means taking them our of their constrainted world of 433.92MHz. To do this I am building a set of 433.92MHz receivers to forward the command messages to my MQTT broker. This means I can extend my existing set of automation rules to react to the LWRF switch commands by, for example, sending a command to the Hue Hub to control a Hue light. I can also build up more complex operations with other rules such as only performing certain actions outside of daylight hours, or controlling multiple devices at the same. This also allows for more interesting control of the LightwaveRF devices themselves because I can now insert rules between the transmitter and receiver simply by not pairing the device with the transmitter and instead routing everything through the MQTT world and the LightwaveRF network bridge.

img_9021The prototype is based on three main components:

  1. A 433.92MHz receiver – I’m using a cheap one from Amazon. This has a 17.3cm wire antenna soldered on to it.
  2. An Arduino Uno R3 to handle the demodulation of the on-off keying and the protocol decoding.
  3. An existing Raspberry Pi to forward the decoded messages from the Arduino to the MQTT broker.

Why the separate Arduino? That’s because I don’t then have to worry about responsiveness of the decoding software if it was to be running on a Raspberry Pi alongside other stuff – some of which may also be latency sensitive.

There is plenty of material online (see the resources below) about the LightwaveRF protocol. I found that none of the existing code (at least what I could find) worked in the way I wanted so I implemented a decoder from scratch using the various online protocol resources as guides.The decoder, running on the Arduino, is formed of three main pieces. Firstly a demodulator that looks for state changes on the data coming from the 433.92MHz receiver. This then feeds the demodulated bits into the main protocol decoder which looks for the message start bit, each byte’s start bit, and a valid pattern for the byte (which is a form of 4b8b encoding). The final piece kicks in once the transmission has ceased for 25ms: the buffered received data is de-duplicated and for each unique message a MQTT message is sent over the serial port (via USB).

The format of the MQTT message is topic=”LWRF433/<unitID>/<channel>”, message=”<command 0=on,1=off>|<level>”, where:

  • <unitID> is the unique 3 byte identifier for the switch unit
  • <channel> is the channel number, the meaning of which varies across the different type of switches
  • <command> and <level> tell the light what to do and vary depending on whether the controlling switch is a simple switch, dimmer, or mood switch.

lwrfmqtt

The initial prototype is connected to an existing Raspberry Pi running LibreELEC/Kodi as a media centre. The Arduino is connected to a USB port on this Pi. The function of the Pi is simply to forward MQTT messages received over the USB serial port from the Arduino to the house MQTT broker. To do this in the LibreELEC/Kodi environment is a little trickier than in a general Linux/Raspbian environment due to the locked-down, read-only nature of the LibreELEC distribution. However the Kodi add-on mechanism provides a reliable way to do this.

20161009_170439I created a Kodi add-on formed of two main parts. Firstly a Python script that acts as the main forwarding loop between the USB serial port and the MQTT broker. This is based on code from a previous, albeit standalone, proxy doing largely the same thing – it includes a device scanning function to watch for Arduino devices appearing and to fire up proxy threads for each one – this was originally done to avoid static configuration and to allow for hot-plugging of new Arduino devices (this was in a far more complex, multi-Arduino system, compared to this simple case).

The second part of the Kodi add-on is really just boilerplate and plumbing to kick off this script.

So putting it all together this is how it works:

  1. A button is pushed on a LightwaveRF switch, this sends a message (actually a burst of several) on 433.92MHz.
  2. The 433.92MHz receiver module receives these messages and passes the raw data to the Arduino.
  3. The software on the Arduino decodes the messages, de-duplicates and sends one or more MQTT messages over the USB serial port.
  4. The proxy script running on the Kodi Pi forwards the MQTT message(s) to the MQTT broker.
  5. Part of my MQTT rules engine is subscribed to LWRF433 messages and receives the message(s). After debouncing, the relevant rule is invoked, e.g. sending a separate MQTT message to control a Hue light.

 

The initial use-case is to use the LightwaveRF remote control to turn off the room lights, pause whatever the media centre is playing, and turn off the TV, all with a single button push. To do this I created a rule that on receipt of the appropriate LWRF command via MQTT sends out two more MQTT messages, one to turn off the TV and one to pause Kodi. Both of these are handled by a separate add-on running on the same Kodi Pi, but that piece of functionality is completely separate to the LWRF add-on described above and is the subject of a future blog. The room lights turn off directly in response to the LightwaveRF 433MHz command without any MQTT infrastructure being used.

lwrfrule

Resources:

Getting started with home automation

20160908_195003I’ve always had an interest in electronics and software, and in connecting the two together. I guess it started in my pre-teen years when I figured out I could use the cassette motor relay on my family’s BBC Micro to turn LEDs and buzzers on and off, and it grew as I learned to use the BBC’s 8 bit “user port” with more sophisticated electronics. I’ve used a variety of technologies and gadgets over the years, including various microcontrollers (PIC in particular) accessed via serial (RS232 or RS423), Elexol’s USBIO24 GPIO devices and, more recently, various Arduino and Raspberry Pi models. I’ve built a number of different things such as controls and displays for my flight simulator, computer control and feedback interfaces for my model railway, and miscellaneous gadgets of varying levels of utility. But until recently an area I’ve not explored is home automation – a topic well aligned with my experience and interests. That changed about 4 years ago when the problem of needing landlord permission to run cables and drill holes disappeared and I became a homeowner.

Like most people who venture into home automation my starting point (and mostly still the extent of my experience) was lighting. The automation of lights is both relatively straightforward and safe – there are no moving items under control of my software so no bug can lead to overheated motors or physical damage.

20160908_185431A decade ago I’d probably have started by buying a bunch of relays or triacs and working back from that (in fact I still have a device much like this that I fear to plug in) however I decided that it was time to leave the mains voltage to the professionals and concentrate on the low voltage stuff and the software. When I looked around for suitable hardware I was particularly impressed by the LightwaveRF range. The core of the range is a set of dimmers and relays in various form-factors including inline (which for the light switch types mean they need a leakage current through the lights to power them – something I’m not keen on) and plug-in units. All the dimmers and relays are controlled by 433MHz RF, either locally from handheld remotes or wall-mounted buttons, or via the network using an Ethernet to RF bridge (called a “Wi-Fi Link” despite having no Wi-Fi capability!).

20160908_185332The “Wi-Fi link” is designed to be used with LightwaveRF’s cloud service to enable control of the lights from mobile apps or via REST APIs. However, it can also be used directly by sending suitably formatted UDP packets to it.

When I first started using LightwaveRF my priority was to use the system to replace timer-based security lights simulating occupation while away from home. I initially started with Paul Clarke’s excellent “lightwaverf” tool which can drive the Wi-Fi Link from either command line invocations or from events in a Google calendar. I ran this tool on an early-model Raspberry Pi sitting in the cellar. I coupled this with an IFTTT recipe that runs daily and populates a dedicated Google calendar with a sunset event which was the basis for triggering the switching on of some of house lights.

20160908_185404This was all fine until Google withdrew the ability to share a calendar privately as an XML download. This was the motivation to build a more flexible system that would enable more use-cases for automatic light control (these will be the subject of future blogs). I looked at using Octoblu, an IoT automation platform acquired by Citrix. It didn’t have support for LightwaveRF but I did end up building a simple gateway to allow me to use the two technologies together. More importantly it was, at the time, not particularly stable (it’s much better now) so I ended up building a local MQTT-based system with a bunch of individual services connected via the MQTT broker (all running on the same Raspberry Pi as the previous system). One of these services is the LightwaveRF service which subscribes to messages about light controls and sends the appropriate UDP commands to the LightwaveRF Wi-Fi Link device (turns out there’s a NPM library for this). Another service is the calendar service which uses the Google calendar APIs to regularly pull down the same automation events as I was using with the previous system, but this time using my Google account and an API key, thus avoiding the problem of the missing private XML calendar. This service then issues lighting control command via messages published to the MQTT broker. By adopting the same calendar format as used previously I was able to continue to use the IFTTT recipe to populate the sunset events and enable/disable the security lights based on my travel plans

I’ve since added more services to the MQTT environment enabling more lighting automation use-cases – keep an eye out for more blog posts on these in the future.