Skip to content
simen edited this page Dec 21, 2016 · 15 revisions

1. Overview

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.


## 2. Installation

$ npm install ziee --save


## 3. Initialization of Clusters: Step by step

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 the cb with the last argument. Here, we initialize ZCL commands of 'moveToHue', 'stepHue', and 'stepColor' as an example.

      ziee.init('lightingColorCtrl', 'cmds', {
          moveToHue: function (zapp, movemode, rate, cb) {
              // ... do something, then call the err-first callback
              cb(null, something);
          },
          stepHue: function (zapp, stepmode, stepsize, transtime, cb) {
              // ...
          },
          stepColor: {    // you can also wrap a command within an object by key 'exec'
              exec: 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.

## 4. Access Clusters

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, stepx, stepy, transtime, cb) {
    // ...
});

## 5. Dump Data

Asynchronous dump

// 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').


************************************************* ### new 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:

  1. (none)

Returns:

  • (Object): ziee

Examples:

var Ziee = require('ziee');
var ziee = new Ziee();

************************************************* ### init(cid, sid, spec[, isZcl]) Initialize your cluster and all its specs. Here, a `spec` is an object required by the corresponding init procedure.

Arguments:

  1. cid (String | Number): Cluster Id. Will be turned into a key in string internally.
  2. sid (String): Spec Id, which accepts 'dir', 'acls', 'attrs', 'cmds', and 'cmdRsps'.
  3. spec (Object): An object holds all Resources (attributes, flags, command methods, ...) corresponding to which sid to be initialized.
  4. isZcl (Boolean): Optional. Force to use ZCL-defined ids if true, and default is true. If you like to add something that is not ZCL-defined, please init() it with false (highly not recommended).

Returns:

  • (Object): ziee

Examples:

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, movemode, rate, cb) {
        // 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, stepmode, stepsize, transtime, cb) {
        // ...
    },
    stepColor: {    // you can also wrap a command within an object by key 'exec'
        exec: function (zapp, argObj, cb) {
            // argObj = { stepx, stepy, transtime }
            // ...
        }
    }
});

************************************************* ### glue(zapp) Glue `ziee` to a zapp.

Arguments:

  1. (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);

************************************************* ### clusterList() Export the input and out cluster lists within this ziee.

Arguments:

  1. 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 ]
}
*/

************************************************* ### has(cid[, sid[, rid]]) To see if `ziee` has the specified _Cluster_, Cluster Spec_, or _Cluster Resource_.

Arguments:

  1. cid (String | Number): Cluster Id of the target.
  2. sid (String): Spec Id of the target, which accepts 'dir', 'acls', 'attrs', 'cmds', and 'cmdRsps'.
  3. rid (String | Number): Resource Id of the target. (Resource Id is also the Attribute Id if sid == 'attrs')

Returns:

  • (Boolean): Returns true if target exists, otherwise false.

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

************************************************* ### get(cid, sid, rid) Synchronously get the specified _Resource_.

Arguments:

  1. cid (String | Number): Cluster Id of the target.
  2. sid (String): Spec Id of the target, which accepts 'dir', 'acls', 'attrs', 'cmds', and 'cmdRsps'.
  3. rid (String | Number): Resource Id of the target. (Resource Id is also the Attribute Id if sid == '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 () { ... } }

************************************************* ### set(cid, sid, rid, value) Synchronously set a value to the specified _Resource_.

Arguments:

  1. cid (String | Number): Cluster Id of the target.
  2. sid (String): Spec Id of the target, which accepts 'dir', 'acls', 'attrs', 'cmds', and 'cmdRsps'.
  3. rid (String | Number): Resource Id of the target. (Resource Id is also the Attribute Id if sid == 'attrs')
  4. value (Primitives | Object): Resource data or an object with read/write/exec method(s). This method will throw you an error if value is given with a function.

Returns:

  • (Boolean): Returns true if set successfully, else returns false 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, stepx, stepy, transtime, cb) {
    // ...
});

************************************************* ### read(cid, attrId, callback) Asynchronously read the specified _Attribute_ value.

Arguments:

  1. cid (String | Number): Cluster Id of the target.
  2. attrId (String | Number): Attribute Id within the cluster.
  3. callback (Function): function (err, data) { ... }. Will be called when reading is done or any error occurs, where data is the Resource value. (When an error occurs, ziee will pass you a string like '_notfound_' with data)
  • 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_'
    }
});

************************************************* ### write(cid, attrId, value, callback) Asynchronously write a value to the specified _Attribute_.

Arguments:

  1. cid (String | Number): Cluster Id of the target.
  2. attrId (String | Number): Attribute Id within the cluster.
  3. value (Depends): The value to write to the specified attribute.
  4. callback (Function): function (err, data) { ... }. Will be called when writing is done or any error occurs, where data is the Attribute value. (When an error occurs, ziee will pass you a string like '_notfound_' with data)
  • 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_'
    }
});

************************************************* ### exec(type, cid, cmdId, argObj, callback) Execute the specified _Command_. The executable _Command_ is a ZCL-defined functional procedure.

Arguments:

  1. 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.
  2. cid (String | Number): Cluster Id.
  3. cmdId (String | Number): Command Id within the cluster.
  4. argObj (Object): The parameters required by the command.
  5. callback (Function): function (err, data) { ... }. Will be called when execution is performed or any error occurs, where data 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.
*/
});

************************************************* ### dump([cid[, sid],] callback) Asynchronously dump data from `ziee`. This method uses the asynchronous `read()` under the hood.
  • Given with cid, sid, and a callback to dump data of a Spec.
  • Given with cid and a callback to dump data of a Cluster.
  • Given with only a callback to dump data of all Clusters.

Arguments:

  1. cid (String | Number): Cluster Id of the target.
  2. sid (String): Spec Id of the target, which accepts 'dir', 'acls', 'attrs', 'cmds', and 'cmdRsps'.
  3. 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'
    }
*/
});

************************************************* ### dumpSync([cid[, sid]]) Synchronously dump data from `ziee`. This method uses the synchronous `get()` under the hood.
  • Given with both cid and sid 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, use get() instead.

Arguments:

  1. cid (String | Number): Cluster Id of the target.
  2. 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_'},
      ...
    }
*/