UNPKG

thing-it-device-z-wave

Version:

[thing-it-node] Device Plugin for Z-wave Networks.

449 lines (385 loc) 16.7 kB
module.exports = { metadata: { family: 'z-wave', plugin: 'zWaveNetwork', label: 'Z-Wave Network', manufacturer: 'Z-Wave', discoverable: true, additionalSoftware: [{ name: "Open Z-Wave", description: "Free software library that interfaces with selected Z-Wave PC controllers.", url: "https://github.com/OpenZWave/open-zwave", version: "v1.3" }], actorTypes: [], sensorTypes: [], services: [], configuration: [] }, create: function () { return new ZWaveNetwork(); }, discovery: function () { return new ZWaveNetworkDiscovery(); } }; var os = require('os'); var q = require('q'); var _ = require('lodash'); var connectionRequested = false; var connected = false; /** * * @constructor */ function ZWaveNetworkDiscovery() { /** * * @param options */ ZWaveNetworkDiscovery.prototype.start = function () { if (this.node.isSimulated()) { this.timer = setInterval(function () { }.bind(this), 20000); } else { if (!this.zWave) { var ZWave = require('openzwave-shared'); this.zWave = new ZWave({ Logging: false, ConsoleOutput: false, SuppressRefresh: false, }); } this.nodes = []; this.zWave.on('driver ready', function (homeid) { this.logDebug('Scanning network with homeid 0x%s...', homeid.toString(16)); connected = true; this.currentHomeId = parseInt("0x" + homeid.toString(16)); }.bind(this)); this.zWave.on('driver failed', function () { this.logDebug('Failed to start driver.'); connected = false; connectionRequested = false; this.zWave.disconnect(); }.bind(this)); this.zWave.on('node added', function (nodeId) { this.nodes[nodeId] = { manufacturer: "unknown", manufacturerid: "unknown", product: "unknown", producttype: "unknown", productid: "unknown", type: "unknown", name: "unknown", loc: "unknown", ready: false, classes: {} }; this.logDebug('Node added: ' + nodeId); }.bind(this)); this.zWave.on('node ready', function (nodeId, nodeInfo) { this.logDebug('Node ready'); this.logDebug('ID : ' + nodeId); this.logDebug('Type : ' + nodeInfo.type); this.logDebug('Manufacturer: ' + nodeInfo.manufacturer); this.logDebug('Product : ' + nodeInfo.product); this.logDebug('Product Type: ' + nodeInfo.producttype); this.logDebug('Location : ' + nodeInfo.loc); this.nodes[nodeId].manufacturer = nodeInfo.manufacturer; this.nodes[nodeId].manufacturerid = nodeInfo.manufacturerid; this.nodes[nodeId].product = nodeInfo.product; this.nodes[nodeId].producttype = nodeInfo.producttype; this.nodes[nodeId].productid = nodeInfo.productid; this.nodes[nodeId].type = nodeInfo.type; this.nodes[nodeId].name = nodeInfo.name; this.nodes[nodeId].loc = nodeInfo.loc; this.nodes[nodeId].ready = true; }.bind(this)); this.zWave.on('scan complete', function () { this.logDebug('Scanning complete, adding devices to mesh.'); // Add the Z-Wave Network Device var zWaveNetwork = new ZWaveNetwork(); if (this.defaultConfiguration) { zWaveNetwork.configuration = _.cloneDeep(this.defaultConfiguration); } else { zWaveNetwork.configuration = {}; } zWaveNetwork.id = this.currentHomeId; zWaveNetwork.uuid = this.currentHomeId; zWaveNetwork.label = "Z-Wave Network " + this.currentHomeId; zWaveNetwork.configuration.homeId = this.currentHomeId; zWaveNetwork.configuration.nodeId = 1; zWaveNetwork.actors = []; // Add all ready Nodes depending on their types // TODO Add all remaining device classes for (n in this.nodes) { this.logDebug("++++++++ ", this.nodes[n].type); var actor; if ((this.nodes[n].type === 'Binary Power Switch') || (this.nodes[n].type === 'Binary Scene Switch')) { this.logDebug("Adding Binary Switch", this.nodes[n]); zWaveNetwork.actors.push(actor = { id: "binaryPowerSwitch" + n, label: "Binary Power Switch " + n, type: "binaryPowerSwitch", configuration: { nodeId: n, deviceType: this.nodes[n].type, manufacturer: this.nodes[n].manufacturer, product: this.nodes[n].product } }); } else if (this.nodes[n].type === 'Routing Multilevel Sensor') { this.logDebug("Adding Routing Multilevel Sensor", this.nodes[n]); zWaveNetwork.actors.push(actor = { id: "multilevelSensor" + n, label: "Multilevel Sensor " + n, type: "multilevelSensor", configuration: { nodeId: n, deviceType: this.nodes[n].type } }); } else if ((this.nodes[n].type === 'Multilevel Scene Switch') || (this.nodes[n].type === 'Multilevel Power Switch')) { this.logDebug("Adding Multilevel Switch", this.nodes[n]); zWaveNetwork.actors.push(actor = { id: "multilevelSceneSwitch" + n, label: "Multilevel Scene Switch " + n, type: "multilevelSceneSwitch", configuration: { nodeId: n, deviceType: this.nodes[n].type } }); } else if (this.nodes[n].type === 'Home Security Sensor') { this.logDebug("Adding Home Security Sensor", this.nodes[n]); zWaveNetwork.actors.push(actor = { id: "homeSecuritySensor" + n, label: "Home Security Sensor " + n, type: "homeSecuritySensor", configuration: { nodeId: n, deviceType: this.nodes[n].type } }); } else if (this.nodes[n].type === 'Static PC Controller') { //do nothing } else { this.logDebug("Adding Generic Device", this.nodes[n]); zWaveNetwork.actors.push(actor = { id: "generic" + n, label: "Generic Z-Wave Device " + n, type: "genericDevice", configuration: { nodeId: n, deviceType: this.nodes[n].type } }); } } this.advertiseDevice(zWaveNetwork); }.bind(this)); if (!connected && !connectionRequested) { connectionRequested = true; this.zWave.connect(getDriverPath()); } // TODO For now, need to be able to switch for Discovery or inherit from Device this.logLevel = 'debug'; } }; /** * * @param options */ ZWaveNetworkDiscovery.prototype.stop = function () { if (this.timer) { clearInterval(this.timer); } }; } /** * * @constructor */ function ZWaveNetwork() { /** * */ ZWaveNetwork.prototype.start = function () { var deferred = q.defer(); this.logDebug("****************************"); this.logDebug("********* HELLOOOO *********"); this.logDebug("****************************"); this.logDebug("Simulated: " + this.isSimulated()); if (this.isSimulated()) { this.logDebug("Started Z-Wave Network in simulated mode."); deferred.resolve(); } else { this.nodes = Array.apply(null, Array(256)).map(function () { }); this.logDebug("Starting up Z-Wave Device in non-simulated mode."); this.logDebug(this.configuration); try { if (!this.zWave) { this.logDebug("Loading Z-Wave library."); var ZWave = require('openzwave-shared'); this.zWave = new ZWave({ Logging: true, ConsoleOutput: false, // PollInterval: 60000, SuppressRefresh: false, }); this.logDebug("Z-Wave library loaded."); } } catch (e) { this.logError(e); } this.zWave.on('driver ready', function (homeid) { connected = true; this.logDebug('Scanning network with homeid %s...', homeid.toString(16)); }.bind(this)); this.zWave.on('driver failed', function () { this.logDebug('Failed to start driver.'); connected = false; connectionRequested = false; this.zWave.disconnect(); }.bind(this)); this.zWave.on('node ready', function (nodeid, nodeinfo) { this.logDebug('Node ready : ' + nodeid); this.logDebug('Manufacturer: ' + nodeinfo.manufacturer); this.logDebug('Product : ' + nodeinfo.product); this.logDebug('Product Type: ' + nodeinfo.producttype); this.logDebug('Location : ' + nodeinfo.loc); this.logDebug('Type : ' + nodeinfo.type); this.logDebug('Begin Classes for Node ' + nodeid); for (comclass in this.nodes[nodeid]['classes']) { var values = this.nodes[nodeid]['classes'][comclass]; this.logDebug('node' + nodeid + ': class ' + comclass); for (idx in values) this.logDebug('node' + nodeid + ': ' + values[idx]['label'] + '=' + values[idx]['value'] + ' (' + values[idx]['value_id'] + ')'); } this.logDebug('End Classes for Node ' + nodeid); }.bind(this)); this.zWave.on('node added', function (nodeid) { this.logDebug('Node added: ' + nodeid); }.bind(this)); this.zWave.on('node available', function (nodeid, nodeinfo) { if (!this.nodes[nodeid]) { this.nodes[nodeid] = {}; } this.nodes[nodeid].available = true; this.logDebug('Node available: ' + nodeid); this.logDebug('Manufacturer : ' + nodeinfo.manufacturer); this.logDebug('Product : ' + nodeinfo.product); this.logDebug('Product Type : ' + nodeinfo.producttype); this.logDebug('Location : ' + nodeinfo.loc); this.logDebug('Type : ' + nodeinfo.type); }.bind(this)); this.zWave.on('value added', function (nodeid, comclass, value) { if (this.nodes[nodeid] && this.nodes[nodeid].unit) { if (!this.nodes[nodeid]['classes']) { this.nodes[nodeid]['classes'] = {}; } if (!this.nodes[nodeid]['classes'][comclass]) this.nodes[nodeid]['classes'][comclass] = {}; this.nodes[nodeid]['classes'][comclass][value.index] = value; } }.bind(this)); this.zWave.on('value changed', function (nodeid, comclass, value) { if (this.nodes[nodeid] && this.nodes[nodeid].unit) { this.nodes[nodeid].unit.setStateFromZWave(comclass, value); } }.bind(this)); this.zWave.on('value refreshed', function (nodeid, comclass, value) { if (this.nodes[nodeid] && this.nodes[nodeid].unit) { this.nodes[nodeid].unit.setStateFromZWave(comclass, value); } }.bind(this)); this.zWave.on('node event', function (nodeid, event, valueId) { if (this.nodes[nodeid] && this.nodes[nodeid].unit) { this.nodes[nodeid].unit.handleEventFromZWave(event, valueId); } }.bind(this)); this.zWave.on('notification', function (nodeid, notif, help) { if (this.nodes[nodeid] && this.nodes[nodeid].unit) { this.nodes[nodeid].unit.handleNotificationFromZWave(notif, help); } }.bind(this)); this.zWave.on('scan complete', function () { this.logDebug("Scan complete, notifying actors."); var currentNode; for (n in this.nodes) { currentNode = this.nodes[n]; if (currentNode && currentNode.unit) { try { currentNode.unit.scanComplete(); } catch (e) { this.logDebug("Error notyfing node about scan complete", currentNode.unit.configuration, e); } finally { } } } }.bind(this)); if (!connected && !connectionRequested) { this.logDebug("Connecting to Z-Wave driver."); this.logDebug(getDriverPath()); connectionRequested = true; this.zWave.connect(getDriverPath()); this.logDebug("Connect called."); } else { this.logDebug("Z-Wave driver already loaded, notufying nodes."); var currentNode; for (n in this.nodes) { currentNode = this.nodes[n]; if (currentNode && currentNode.unit) { try { currentNode.unit.scanComplete(); } catch (e) { this.logDebug("Error notyfing node about scan complete", currentNode.unit.configuration, e); } finally { } } } } deferred.resolve(); } return deferred.promise; }; /** * */ ZWaveNetwork.prototype.stop = function () { var deferred = q.defer(); if (this.isSimulated()) { } else { this.zWave.disconnect(); } deferred.resolve(); return deferred.promise; }; /** * */ ZWaveNetwork.prototype.getState = function () { return {}; }; /** * */ ZWaveNetwork.prototype.setState = function () { }; } var driverPaths = { "darwin": '/dev/cu.usbmodem14611', "linux": '/dev/ttyACM0', "windows": '\\\\.\\COM3' } /** * * @returns {*} */ function getDriverPath() { console.log(">>>>>>>>>>>>> Driver for " + os.platform()); return driverPaths[os.platform()]; //return "/dev/cu.usbmodem1411"; }