-
Notifications
You must be signed in to change notification settings - Fork 5
Home
ziee is a Class that helps you create ZCL Clusters in your JavaScript applications. You can use ziee as the base class to abstract your hardware, sensor modules, or gadgets into plugins (node.js packages) for your users convenience.
$ npm install ziee --save
Here is a quick example that will walk you through the steps of initializing a 'lightingColorCtrl' cluster.
-
Step 1: Import the Ziee Class
var Ziee = require('ziee'), zApp = {}; // Your zigbee application, I take a mock object here as an example
-
Step 2: New a ziee instance. Then, initialize a 'lightingColorCtrl' cluster in your ziee, including the cluster's (1) direction (2) attributes (3) access control flags, and (4) zcl commands.
var ziee = new Ziee();
-
Step (2-1): Direction. Tell ziee that this is an input, output, or input/output cluster.
ziee.init('lightingColorCtrl', 'dir', { value: 1 }); // 1: input, 2: output, 3: input/output
-
Step (2-2): Attributes. Abstract hardware operation with read/write callbacks if needed. Here, we initialize attributes of 'currentHue', 'currentSaturation', and 'colorMode' as an example.
ziee.init('lightingColorCtrl', 'attrs', { currentHue: 10, // (A) a simple primitive currentSaturation: { // (B) with read/write method read: function (cb) { // ... do something to get data cb(null, data); }, write: function (val, cb) { // ... do something to set data cb(null, val); } }, colorMode: { // (C) with read method read: function (cb) { // ... do something to get data cb(null, data); } } });
-
Step (2-3): Access control flags. Specify the access control of each attribute. The
'acls'
spec is used to control the authority from remote access. The local access depends on read/write methods, not depends on these flags.// 'RW': readable and writable, 'R': read-only, 'W': write-only ziee.init('lightingColorCtrl', 'acls', { currentHue: 'RW', currentSaturation: 'R', colorMode: 'R' });
-
Step (2-4): Zcl commands. Define commands that your cluster supports. In each command method, ziee will pass you the
zapp
with 1st argument, and pass you thecb
with the last argument. Here, we initialize ZCL commands of 'moveToHue', 'stepHue', and 'stepColor' as an example.ziee.init('lightingColorCtrl', 'cmds', { moveToHue: function (zapp, argObj, cb) { // argObj = { movemode, rate } // ... do something, then call the err-first callback cb(null, something); }, stepHue: function (zapp, argObj, cb) { // argObj = { stepmode, stepsize, transtime } // ... }, stepColor: function (zapp, argObj, cb) { // argObj = { stepx, stepy, transtime } // ... } });
-
-
Step 3: Glue your ziee to the zapp.
ziee.glue(zApp);
- After glued, invoke ziee.init() again will throw you an error. Which means you have to init every thing before gluing ziee to zapp.
ziee provides you with read()
, write()
, exec()
, get()
, and set()
methods to access the clusters. It is highly recommended to use asynchronous read/write methods to access the attributes, especially for those should be got from certain operations, i.e. reading from an ADC, writing to a PWM port.
### Asynchronous read/write/exec methods
- read(): Asynchronously read the specified Attribute value.
- write(): Asynchronously write a value to the specified Attribute.
- exec(): Asynchronously execute the specified Command.
// read/write methods are only valid to access attributes.
ziee.read('lightingColorCtrl', 'currentHue', function (err, data) {
if (!err)
console.log(data); // 10
});
ziee.write('lightingColorCtrl', 'currentHue', 18, function (err, data) {
if (!err)
console.log(data); // 18
});
// exec method is only valid to commands.
ziee.exec('lightingColorCtrl', 'stepColor', { stepx: 6, stepy: 110, transtime: 20 }, function (err, data) {
if (!err)
console.log(data);
});
### Synchronous getter and setter
- get(): Synchronously get the specified Resource. This getter will return you the raw content of the specified Resource.
- set(): Synchronously set a value to the specified Resource. This setter will mutate the raw content of the specified Resource.
ziee.get('lightingColorCtrl', 'dir', 'value'); // 1
ziee.get('lightingColorCtrl', 'attrs', 'currentHue'); // 10
ziee.get('lightingColorCtrl', 'attrs', 'colorMode'); // { read: function () { ... }, _isCb: true }
ziee.get('lightingColorCtrl', 'acls', 'currentHue'); // 'RW'
ziee.get('lightingColorCtrl', 'cmds', 'moveToHue'); // { exec: function () { ... } }
ziee.set('lightingColorCtrl', 'dir', 'value', 0);
ziee.set('lightingColorCtrl', 'attrs', 'currentHue', 6);
ziee.set('lightingColorCtrl', 'acls', 'currentHue', 'W');
ziee.set('lightingColorCtrl', 'cmds', 'stepColor', function (zapp, argObj, cb) {
// argObj = { stepx, stepy, transtime }
// ...
});
## 5. Dump Data
// dump all clusters
ziee.dump(function (err, data) {
/*
{
lightingColorCtrl: {
dir: { value: 1 },
acls: { ... },
attrs: { ... },
cmds: { ... }
},
ssIasZone: {
dir: { value: 0 },
acls: { ... },
attrs: { ... },
cmds: { ... }
},
...
}
*/
});
// dump a cluster
ziee.dump('lightingColorCtrl', function (err, data) {
/*
{
dir: { value: 1 },
acls: { ... },
attrs: { ... },
cmds: { ... },
... // if you have some thing more
}
*/
});
// dump a spec
ziee.dump('lightingColorCtrl', 'acls', function (err, data) {
/*
{
currentHue: 'RW',
currentSaturation: 'R',
colorMode: 'R'
}
*/
});
### Synchronous dump
// dump access control flags
ziee.dumpSync('lightingColorCtrl', 'acls');
/*
{
currentHue: 'RW',
currentSaturation: 'R',
colorMode: 'R'
}
*/
// dump commands, the function cannot be serialized and it will be
// dumped into a string '_exec_'
ziee.dumpSync('lightingColorCtrl', 'cmds');
/*
{
stepColor: { exec: '_exec_'},
...
}
*/
## 6. APIs
### Ziee Class Exposed by `require('ziee')`.
Create an instance of Ziee class. This document will use ziee
to indicate this kind of instance. A ziee
can hold many Clusters in it.
Arguments:
- (none)
Returns:
- (Object): ziee
Examples:
var Ziee = require('ziee');
var ziee = new Ziee();
Initialize your cluster and all its specs. Here, a spec
is an object required by the corresponding init procedure.
Arguments:
-
cid
(String | Number): Cluster Id. Will be turned into a key in string internally. -
sid
(String): Spec Id, which accepts'dir'
,'acls'
,'attrs'
,'cmds'
, and'cmdRsps'
. -
spec
(Object): An object holds all Resources (attributes, flags, command methods, ...) corresponding to whichsid
to be initialized. -
isZcl
(Boolean): Optional. Force to use ZCL-defined ids iftrue
, and default istrue
. If you like to add something that is not ZCL-defined, please init() it withfalse
(highly not recommended).
Returns:
- (Object): ziee
Examples:
- Initialize a
'lightingColorCtrl'
cluster
ziee.init('lightingColorCtrl', 'dir', { value: 1 });
ziee.init('lightingColorCtrl', 'attrs', {
currentHue: 10, // (A) a simple primitive
currentSaturation: { // (B) with read/write method
read: function (cb) {
// ... do something to get data
cb(null, data);
},
write: function (val, cb) {
// ... do something to set data
cb(null, val);
}
},
colorMode: { // (C) with read method
read: function (cb) {
// ... do something to get data
cb(null, data);
}
}
});
ziee.init('lightingColorCtrl', 'acls', {
currentHue: 'RW',
currentSaturation: 'R',
colorMode: 'R'
});
ziee.init('lightingColorCtrl', 'cmds', {
moveToHue: function (zapp, argObj, cb) {
// argObj = { movemode, rate }
// ziee will pass zapp with 1st argument, and pass cb to the last argument to you
// ... do something, then call the err-first callback
cb(null, something);
},
stepHue: function (zapp, argObj, cb) {
// argObj = { stepmode, stepsize, transtime }
// ...
},
stepColor: function (zapp, argObj, cb) {
// argObj = { stepx, stepy, transtime }
// ...
}
});
- Initialize a
'ssIasZone'
cluster
// To implement a CIE application, please refer to ZigBee IAS Zone specification.
// This example only shows how to init the cluster, and not implements the logistics.
ziee.init('ssIasZone', 'dir', { value: 0 });
ziee.init('ssIasZone', 'attrs', {
zoneState: 0x00,
zoneType: 0x00,
zoneStatus: 0x00,
iasCieAddr: '0x00124b0001ce4beb',
zoneId: 6
});
ziee.init('ssIasZone', 'acls', {
zoneState: 'R',
zoneType: 'R',
zoneStatus: 'R',
iasCieAddr: 'RW',
zoneId: 'R'
});
ziee.init('ssIasZone', 'cmds', {
}); // No command
ziee.init('ssIasZone', 'cmdRsps', { // Direction is s2c, thus it is 'cmdRsps'
statusChangeNotification: function (zapp, data) {
// data = { src, zonestatus, extendedstatus }
// , where data.src = { epId, ieeeAddr, nwkAddr } to denote the source endpoint
// ...
},
enrollReq: function (zapp, data) {
// data = { src, zonetype, manucode }
// , where data.src = { epId, ieeeAddr, nwkAddr } to denote the source endpoint
// CIE logistics: Implemented by developer
// Finally, for example, the implementer call enrollRsp to
// response back to a IAS Zone peripheral
/*
zapp.functional(
data.src.ieeeAddr,
data.src.epId,
'ssIasZone',
'enrollRsp',
{ enrollrspcode: 0x00, zoneid : 6 },
{ direction: 0 },
function (err, rsp) {
// ...
}
);
*/
}
});
Glue ziee
to a zapp.
Arguments:
- (Object): zigbee app
Returns:
- (Object):
ziee
Examples:
var zApp = {}; // Your zigbee application, I take a mock object here as an example
// ... do the initialization
ziee.glue(zApp);
Export the input and out cluster lists within this ziee.
Arguments:
- none
Returns:
- (Object): Returns an object with
'in'
and'out'
properties to show the input and output cluster lists. Each element in the list is a numeric cluster id.
Examples:
ziee.clusterList();
/*
{
in: [ 768, 2818, 1280, 513, 257, 6 ],
out: [ 513, 257, 11, 9, 6 ]
}
*/
To see if ziee
has the specified Cluster, Cluster Spec_, or Cluster Resource.
Arguments:
-
cid
(String | Number): Cluster Id of the target. -
sid
(String): Spec Id of the target, which accepts'dir'
,'acls'
,'attrs'
,'cmds'
, and'cmdRsps'
. -
rid
(String | Number): Resource Id of the target. (Resource Id is also the Attribute Id ifsid == 'attrs'
)
Returns:
- (Boolean): Returns
true
if target exists, otherwisefalse
.
Examples:
ziee.has('lightingColorCtrl', 'cmds', 'stepHue'); // true
ziee.has('lightingColorCtrl', 'cmds', 'xxx'); // false
ziee.has('lightingColorCtrl', 'attrs', 'currentSaturation'); // true
ziee.has('lightingColorCtrl', 'attrs', 'yyy'); // false
ziee.has('lightingColorCtrl', 'acls', 'currentSaturation'); // true
Synchronously get the specified Resource.
Arguments:
-
cid
(String | Number): Cluster Id of the target. -
sid
(String): Spec Id of the target, which accepts'dir'
,'acls'
,'attrs'
,'cmds'
, and'cmdRsps'
. -
rid
(String | Number): Resource Id of the target. (Resource Id is also the Attribute Id ifsid == 'attrs'
)
Returns:
- (Depends): Returns the Resource value, or
undefined
if Resource does not exist.
Examples:
ziee.get('lightingColorCtrl', 'dir', 'value'); // 1
ziee.get('lightingColorCtrl', 'attrs', 'currentHue'); // 10
ziee.get('lightingColorCtrl', 'attrs', 'colorMode'); // { read: function () { ... }, _isCb: true }
ziee.get('lightingColorCtrl', 'attrs', 'xxx'); // undefined
ziee.get('lightingColorCtrl', 'acls', 'currentHue'); // 'RW'
ziee.get('lightingColorCtrl', 'acls', 'yyy'); // undefined
ziee.get('lightingColorCtrl', 'cmds', 'moveToHue'); // { exec: function () { ... } }
Synchronously set a value to the specified Resource.
Arguments:
-
cid
(String | Number): Cluster Id of the target. -
sid
(String): Spec Id of the target, which accepts'dir'
,'acls'
,'attrs'
,'cmds'
, and'cmdRsps'
. -
rid
(String | Number): Resource Id of the target. (Resource Id is also the Attribute Id ifsid == 'attrs'
) -
value
(Primitives | Object): Resource data or an object with read/write/exec method(s). This method will throw you an error ifvalue
is given with a function.
Returns:
- (Boolean): Returns
true
if set successfully, else returnsfalse
if the Cluster does not exist (Resource cannot be set).
Examples:
ziee.set('lightingColorCtrl', 'dir', 'value', 0);
ziee.set('lightingColorCtrl', 'attrs', 'currentHue', 6);
ziee.set('lightingColorCtrl', 'acls', 'currentHue', 'W');
ziee.set('lightingColorCtrl', 'cmds', 'stepColor', function (zapp, argObj, cb) {
// argObj = { stepx, stepy, transtime }
// ...
});
Asynchronously read the specified Attribute value.
Arguments:
-
cid
(String | Number): Cluster Id of the target. -
attrId
(String | Number): Attribute Id within the cluster. -
callback
(Function):function (err, data) { ... }
. Will be called when reading is done or any error occurs, wheredata
is the Resource value. (When an error occurs,ziee
will pass you a string like'_notfound_'
withdata
)
- This table show you what results may the callback receive:
err | data | Description |
---|---|---|
Error object | '_notfound_' |
Attribute not found. |
Error object | '_unreadable_' |
Attribute is unreadable. |
Error object | '_exec_' |
Attribute is unreadable (Because it is an executable Resource). |
null |
Depends | Attribute is successfully read. |
Returns:
- (none)
Examples:
ziee.read('lightingColorCtrl', 'currentHue', function (err, data) {
if (!err)
console.log(data); // 10
});
ziee.read('lightingColorCtrl', 'xxxx', function (err, data) {
if (err) {
console.log(err);
console.log(data); // '_nofound_'
}
});
Asynchronously write a value to the specified Attribute.
Arguments:
-
cid
(String | Number): Cluster Id of the target. -
attrId
(String | Number): Attribute Id within the cluster. -
value
(Depends): The value to write to the specified attribute. -
callback
(Function):function (err, data) { ... }
. Will be called when writing is done or any error occurs, wheredata
is the Attribute value. (When an error occurs,ziee
will pass you a string like'_notfound_'
withdata
)
- This table show you what results may the callback receive:
err | data | Description |
---|---|---|
Error object | '_notfound_' |
Attribute not found. |
Error object | '_unwritable_' |
Attribute is unwritable. |
Error object | '_exec_' |
Attribute is unwritable (Because it is an executable Resource). |
null |
Depends | Attribute is successfully write. |
Returns:
- (none)
Examples:
ziee.write('lightingColorCtrl', 'currentHue', 18, function (err, data) {
if (!err)
console.log(data); // 18
});
ziee.write('lightingColorCtrl', 'xxx', 18, function (err, data) {
if (err) {
console.log(err);
console.log(data); // '_nofound_'
}
});
Execute the specified Command. The executable Command is a ZCL-defined functional procedure.
Arguments:
-
type
(String): Set it to'cmd'
to execute client-to-server (c2s) command, and set it to'cmdRsp'
to execute server-to-client (s2c) command. -
cid
(String | Number): Cluster Id. -
cmdId
(String | Number): Command Id within the cluster. -
argObj
(Object): The parameters required by the command. -
callback
(Function):function (err, data) { ... }
. Will be called when execution is performed or any error occurs, wheredata
is your command should respond back.
- To see what kind of data you should respond back upon receiving a command, please go to ZCL Functional Command Reference Table for more information.
- For example, when you receive a 'getWeeklySchedule' command, you should respond a 'getWeeklyScheduleRsp' response to the requester.
- This table shows you what results may the callback receive:
err | data | Description |
---|---|---|
Error object | '_notfound_' |
Resource not found. |
Error object | '_unexecutable_' |
Resource is unexecutable. |
Error object | '_badarg_' |
Input arguments is not an array. |
null |
Depends |
Command is successfully executed, and data depends on ZCL definition. |
Returns:
- (none)
Examples:
ziee.exec('cmd' ,'hvacThermostat', 'getWeeklySchedule', {
daystoreturn: 110,
modetoreturn: 20
}, function (err, data) {
if (!err)
console.log(data);
/*
data is 'getWeeklyScheduleRsp' response data object defined by ZCL, and
your exec function should return an object like:
{
numoftrans:3,
dayofweek: 2,
mode: 1,
thermoseqmode: 1
}
back through the callback.
*/
});
Asynchronously dump data from ziee
. This method uses the asynchronous read()
under the hood.
- Given with
cid
,sid
, and acallback
to dump data of a Spec. - Given with
cid
and acallback
to dump data of a Cluster. - Given with only a
callback
to dump data of all Clusters.
Arguments:
-
cid
(String | Number): Cluster Id of the target. -
sid
(String): Spec Id of the target, which accepts'dir'
,'acls'
,'attrs'
,'cmds'
, and'cmdRsps'
. -
callback
(Function):function (err, data) { }
.
Returns:
- (none)
Examples:
// (1) Dump all clusters
ziee.dump(function (err, data) {
/*
{
lightingColorCtrl: {
dir: { value: 1 },
acls: { ... },
attrs: { ... },
cmds: { ... }
},
ssIasZone: {
dir: { value: 0 },
acls: { ... },
attrs: { ... },
cmds: { ... }
},
...
}
*/
});
// (2) Dump a cluster
ziee.dump('lightingColorCtrl', function (err, data) {
/*
{
dir: { value: 1 },
acls: { ... },
attrs: { ... },
cmds: { ... },
... // if you have some thing more
}
*/
});
// (3) Dump a spec
ziee.dump('lightingColorCtrl', 'acls', function (err, data) {
/*
{
currentHue: 'RW',
currentSaturation: 'R',
colorMode: 'R'
}
*/
});
Synchronously dump data from ziee
. This method uses the synchronous get()
under the hood.
- Given with both
cid
andsid
to dump data of a Spec. - Given with only
cid
to dump data of a Cluster. - Given with no ids to dump data of all Clusters.
- This method should only be used at server-side (since at server-side, all stored Clusters are simply data pieces).
- All read/write/exec method will be dump to strings
'_read_'
,'_write_'
, and'_exec_'
. If you like to have the function method, useget()
instead.
Arguments:
-
cid
(String | Number): Cluster Id of the target. -
sid
(String): Spec Id of the target, which accepts'dir'
,'acls'
,'attrs'
,'cmds'
, and'cmdRsps'
.
Returns:
- (Object): The dumped data, can be from a Spec, a Cluster, or whole Clusters.
Examples:
ziee.dumpSync('lightingColorCtrl', 'acls');
/*
{
currentHue: 'RW',
currentSaturation: 'R',
colorMode: 'R'
}
*/
ziee.dumpSync('lightingColorCtrl', 'cmds');
/*
{
stepColor: { exec: '_exec_'},
...
}
*/