Those who know me know that I love gadgets, and more than that, I love writing code for gadgets. I have used Internet of Things before it was called like that (IoT). My biggest gadget is my home. I have a home automation system based on EIB/KNX technology. The nice thing about this technology is that there is no central processing unit. Many home automation systems are based on a central PLC that controls the house. In EIB/KNX, each device is connected to a bus. The device is actually a tiny computer that has its own physical and logical bus address and that can issue or listen to bus commands. When I press a wall panel button to turn on the light, this button sends a command telling to an actuator that listens to this command, to turn on the light. Each actuator can listen to several different addresses and act upon them. For example it can listen to its own private address, or to a group address that all actuators on the floor listen to (to turn off all the lights in that floor), or another group address that belongs to all light devices in the house. An actuator can execute a simple or a complex command, for example setting the light state requires only one-bit value, but setting a dimmer or a shutter position needs a byte.
Some of the devices have additional logic capabilities that allow executing a sequence of commands (for running scenarios such as light and shutter settings when leaving the house or when watching a movie).
A computer can be connected to the EIB/KNX bus using special devices such as USB/Serial or IP Gateways. In many cases, the computer is only used to program bus devices, however having a computer as part of the system enables much more complex scenarios, those that a PLC can do and much more. I use a computer to implement these scenarios:
1. Turning the boiler on, according to the current weather, using a forecast web service
2. Turning the garden lights on at sunset
3. Raising the shutters in the morning, and close them at midnight
4. Turn off all garden lights at midnight
5. provide statistics about the usage of controlled electrical devices
6. Provide a vacation mode to keep away thieves
7. Have a web/Windows/Phone remote control app
I started my project in 2004, and I use an Atom based machine to host it. The old project was built using ASP.Net ASMX services, C++/CLI wrapper on top of EIB Falcon COM object, an Executable that was used to call the web service from within the Windows Task Scheduler and a Media Center application that allowed me to control my home from my TV.
I decided that now it is a good time to create my Home Automation 2.0 project, this time with new Microsoft technologies.
The new architecture is based on a classical layer architecture. The server side has a device access layer, a business logic layer and a service layer, which is based on ASP.NET MVC Web API.
There are several clients. The main client is the Windows 8.1 and Windows Phone 8.1 Universal app that communicate with the server side through the RESTful web interface. There are two other clients that enable executing bus commads from the Windows Task Scheduler, and a bridge DLL that supports my old Windows Media Center application (built as .NET 2.0 assembly) as well as my Boiler setter, which is based on the forecast application.
Falcon COM Object
Connecting to the EIB/KNX Bus, send telegrams and listen to bus events
An access layer that:
1. Handle bus connections
2. Transform .NET commands to bus telegrams and vice versa
3. Provide bus events as .NET events
4. Map Falcon COM error to .NET exceptions with meaningful messages
Instead of having C++/CLI layer, I used the Falcon PIA. I also use the new syntax to connect to the bus. Since my developer machine has a USB gateway and my Atom runtime machine uses Serial connection I created a code segment that tries to connect to the bus first using COM and then using USB:
FalconWrapper Main interface:
Hosted as part of the service in IIS – the main server logic layer
1. Provide devices metadata such as addresses and capabilities
2. Provide device-building map, i.e. devices by rooms, levels, and home
3. Provide device real-time status data
4. Handle device commands
5. Handle scheduler commands
The main interface:
The layer provides three types of functions, a home device topology functions (“DNS”), EIB/KNX bus related functions, and a task scheduler related functions.
Implementing the “DNS” functions:
I built a DOM that describes the home device topology using LINQ to XML based set of queries from an embedded resource XML file:
At initialization time, The DOM is built from the above XML file:
The building has number of levels. Each level has rooms. Each room has a list of devices, and each device has a list of EIB Actions. EIB Action has the EIB device address, the current device value, the last device value update time and if this value is valid. When the application gets a BUS event – for example when I turn on the light using the wall panel, the application searches the DOM for the bus command EIB address. This address might belong to a single device, or effect the whole room, level or home. According to the Effect value of this address, I invalidate all affected devices. When a client needs to get the device info, and the value is invalid, the application issues an EIB bus read telegram.
Having the DOM ready, a simple LINQ query provides the DNS information:
The Business logic layer:
The Accessor layer:
Implementing the EIB telegram functions:
Sending a telegram is implemented by calling the EIB Falcon Wrapper:
Implementing the Scheduler functions:
To have a bus command set to be executed in the future, I use the Windows Task Scheduler.The Windows Task Scheduler executes code that calls the REST service. When I set the schedule task, I save the command parameters. When the Task Scheduler executes the command it passes those parameters and the code calls the Home Automation Service. I have two different tasks. To enable my “old” 2004 boiler control client, I use an executable that gets the telegram data (boiler address and data) in its command line arguments. The executable is a simple REST client:
For implementing the new task scheduling command, I use an Enterprise Service COM object that implements the ITaskHandler, to spare the need to run an external executable. This object is signed, GAC installed and regsvcs registered. This is the simplest way to implement ITaskHandler in .NET. For more information look at this project.
In the server, I use the Task Scheduler COM interface API to set the future task. I also provide an interface to query and delete future commands. Later when I will write about the client app, I will show how the client manages future tasks:
The Scheduler code:
The REST service ASP.NET MVC app:
a. I have implemented the AuthorizationFilterAttribute to support simple ApiKey based security, when using with https, I have client app authentication and authorization
Turning on the light using the Test Page:
Get the Device Info:
In the next blog post I will write about the client side – the Windows 8.1 Universal App!