Page 1 of 2

Home automation engine

Posted: 24 Sep 2013 04:16
by PoltoS
We know that all of you are waiting for Home Automation engine with impation. We are working to make it real! But please do not be too excited before we have finished. So far it is more for geeks that for real life.I'll describe three concepts of Home Automation we are developing. Most of you will use the third one, but some will still use the low level approach.Low level work with Z-Way JS APIThis approach is based on direct access to zway object and usage of bind() calls on each dataholder. Here is an example:Z-Way.JS tricks

// Blink with some devices (flashStart() to start blinking, flashStop() to stop)

var flashTmr = null;

var flashStart = function () {
if (flashTmr) clearTimeout(flashTmr);
flashTmr = setInterval(flashBlink, 5 * 1000)
}

var flashStop = function () {
clearTimeout(flashTmr);

zway.devices[4].SwitchBinary.Set(255);
zway.devices[3].SwitchMultilevel.Set(20);
zway.devices[14].SwitchMultilevel.Set(20);
zway.devices[20].SwitchMultilevel.Set(20);
}

var flashBlink = function () {
zway.devices[4].instances[1].SwitchBinary.Set(zway.devices[4].instances[1].SwitchBinary.data.level.value ? 0 : 255);
zway.devices[3].SwitchMultilevel.Set(zway.devices[3].SwitchMultilevel.data.level.value ? 0 : 99);
zway.devices[14].SwitchMultilevel.Set(zway.devices[14].SwitchMultilevel.data.level.value ? 0 : 99);
zway.devices[20].SwitchMultilevel.Set(zway.devices[20].SwitchMultilevel.data.level.value ? 0 : 99);
}

// All Off on Fob double click 1 and Dimmer 3 double click (will come as MultichannelAssociation to controller instance 2)

zway.devices[1].instances[2].Basic.data.level.bind(function() {
if (this.value == 0) {
zway.devices[4].SwitchBinary.Set(0);
zway.devices[3].SwitchMultilevel.Set(0);
zway.devices[7].instances[1].SwitchBinary.Set(0);
zway.devices[9].SwitchMultilevel.Set(0);
zway.devices[14].SwitchMultilevel.Set(0);
zway.devices[20].SwitchMultilevel.Set(0);
}
});

// Alarm on Fob double click 2(on)/4(off) (will come as MultichannelAssociation to controller instance 4)

zway.devices[1].instances[4].Basic.data.level.bind(function() {
if (this.value > 0)
flashStart();
else
flashStop();
});

// Auto Off

var autoOff4 = null;

zway.devices[4].instances[1].SwitchBinary.data.level.bind(function() {
if (autoOff4)
clearTimeout(autoOff4);

if (this.value > 0)
autoOff4 = setTimeout(function() {
zway.devices[4].instances[1].SwitchBinary.Set(0)
}, 30*1000);
});

// Smooth dimming on Wall Controller double click (will come as SceneActivation)

zway.devices[11].instances[0].SceneActivation.data.currentScene.bind(function() {
if (this.value == 12) {
zway.devices[14].SwitchMultilevel.Set(0, 129); // With Duration
zway.devices[20].SwitchMultilevel.Set(0, 129); // With Duration
}
});

// Scenes on Wall Controller click (will come as 1:5. Direct associations are with 14 an 20)

var sceneState = 0;
zway.devices[1].instances[5].Basic.data.level.bind(function() {
if (this.value)
switch(sceneState) {
case 0:
case 3:
sceneState = 1;
zway.devices[14].SwitchMultilevel.Set(30);
zway.devices[20].SwitchMultilevel.Set(30);
break;
case 1:
sceneState = 2;
zway.devices[14].SwitchMultilevel.Set(0);
zway.devices[20].SwitchMultilevel.Set(30);
break;
case 2:
sceneState = 3;
zway.devices[14].SwitchMultilevel.Set(30);
zway.devices[20].SwitchMultilevel.Set(0);
break;
}
else
sceneState = 0;
}); Of course this code needs to be placed in a file and executed from main.js (or even placed in main.js itself). On startup Z-Way executes main.js contained in the folder listed under automation-dir tag in config.xml. This approach is extremely flexible, but quite hard to extend and share with others.Modules based usage of Z-Way APIThis approach is way better, since separates different functions into modules. Modules are easy to share and extend. Z-Way is shipped with module system. Advanced users can write their own modules and/or modify existing.New module should be placed in automation/modules folder. Each module consist of a folder named exactly as the module's class and at last two files inside: index.js and module.json.index.js must contain the declaration of the module object (in this example BatteryPolling, stored in the folder also called BatteryPolling), some mandatory lines to register the object and init prototype. function BatteryPolling (id, controller) {
// Call superconstructor first (AutomationModule), do not remove this line
BatteryPolling.super_.call(this, id, controller);

// From here you can write your own constructor
}

// This is needed to correctly register the module
inherits(BatteryPolling, AutomationModule);
_module = BatteryPolling;

