“Gentlemen, I am now about to send a signal from this laptop through our local ISP, racing down fibre-optic cable at the speed of light to San Francisco, bouncing off a satellite in geosynchronous orbit to Lisbon, Portugal, where the data packets will be handed off to submerged transatlantic cables terminating in Halifax, Nova-Scotia, and transferred across the continent via microwave relays back to our ISP and the X10 receiver attached to this (clicks mouse, lamp switches on) lamp.” – Howard Wolowitz.
Ok, hopefully my home automation system doesn’t traverse quite as many network links but since the move to Amsterdam and the connection of the Amsterdam and Sydney home automation systems to each other, you never know…
As you can probably tell from some of the other posts here, I’ve created a home automation system. Why you ask…. Well, firstly – I’m a geek that really enjoys software development – and I can’t stress enough how significant a factor that is in my decision to create a home automation system. Secondly, many of the home devices I have could not be automated with off the shelf systems, and thirdly – those off the shelf systems didn’t really exist when I started all of this. I keep doing it now for the immense satisfaction it gives me, and I get to learn a lot along the way.
The system is predominately written in C# using the .NET 4.5.1 framework. At present the system is controllable through a mobile phone interface and through speech control. The system is decentralised and uses a message bus for communication between components. The system has components hosted in Sydney and components hosted in Amsterdam, with each location running it’s own independent hub/core – that can manage components in the other site if necessary. The web interface is available globally, but has an instance hosted in Sydney and an instance hosted in Amsterdam – and they both have the same functionality/look & feel. Either interface can control the entire system.
I’ve included a high level architecture diagram below, and will describe the components and functionality further down.
Web Interface (ASP.NET 4.5 Web Application)
The web interface has a stylesheet set optimised for mobile phones. It uses WCF (Windows Communication Framework) API via SOAP/XML/HTTPS to communicate to the Hub/Core service.
Hub/Core (C#/.NET 4.5.1 Windows Service)
This is where most of the functionality started before the system became decentralised and most of the code moved out to the other components. Now the hub/core is responsible for system health – monitoring and service restoration. I wasn’t quite crazy enough to implement an incident/problem/change/configuration system for it…. yet, but it does at least monitor the health of the entire system – and where it can, restore service. The hub/core also runs the task scheduler for site local automated tasks – e.g. automated control of lighting, temperature, irrigation etc.
Message Bus (Microsoft Message Queue)
The message bus is based on the Microsoft Message Queue (MSMQ) component provided with Windows Server 2012 R2. As the blue components in the diagram are spread out over several virtual machines across several countries, the MSMQ component is located with each virtual machine hosting part of the home automation system. When I moved to a decentralised architecture this helped decouple the various components and functions.
Event Log (C#/.NET 4.5.1 Windows Service/SQL Server 2014)
This component captures all of the events within each country/site. Examples of events include the on/off action of the air conditioner; zone on/off of the irrigation (sprinklers); on/off of power switches; garage door open/close; alarm arm/disarm etc. It also captures network related events – e.g. loss of connectivity between sites; router configuration change; or the presence of an unexpected device on the network. Some of that information comes in via syslog. All of this information is written to a local SQL database, which is replicated between sites in a multi-master configuration – all sites can read/write independently.
Power (C#/.NET 4.5.1 Windows Service/Arduino Custom Device)
The power component manages interaction with a custom Arduino based hardware device I’ve built – well, I wrote the software and my father built the hardware device – for controlling AC power switches. This is currently used to remotely control a battery charger connected to my car in Sydney.
Weather (C#/.NET 4.5.1 Windows Service/Weather Station Device)
I purchased a weather station device from Jaycar, which has an outdoor unit and an indoor unit – the indoor unit connecting to the home server via USB. The weather station comes with an application that communicates with the indoor unit through USB and records the weather readings to a local access database. The weather component launches the supplied weather application as a child process, keeps an eye on it, and periodically reads from the access database. This weather data is used by the hub/core to determine if it should skip watering for that day due to inclement weather. Ah, technology.
Lighting (C#/.NET 4.5.1 Windows Service/LIFX Wireless Light Bulbs)
The lighting component communicates with the various LIFX light bulbs using the LIFX proprietary binary communication protocol. This component also provides its own additional lighting features, e.g. fade in/out, candle mode. I haven’t quite taught this service to automatically manage the firmware levels of the light bulbs yet, but there’s still time…
Air Conditioner (C#/.NET 4.5.1 Windows Service/ASP.NET 4.5 Web Application/ActronConnect Module/Actron Air Conditioner)
This one is a little more tricky. The Actron Air Conditioner uses an ActronConnect module to connect the air conditioner to the home wireless network. I then use some custom local DNS entries to trick the ActronConnect into communicating with one of my servers instead of their cloud server – for many reasons I won’t get into here. I then use ASP.NET routing to impersonate the cloud web service. The ASP.NET web application then communicates via WCF SOAP/XML/HTTPS to the air conditioner component service. Basically it means my service has complete control over the air conditioner, but the air conditioner is none the wiser. It also disconnects my air conditioner from the cloud service so that it can only be controlled by the home automation system and the wall panels.
Alarm (C#/.NET 4.5.1 Windows Service/Networx NX-4 Alarm/Arduino Custom Device)
Related posts: here.
The NX-4 Alarm has a network module of its own and a very useless/clunky web interface. As such, the alarm component service acts as an interface to that web interface – the component authenticates to and executes actions via HTTPS through the web interface. However, due to the unreliability of the web interface to accurately reflect logging data, I’ve built an Arduino device that actually pulls sensor readings directly from the alarm sensors around the house. When the Arduino device detects a change in the status of any of the zone sensors, it immediately sends an event message back to the alarm component service. Therefore I receive events immediately when one of the sensors detects movement. I then use this information at the hub/core to trigger movement based lighting.
Garage (C#/.NET 4.5.1 Windows Service/Arduino Custom Device/Gliderol Garage Door Controller)
The garage component communicates with an Arduino device I’ve built that interfaces with the garage door controller, and several magnetic sensors used to determine the status of the garage door (open, closed, in between). This Arduino device also generates events when the status of the garage door changes.
Irrigation (C#/.NET 4.5.1 Windows Service/Arduino Custom Device)
The irrigation component communicates with an Arduino device that my father and I worked on. This Arduino device controls four solenoids connected to a set of lawn sprinklers. This allows for remote control of the four different sprinkler zones. Whilst the Arduino device simply responds to commands from the irrigation component, it does have a fail safe built in – so that if it doesn’t receive a zone off command within a certain period of time then it turns the sprinklers off by itself (and sends an event to the service – assuming its available).
Ceiling Fans (C#/.NET 4.5.1 Windows Service/Arduino Custom Device)
This is probably the least sophisticated part of the home automation system. We have remote controlled ceiling fans/lights in many rooms of the house. They all use the same model remote control, but each ceiling fan/remote control pair uses a different DIP switch setting to identify them. For simplicity, I disassembled one of the remote controls and built an Arduino circuit around it. As such, my Arduino device actually controls a single remote control – including the DIP switch setting. Therefore the ceiling fan component can – using one single device – independently control the ceiling fan power/speed and lighting across all of the rooms. The only down side is the lack of status reporting – the ceiling fan remotes don’t know if the fan is actually on or off. Whilst I understand this is a limitation I need to live with, the pedantic obsessive-compulsive part of my personality is pretty unhappy about it. Future Mike’s problem though.
iTunes Control (C#/.NET 4.5.1 Windows Service/iTunes Application/Apple TV Devices)
Related post: here.
This is probably the most complex part of the home automation system. We use Apple TV devices for streaming our legally acquired media – TV/Movies/Music to the TVs. Whilst we really like the Apple TVs, the fact that they really need iTunes as the server product is still a little frustrating. There are other devices that can act as an iTunes server, but never with as much functionality – especially when you’re using the iTunes store for purchasing media. The key issue here is that Apple doesn’t actually make an iTunes server product – simply a desktop application that could not find more excuses to randomly popup a user interface prompt if it tried. This really doesn’t lend itself to trying to use it as a headless server application.
Nonetheless, we do. The iTunes Control component runs as a Windows service and launches the iTunes process in the background. It monitors the messages flowing through the application (the method of communicating user interface information in a Win32 type application). With these messages it can detect when iTunes is unhelpfully telling you that your server doesn’t have an audio card, and then respond by simulating the ‘OK’ button click. It does this for the relentless upgrade messages, the lack of audio card message, the lack of a decent video card message – etc, etc, etc. I’ll publish the code for that later – as it’s a problem a lot of people have tried to fix. Anyway, this service allows iTunes to run in the background – without requiring any direct user input.
The service then maintains the media library in iTunes, adding/removing tracks to the library based on their addition/removal from the file system. It does this using DCOM – with the iTunes Type Library supplied with iTunes.
The problem (and of course advantage) with this whole approach is that the iTunes user interface is hidden. That’s great given it’s all running in a virtual machine, but it makes it difficult to edit playlists (a task traditionally performed using the user interface). As such, the home automation web interface now has a UI for creating and maintaining playlists. All of this is again done through DCOM to the running iTunes instance.
With playlist management in place, the last piece of functionality to be added was AirPlay for the Apple TVs. Now, we can use the web interface to tell the iTunes server to play any playlist to any of the TVs (through the Apple TV). This can’t be done unfortunately through DCOM – instead, my component service registers itself with iTunes as a remote control (like the remote control application on the phone), and then sends HTTP commands to the running iTunes instance – enumerating detected AirPlay devices, and changing the target AirPlay device.
All of this bundles together into a single Windows service that completely control the health of the iTunes process, the media library, the playlists and the ability to AirPlay to media devices on the network. Once we coupled that with speech control, it meant the ability to ask the home automation system to play music. It’s not quite as fancy yet as simply saying ‘hey, smooth jazz’, but it does allow you to specify which playlist you want played to which room – and start/stop/track change etc.
Sensor Control (C#/.NET 4.5.1 Windows Service/UWP Windows 10 Application/Raspberry Pi 3 Devices)
Related posts: here.
The sensor control service acts as the hub for the Raspberry Pi devices – some running Windows 10, some running ArchLinux – all with a microphone/speaker attached. These Raspberry Pi devices are currently all in Amsterdam, but were originally in the key rooms around our Sydney house. They allowed you to walk into a room, and ask the home automation system to do something – or simply have a conversation. Some of the speech enabled functionality included ceiling fan, lighting, and air conditioner controls, plus conversations around our daily calendar, the time, or the weather forecast. The sensor control service manages the conversation status in each room – and is aware which room is having the conversation. This was needed so that you could simply ask the home automation system to turn on the light – and have it know which room you were referring to. If there wasn’t a light in that room, then it would ask you to specify the room to which you were referring.
I’m planning on writing more posts about each of these components in the future – this post is more to add context for how all of the components fit together.