Home automation engine

Discussions about RaZberry - Z-Wave board for Raspberry computer
User avatar
PoltoS
Posts: 7571
Joined: 26 Jan 2011 19:36

Home automation engine

Post 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.
pz1
Posts: 2053
Joined: 08 Apr 2012 13:44

Thanks for this information.

Post 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
Since 29-12-2016 I am no longer a moderator for this forum
Pitt13
Posts: 41
Joined: 13 Apr 2013 23:52

Hello everyone,

Post 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?
User avatar
alexey.zimarev
Posts: 24
Joined: 16 Oct 2012 17:54

Events bus

Post 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?
maha
Posts: 2
Joined: 01 Nov 2013 18:10

make http calls to remote server

Post 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
User avatar
PoltoS
Posts: 7571
Joined: 26 Jan 2011 19:36

So far only via system call

Post 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
Pitt13
Posts: 41
Joined: 13 Apr 2013 23:52

hello,

Post 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.
krambriw
Posts: 46
Joined: 03 Apr 2013 18:14

Very interesting system architecture

Post 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 
dirkx
Posts: 13
Joined: 03 Nov 2013 20:52

Learning the source

Post 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 ?
});
maha
Posts: 2
Joined: 01 Nov 2013 18:10

How: So far only via system call

Post 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???


Post Reply