// This is initializer function, called for each instance of the module with a specific config for the particular instance
BatteryPolling.prototype.init = function (config) {
// Call superclass' init (this will process config argument and so on), don't remove this line
BatteryPolling.super_.prototype.init.call(this, config);

    // From here modules specific code

this.controller.emit("cron.addTask", "batteryPolling.poll", {
minute: 0,
hour: 0,
weekDay: this.config.launchWeekDay,
day: null,
month: null
});

// Setup event listener
this.controller.on('batteryPolling.poll', function () {
for (var id in zway.devices) {
zway.devices[id].Battery && zway.devices[id].Battery.Get();
}
});
};
One can see that this module dirrectly access to zway object to make polling of batteries charge values.module.json contains module metadata and default configuration. singleton means that the module can be instanciated only once, autoload can instruct Home Automation engine to load it at startup (even if not listed in the list of instances in config.json) {
"autoload": true,
"singleton": false,
"defaults": {
"launchWeekDay": 0,
"warningLevel": 20
}
} Here we are not only introducing a specification how to write modules, but also provide "events" system: a way to emit and trap different events.Event is named by a string (event name), which should be specified as <module_name>.<event_name>. Any module can trap events with any name using controller.on() call and emit them using controller.emit() call. Each module is supposed to provide (emit) some events and to listen (subscribe) events. Each event can be accompained by some additional parameters.Using this even system we have implemented all releations between modules. For example cron module listens for cron.addTask event and set up scheduler. As a parameters this event contains schedule definition and event name to fire periodically. The callee is supposed to listen for these events and perform some task once triggered by scheduler (in our example it is batteryPolling.poll).Module based system with Virtual DevicesWe understand, that direct access to Z-Way API is cool, but too difficult to make own home automation system flexible.To make life easier we provide Virtual Devices concept. A Virtual Device can be generated based on Z-Wave device, some other data (wheather or finantial quotes) or even in future from another Home Automation protocol such as X10/EnOcean/KNX/....Let's look on another module called AutoOff. It is supposed to turn off a device after it was turned on.function AutoOff (id, controller) {
// Call superconstructor first (AutomationModule), do not remove this line
AutoOff.super_.call(this, id, controller);

// From here you can write your own constructor

// Create instance variables
this.timer = null;
}

// This is needed to correctly register the module
inherits(AutoOff, AutomationModule);
_module = AutoOff;

// This is initializer function, called for each instance of the module with a specific config for the particular instance
AutoOff.prototype.init = function (config) {
// Call superclass' init (this will process config argument and so on), don't remove this line
AutoOff.super_.prototype.init.call(this, config);

// From here modules specific code

// Check VirtualDevice existence
if (!this.controller.devices.hasOwnProperty(this.config.device)) {
// Exit initializer due to lack of the device
console.log("ERROR", "AutoOff Device", this.config.device, "doesn't exist.");
return;
}

var device = this.controller.devices[this.config.device];

// Check if device is a switch
if ("switch" !== device.deviceType) {
// Exit initializer due to invalid device type
console.log("ERROR", "AutoOff Device", this.config.device, "isn't switch", "("+device.deviceType+").");
return;
}

// Remember "this" for detached callbacks (such as event listener callbacks)
var self = this;

// Setup metric update event listener
this.controller.on('metricUpdate.'+this.config.device, function (metric, value) {
if ("level" === metric) {
if (self.timer) {
// Timer is set, so we destroy it
clearTimeout(self.timer);
}
if (255 === value) {
// Device reported "on", set (or reset) timer to new timeout
// Notice: self.config.timeout set in seconds
self.timer = setTimeout(function () {
// Timeout fired, so we send "off" command to the virtual device
// (every switch device should handle it)
device.performCommand("off");
// And clearing out this.timer variable
self.timer = null;
}, self.config.timeout*1000);
}
}
});
};controller.devices is a list of all Virtual Devices registered in our engine. Usually hey are named like ZWavDev_6:0:38. Don't care much about the name, but take in mind that the name can help you to find the real deivce ID in Z-Wave network. String 6:0:38 in the name means ID 6, instance 0, Command Class 38 (Switch Multilevel). But this is just an internal name and MUST NOT be used to get real Z-Wave ID using parsing of this string.Each Virtual Device will receive metricUpdate event on it's values change. As a parameter it's value is passed. You can also call performCommand() on the Virtual Device to turn it on/off. Full list of available commands will be published soon. This list depends on Virtual Device type, stored in deviceType and deviceSubType properties of Virtual Device object.The configuration for such a module would look like the code below. The name of the Virtual Device can be obtained from the new UI (we print it temporary for convenience) or in logs. "config": {
"device": "ZWayVDev_6:0:38",
"timeout": 3
}
On startup a lot of Virtual Devices are created: for each device capability. sensors, switches, dimmers, thermostats, ... all provide it's own Virtual Device.Note that the new UI is based on Virtual Devices only! It has no idea about Z-Wave internals, all widgets are rendered based on Virtual Devices. In future we will demonstrate how to make your own widget in the UI based on own Virtual Device.How to configure modules?All configuration of modules is done from a single place: automation/config.json file. Here is a typical content:{
"controller": {
"modules": [
"EventLog",
"ZWaveGate",
"Cron",
"BatteryPolling",
"AutoOff",
"CustomUserCode",
"BasicReactions"
],
"instances": {
"EventLog" : {
"module": "EventLog",
"config": {}
},
"ZWave" : {
"module": "ZWaveGate",
"config": {
"basicsEnabled": true
}
},
"BasicReactor": {
"module": "BasicReactions",
"config": {
"map": [
{
"channel": 1,
"level": 255,
"reactions": {
"tempOn": {
"vDev": "ZWayVDev_6:0:38",
"timeout": 5
}
}
},
{
"channel": 3,
"level": 255,
"reactions": {
"tempOn": {
"vDev": "ZWayVDev_3:0:37",
"timeout": 3
}
}
}
]
}
}
}
}
}Modules part contains the list of all modules to load. This part will disappear soon: modules will be scanned from automation/modules folder and automatically loaded. Instences part contains the list of instance for each module you want. Some modules MUST be instanciated to make the whole subsystem to work: EventLog, ZWave. Some are optional, like Cron, AutoOff. The name of the instance can be any (make sure to have different names for different instances - these never appears in any place). Module name is refered in module parameter, while config parameter defines individual parameters for each instance.In next release we are planing to add visial editor for this config.json file, so you will not need anymore to edit it manually using vi ;)Which way to choose for you?We believe that the most efficient way is to use Virtual Devices approach. But for some small and straightforward tasks direct access to Z-Way JS API is way better. You can even mix both approaches without any problem.Run custom codeInstead of altering the content of main.js file to run your own code we propose a CustomCode module. It just requires one parameter with the list of files to execute. These files will be executed during Home Automation engine startup. We suggest to move all custom code into separate files and execute it form here.Get more infoPlease check sources and documentation on GitHub.Also have a look on user manual and developers guide.ParticipateWe welcome everyone to contribute to this project. Source codes of Home Automation engine are available on GitHub. You are free to write your own modules and commit them bak into GitHub. Make pull requests if you feel your feature to bee cool and important for our project!See more about your commitment on https://github.com/Z-Wave-Me/home-autom ... stallation.

