Skip to content

Commit

Permalink
fix broken NR status updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ekarak committed Jan 14, 2017
1 parent 013528b commit 990db59
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 37 deletions.
74 changes: 45 additions & 29 deletions 10-zwave.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@
limitations under the License.
*/
var fs = require('fs');
var path = require('path');
var util = require('util');
var UUIDPREFIX = "_macaddr_";
var HOMENAME = "_homename_";

var ozwsharedpath = path.dirname(path.dirname(require.resolve('openzwave-shared')));
var ozwsharedpackage = JSON.parse(fs.readFileSync(ozwsharedpath+"/package.json"));
var thispackage = JSON.parse(fs.readFileSync(__dirname+'/package.json'));

require('getmac').getMac(function(err, macAddress) {
if (err) throw err;
UUIDPREFIX = macAddress.replace(/:/gi, '');
Expand All @@ -34,9 +40,10 @@ module.exports = function(RED) {
}
}

RED.log.info('OpenZWave module: ' + require.resolve('openzwave-shared'));
var OpenZWave = require('openzwave-shared');
RED.log.info('node-red-contrib-openzwave: ' + thispackage.version);
RED.log.info('openzwave-shared: ' + ozwsharedpackage.version);

var OpenZWave = require('openzwave-shared');
var ozwConfig = {};
var ozwDriver = null;
var ozwConnected = false;
Expand All @@ -56,10 +63,10 @@ module.exports = function(RED) {
function zwsubscribe(nrNode, event, callback) {
if (!(event in nrNodeSubscriptions)) {
nrNodeSubscriptions[event] = {};
nrNodeSubscriptions[event][nrNode.id] = callback;
log('full', util.format('%s(%s) subscribed to \"%s\"', nrNode.type,
nrNode.id, event));
}
nrNodeSubscriptions[event][nrNode.id] = callback;
log('full', util.format('%s(%s) subscribed to \"%s\"', nrNode.type,
nrNode.id, event));
}

// and unsubscribe
Expand Down Expand Up @@ -89,27 +96,43 @@ module.exports = function(RED) {
var nrNodes = nrNodeSubscriptions[event];
// an event might be subscribed by multiple NR nodes
for (var nrnid in nrNodes) {
if (nrNodes.hasOwnProperty(nrnid)) {
var nrNode = RED.nodes.getNode(nrnid);
log('full', "\t\\==> " + nrnid + " event:" + event);
nrNodes[nrnid].call(nrNode, event, arghash);
updateNodeRedStatus(nrNode);
var nrNode = RED.nodes.getNode(nrnid);
log('full', "\t\\==> " + nrnid + " event:" + event);
nrNodes[nrnid].call(nrNode, event, arghash);
// update the node status accordingly
var status = {fill: "yellow", text: event, shape: "ring"};
switch(event) {
case 'node event':
case 'node ready':
status.text = util.format('node %j: %s', arghash.nodeid, event);
break;
case 'value changed':
status.text = util.format('node %j: %s', arghash.nodeid, event);
break;
case 'controller command': //, function(nodeId, ctrlState, ctrlError, helpmsg)
status.text = util.format('%j', arghash.helpmsg);
break;
default:
break;
}
updateNodeRedStatus(nrNode, status);
setTimeout(function() {
updateNodeRedStatus(nrNode);
}, 500);
}
}
}

// update the NR node's status indicator
function updateNodeRedStatus(nrNode) {
function updateNodeRedStatus(nrNode, options) {
// update NR node status
nrNode.status({
nrNode.status(options || {
fill: driverReadyStatus ? "green" : "red",
text: driverReadyStatus ? "connected" : "disconnected",
shape: "ring"
});
}


function driverReady(homeid) {
driverReadyStatus = true;
ozwConfig.homeid = homeid;
Expand Down Expand Up @@ -226,7 +249,7 @@ module.exports = function(RED) {
}
ozwnode.ready = true;
//
log('full', 'only/|R|W| (nodeid-cmdclass-instance-index): type : current state');
log('full', 'only|R|W| (nodeid-cmdclass-instance-index): type : current state');
for (var comclass in ozwnode['classes']) {
switch (comclass) {
case 0x25: // COMMAND_CLASS_SWITCH_BINARY
Expand Down Expand Up @@ -321,7 +344,7 @@ module.exports = function(RED) {
UserPath: RED.settings.userDir,
DriverMaxAttempts: cfg.driverattempts
});
/* =============== OpenZWave events ================== */
/* =========== bind to low-level OpenZWave events ============== */
Object.keys(ozwEvents).forEach(function(evt) {
log('full', node.name + ' addListener ' + evt);
ozwDriver.on(evt, ozwEvents[evt]);
Expand Down Expand Up @@ -372,22 +395,14 @@ module.exports = function(RED) {
/* =============== Node-Red events ================== */
this.on("close", function() {
// set zwave node status as disconnected
node.status({
fill: "red",
shape: "ring",
text: "disconnected"
});
updateNodeRedStatus(node, {fill: "red", shape: "ring", text: "disconnected"});
// remove all event subscriptions for this node
zwunsubscribe(this);
log('full', 'zwave-in: close');
});
this.on("error", function() {
// what? there are no errors. there never were.
node.status({
fill: "yellow",
shape: "ring",
text: "error"
});
updateNodeRedStatus(node, {fill: "yellow",shape: "ring", text: "error"});
});

/* =============== OpenZWave events ================== */
Expand Down Expand Up @@ -487,7 +502,7 @@ module.exports = function(RED) {

this.on("close", function() {
// set zwave node status as disconnected
node.status({
updateNodeRedStatus(node, {
fill: "red",
shape: "ring",
text: "disconnecting"
Expand All @@ -498,8 +513,7 @@ module.exports = function(RED) {
});

this.on("error", function() {
// there are. no. russians. in afghanistacfg.
node.status({
updateNodeRedStatus(node, {
fill: "yellow",
shape: "ring",
text: "error"
Expand All @@ -509,10 +523,12 @@ module.exports = function(RED) {
/* =============== OpenZWave events ================== */
Object.keys(ozwEvents).forEach(function(key) {
zwsubscribe(node, key, function(event, data) {
// nuttin ;) we merely subscribe to have the NR node status update :)
// nuttin'! callback exists simply to update the node status
});
});



// set initial node status upon creation
updateNodeRedStatus(node);
}
Expand Down
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,29 @@ $ npm install node-red-openzwave-shared

#### Nodes added to Node-Red by this package

##### - *zwave-controller*

a unique CONFIG node that holds configuration for initializing OpenZWave and will act as the encapsulator for OZW access. As a node-red 'config' node, it cannot be added to a graph, but it acts as a singleton object that gets created in the the background when you add 'zwave-in' or 'zwave-out' nodes and configure them to point to a ZWave USB controller (usually /dev/ttyUSB0). It also holds the state for the openZWave library which is useful across flow edits (you surely don't want to wait for OpenZWave to reinitialise when you change your flows!)
##### - **zwave-controller**

This is a [config node](http://nodered.org/docs/creating-nodes/config-nodes) whose job is to hold the necessary data for initializing OpenZWave and act as the encapsulator for access to the OpenZWave API. When you add a 'zwave-in' or 'zwave-out' into your flows, a singleton instance of this node is created in the background, and you need to click on the 'controller' icon, in order to *configure where your ZWave USB controller is connected to* (for example `/dev/ttyUSB0` in Linux) and define a logging level.

##### - *zwave-in*

##### - **zwave-in**

A node that emits ZWave events as they are emitted from the ZWave controller. Use this node to get status feedback about what is happening in real time in your ZWave network. For example, the following message is injected into the NR flow when ZWave node #9, a binary switch, is turned on:

`{"topic":"zwave: value changed","payload":{"nodeid":9,"cmdclass":37,"instance":1,"cmdidx":0,"oldState":false,"currState":true}}`
```
{ "topic":"zwave: value changed",
"payload":{
"nodeid":9,
"cmdclass":37,
"instance":1,
"cmdidx":0,
"oldState":false,
"currState":true}}
```


##### - *zwave-out*
##### - **zwave-out**

Use this node to send arbitrary commands to the ZWave appliances. The four most common commands you're going to use are:

Expand All @@ -55,7 +65,7 @@ Use this node to send arbitrary commands to the ZWave appliances. The four most
You can invoke the full `OpenZWave::Manager` API, as long as the command is supported by openzwave-shared (see [this source file for a list of supported commands](https://github.com/OpenZWave/node-openzwave-shared/blob/master/src/openzwave.cc#L59)). You should also consult the [official OpenZWave::Manager class documentation.](http://www.openzwave.com/dev/classOpenZWave_1_1Manager.html)

The Node-Red message should have
- **topic**: set to the OpenZWave::Manager method name (eg. `healNetwork`)
- **topic**: set to the OpenZWave::Manager method name (eg. `healNetwork`). Method names are the same as in the official API, except the first letter is in lower case.
- **payload**: an array of the command arguments **in the correct order**.

Some examples:
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "node-red-contrib-openzwave",
"version": "1.2.0",
"version": "1.2.1",
"description": "ZWave for node-red through OpenZWave, the open source ZWave library",
"dependencies": {
"openzwave-shared": ">= 1.2.0",
"openzwave-shared": ">= 1.2.7",
"getmac": ">= 1.0.0"
},
"repository": {
Expand Down

0 comments on commit 990db59

Please sign in to comment.