The automation engine uses Microsoft .NET and runs on the home hub server providing and orchestrating all the automation services for the user interfaces and plug-ins. This is the most complicated sub-system and runs the following services:
- Message management. Handles the incoming and outgoing messages via a multi-threaded message queue.
- Database management. SQLite is used as the relational data store as it has decent performance and functionality without the need to administer the database.
- State store. Maintains the state of the messages so that message state persist after the message has passed through the message queue.
- Rules module. Every message handled by the central queue is passed through the rules module where the trigger rules are compared and if matched, triggers any associated events.
- Transformation module. Transformations are similar to rule triggers except they apply calculations to the triggered message and act as virtual devices.
- Queries module. Provides the ability to store and execute queries on current and historical data.
- Console. Event logging and debug messages, displayed on the server console or remotely.
Lets have a closer look at the implementation and lessons learnt of a couple of these features not discussed in other logs.
Database and Queries
The SQLite database stores all non system messages in the database as a time-series log (time as the index) using the raw message format. Each message category (eg. Lighting) has its own SQLite file and as the database structure is simple performance is good even with categories with 10's of thousands of messages logged. Database size grows over time - for example polling the solar inverter every 6 seconds for current power generated quickly adds up even if we are only sending messages when the state changes. The relational aspect of SQLite is used for the rules module, where an automation event is associated with triggers and actions, cached in memory when the automation engine starts and edited by the settings function on the HTML5 client.
SQLite has a rich SQL syntax that means queries can be built to answer simple questions like who keeps turning lights on at 3am in the morning, or more complex ones like has the average power increased this month compared to last month. Queries can be run using the current state (from the state store) or historical (from the database) transparently and like transformations can use aggregate time-series functions like average, max and min.
Rules are managed through events, which have associated triggers and run associated actions when fired. Below is an event screen (click for higher resolution), which automates the CBUS lights in my home theater when a CBUS light switch is pressed (triggered by the relevant light switch ON message, then runs actions to manipulate 8 banks of lights to ramp up the lights slowly from the front to the back over 15 seconds - a custom light scene),
The rules module is constantly evaluating new messages for a match against a trigger. Triggers are flexible and can capture state changes as well as date / time changes (eg. sunset, specific time of day or day of week) or both together (to create AND conditions). Below is the trigger record (click for higher resolution) that is listening for the CBUS light switch that the event above uses to fire the lighting scene actions.
Events can associate with multiple triggers to create OR conditionals (activate with any of the triggers firing). Events can also have multiple actions associated with them so actions and triggers can be reused in multiple events.
Triggers are defined by the message taxonomy and wildcards are allowed (eg. trigger on all Lighting messages). Actions either create new messages or run a script. Below is an action record that activates one of the dimmers in my home theater (click for higher resolution).
Transformations are a powerful and unique feature of the automation engine. A transformation will transform raw messages from a plug-in into higher level abstractions by applying user configurable functions to generate new messages, effectively creating a 'virtual' device. While it is possible to do similar by hard coding functions into a plug-in (plug-ins can subscribe to messages as well as publish), transformations do it in a more elegant way by creating transformation rules that are simple to setup and edit. A transformation can work on current state information or can use historical data to calculate aggregate functions like sum, average, min, max over specified timeframes (eg. calculate the average power use over the last year, or the maximum temperature yesterday).
Take an example scenario of monitoring power. My home uses 3 phase power and has sensors to monitor all 3 phases. I don’t really care about the individual phase power consumption but I do want to know the total power consumption. So I configure using a transform a virtual device to be the sum of all three phases and each time the power of a phase changes, the total consumption virtual device changes real time. I can utilise the events from the virtual device the same way as real devices (eg. for history graphs or in a power meter widget). Going further with this concept – I also have solar on the roof so I can create another virtual device that uses total power events from the total power virtual device and subtracts the solar power generated so I know total power drawn or fed into the grid. The utility company will pay me 2x the peak tariff as a rebate if I feed power back into the grid, so using another transform I can calculate in real time the savings I am getting back from the utility co, or do history graphs, or create alerts on maximum power use and so on. All this through configuration not hard coding – i.e. an end user can set this up.
Below is the transformation settings for the solar rebate example (click for higher resolution) which is working in my system today, it creates a new real-time message based on the total power virtual device, subtract the solar power total, don't calculate a value lower than 0 (ie. I won't get money back if I'm consuming more than I'm generating) and multiply by the rebate tariff. Each line in the transform function can be edited in the bottom panel including using aggregate functions like an average value over a selected period.
Transformations have proved to be one of the most useful aspects of this system - turning raw sensor data into useful information, which in the above example has helped me maximise the payback of rebates from the electricity company by managing my energy consumption better.