Thanks for this information.

Posted: 24 Sep 2013 04:16
by pz1
Thanks for this information. A lot to chew for me. I won't get bored the coming weeks;)
Good to see that also the user manual and developers guide have been substantially updated and now reflect version 1.4

Hello everyone,

Posted: 24 Sep 2013 04:16
by Pitt13
Hello everyone,
I do not understand how to use the automation menu, and no menus in automation does work except DASHBOARD.

I do not understand how to enter the Smart TV from the TV UI menu.

the mobile UI menu is pretty easy to use => Thanks to its simplicity :D

Can you explain the views and results to image (screenshot) Code?

Events bus

Posted: 24 Sep 2013 04:16
by alexey.zimarev
Is this correct that in order to listen for changes for all devices I need to have a handler for "metricUpdate"? What is the format for an event name, how can I ask to get all updates for example? Also is there a description for the value parameter for different device types? Are there special events that I can emit to change device configuration?

make http calls to remote server

Posted: 24 Sep 2013 04:16
by maha
Hi,

nice article, this information needs to go into developer documentation. how do i make calls to extenal web url with in module code ??

thanks

So far only via system call

Posted: 24 Sep 2013 04:16
by PoltoS
So far only via system call with curl or wget. But next release will (1.5) have net object to make requests to HTTP using GET and POST. This will allow to store data on remote servers, request wheather and even query another Z-Way to link two boxes and use it's devices to create vDev

hello,

Posted: 24 Sep 2013 04:16
by Pitt13
hello,
can you give us a date or tell us when is really available the "Automation" tab for beginners like me?
Put your hands in the code is not easy for me especially without example video or pictures or a tutorial with screenshot.

Very interesting system architecture

Posted: 24 Sep 2013 04:16
by krambriw
link two boxes and use it's devices to create vDevI think this could eventually open up for a very interesting system architecture....- Multiple boxes (many) in a distributed larger system- When sending command to a vDev, will it actually be executed in the local box where the real Dev belongs?- Could it be realized a kind of redundancy where two boxes are having in parallel support for same vDev's( I mean here to configure two or moreboxes in a cluster setup) ?Best regards, Walter 

Learning the source

Posted: 24 Sep 2013 04:16
by dirkx
PoltoS,

When binding to many events - and doing some sort of common follow up on each; how can one learn what the source is within the event handler ?


// monitor all XXX devices.
for(int device=3 ; device < 10; device++)
zway.devices[ device ].instances[2].Basic.data.level.bind(function() {
// how to extract zDeviceID or other source/reference information ?
});

How: So far only via system call

Posted: 24 Sep 2013 04:16
by maha

Hi Thanks for the Quick reply.


1. Can you please guide me how to curl or wget from javascript (system call?). any example would be great.
2. i have bought RazBerry card and installed using 'curl http://razberry.z-wave.me/install' but this version seems to be older than the one in github (https://github.com/Z-Wave-Me/home-automation) ? any thoughts how do i get latest version ?
3. is there a way i can use nodejs modules inside the automation engine???