diff --git a/client.js b/client.js index a944b12..462480b 100755 --- a/client.js +++ b/client.js @@ -16,7 +16,7 @@ function S101Socket(address, port) { self.port = port; self.socket = null; self.keepaliveInterval = 10; - self.codec = new S101Codec(); + self.codec = null; self.status = "disconnected"; } @@ -49,7 +49,7 @@ function S101Client(socket, server) { if (root !== undefined) { self.emit('emberTree', root); } - } catch(e) { + } catch (e) { self.emit("error", e); } }); @@ -90,7 +90,7 @@ function S101Server(address, port) { util.inherits(S101Server, EventEmitter); -S101Server.prototype.listen = function() { +S101Server.prototype.listen = function () { var self = this; if (self.status !== "disconnected") { return; @@ -113,7 +113,7 @@ S101Server.prototype.listen = function() { } -S101Server.prototype.addClient = function(socket) { +S101Server.prototype.addClient = function (socket) { var client = new S101Client(socket, this); this.emit("connection", client); } @@ -123,29 +123,29 @@ S101Server.prototype.addClient = function(socket) { * Client *****************************************************/ -S101Client.prototype.remoteAddress = function() { +S101Client.prototype.remoteAddress = function () { if (this.socket === undefined) { return; } return `${this.socket.remoteAddress}:${this.socket.remotePort}` } -S101Client.prototype.queueMessage = function(node) { +S101Client.prototype.queueMessage = function (node) { const self = this; this.addRequest(() => { self.sendBERNode(node); }); } -S101Client.prototype.makeRequest = function() { - if(this.activeRequest === null && this.pendingRequests.length > 0) { +S101Client.prototype.makeRequest = function () { + if (this.activeRequest === null && this.pendingRequests.length > 0) { this.activeRequest = this.pendingRequests.shift(); this.activeRequest(); this.activeRequest = null; } }; -S101Client.prototype.addRequest = function(cb) { +S101Client.prototype.addRequest = function (cb) { this.pendingRequests.push(cb); this.makeRequest(); } @@ -155,7 +155,7 @@ S101Client.prototype.addRequest = function(cb) { * Socket *****************************************************/ -S101Socket.prototype.connect = function(timeout = 2) { +S101Socket.prototype.connect = function (timeout = 2) { var self = this; if (self.status !== "disconnected") { return; @@ -171,6 +171,7 @@ S101Socket.prototype.connect = function(timeout = 2) { }, 1000 * timeout); } + self.codec = new S101Codec(); self.socket = net.createConnection(self.port, self.address, () => { winston.debug('socket connected'); @@ -178,10 +179,9 @@ S101Socket.prototype.connect = function(timeout = 2) { clearTimeout(self._timer); } - - setInterval(() => { + self.keepaliveIntervalTimer = setInterval(() => { self.sendKeepaliveRequest(); - }, 1000 * self.keepaliveInterval ); + }, 1000 * self.keepaliveInterval); self.codec.on('keepaliveReq', () => { self.sendKeepaliveResponse(); @@ -196,7 +196,7 @@ S101Socket.prototype.connect = function(timeout = 2) { if (root !== undefined) { self.emit('emberTree', root); } - } catch(e) { + } catch (e) { self.emit("error", e); } }); @@ -219,20 +219,32 @@ S101Socket.prototype.connect = function(timeout = 2) { } -S101Socket.prototype.isConnected = function() { +S101Socket.prototype.isConnected = function () { return ((this.socket !== null) && (this.socket !== undefined)); } -S101Socket.prototype.disconnect = function() { +S101Socket.prototype.disconnect = function () { var self = this; - if (self.isConnected()) { - self.socket.destroy(); - self.socket = null; - self.status = "disconnected"; + + if (!self.isConnected()) { + return Promise.resolve(); } -} + return new Promise((resolve, reject) => { + self.socket.once('close', () => { + self.codec = null; + self.socket = null; + resolve(); + }); + self.socket.once('error', reject); + clearInterval(self.keepaliveIntervalTimer); + clearTimeout(self._timeout); + self.socket.end(); + self.status = "disconnected"; + } + ); +}; -S101Socket.prototype.sendKeepaliveRequest = function() { +S101Socket.prototype.sendKeepaliveRequest = function () { var self = this; if (self.isConnected()) { self.socket.write(self.codec.keepAliveRequest()); @@ -240,7 +252,7 @@ S101Socket.prototype.sendKeepaliveRequest = function() { } } -S101Socket.prototype.sendKeepaliveResponse = function() { +S101Socket.prototype.sendKeepaliveResponse = function () { var self = this; if (self.isConnected()) { self.socket.write(self.codec.keepAliveResponse()); @@ -248,7 +260,7 @@ S101Socket.prototype.sendKeepaliveResponse = function() { } } -S101Socket.prototype.sendBER = function(data) { +S101Socket.prototype.sendBER = function (data) { var self = this; if (self.isConnected()) { var frames = self.codec.encodeBER(data); @@ -258,8 +270,8 @@ S101Socket.prototype.sendBER = function(data) { } } -S101Socket.prototype.sendBERNode = function(node) { - var self=this; +S101Socket.prototype.sendBERNode = function (node) { + var self = this; if (!node) return; var writer = new BER.Writer(); node.encode(writer); @@ -267,6 +279,5 @@ S101Socket.prototype.sendBERNode = function(node) { } - module.exports = { S101Socket, S101Server, S101Client }; diff --git a/device.js b/device.js index a4cbf3d..35b4b91 100755 --- a/device.js +++ b/device.js @@ -42,12 +42,16 @@ function DeviceTree(host, port = 9000) { }); self.client.on('emberTree', (root) => { - if(root instanceof ember.InvocationResult) { + if (root instanceof ember.InvocationResult) { self.emit('invocationResult', root) - if (self._debug) {console.log("Received InvocationResult", root);} - }else{ + if (self._debug) { + console.log("Received InvocationResult", root); + } + } else { self.handleRoot(root); - if (self._debug) {console.log("Received root", root);} + if (self._debug) { + console.log("Received root", root); + } } if (self.callback) { @@ -59,22 +63,22 @@ function DeviceTree(host, port = 9000) { util.inherits(DeviceTree, EventEmitter); -DecodeBuffer = function(packet) { - var ber = new BER.Reader(packet); - return ember.Root.decode(ber); +var DecodeBuffer = function (packet) { + var ber = new BER.Reader(packet); + return ember.Root.decode(ber); } -DeviceTree.prototype.saveTree = function(f) { +DeviceTree.prototype.saveTree = function (f) { var writer = new BER.Writer(); this.root.encode(writer); f(writer.buffer); } -DeviceTree.prototype.isConnected = function() { +DeviceTree.prototype.isConnected = function () { return ((this.client !== undefined) && (this.client.isConnected())); } -DeviceTree.prototype.connect = function(timeout = 2) { +DeviceTree.prototype.connect = function (timeout = 2) { return new Promise((resolve, reject) => { this.callback = (e) => { if (e === undefined) { @@ -89,8 +93,7 @@ DeviceTree.prototype.connect = function(timeout = 2) { }); } -DeviceTree.prototype.expand = function(node) -{ +DeviceTree.prototype.expand = function (node) { let self = this; if (node == null) { return Promise.reject(new Error("Invalid null node")); @@ -101,7 +104,9 @@ DeviceTree.prototype.expand = function(node) return self.getDirectory(node).then((res) => { let children = node.getChildren(); if ((res === undefined) || (children === undefined) || (children === null)) { - if (self._debug) {console.log("No more children for ", node);} + if (self._debug) { + console.log("No more children for ", node); + } return; } let p = Promise.resolve(); @@ -110,7 +115,9 @@ DeviceTree.prototype.expand = function(node) // Parameter can only have a single child of type Command. continue; } - if (self._debug) {console.log("Expanding child", child);} + if (self._debug) { + console.log("Expanding child", child); + } p = p.then(() => { return self.expand(child).catch((e) => { // We had an error on some expansion @@ -123,7 +130,7 @@ DeviceTree.prototype.expand = function(node) }); } -DeviceTree.prototype.getDirectory = function(qnode) { +DeviceTree.prototype.getDirectory = function (qnode) { var self = this; if (qnode == null) { self.root.clear(); @@ -143,20 +150,24 @@ DeviceTree.prototype.getDirectory = function(qnode) { reject(error); } else { - if (self._debug) {console.log("Received getDirectory response", node);} + if (self._debug) { + console.log("Received getDirectory response", node); + } resolve(node); // make sure the info is treated before going to next request. } self.finishRequest(); }; - if (self._debug) {console.log("Sending getDirectory", qnode);} + if (self._debug) { + console.log("Sending getDirectory", qnode); + } self.callback = cb; self.client.sendBERNode(qnode.getDirectory()); }); }); } -DeviceTree.prototype.invokeFunction = function(fnNode, params) { +DeviceTree.prototype.invokeFunction = function (fnNode, params) { var self = this return new Promise((resolve, reject) => { self.addRequest((error) => { @@ -167,37 +178,43 @@ DeviceTree.prototype.invokeFunction = function(fnNode, params) { } let cb = (error, result) => { - self.clearTimeout(); + self.clearTimeout(); if (error) { reject(error); } else { - if (DEBUG) {console.log("InvocationResult", result);} - resolve(result); + if (DEBUG) { + console.log("InvocationResult", result); + } + resolve(result); } self.finishRequest(); }; - if (self._debug) {console.log("Invocking function", fnNode);} + if (self._debug) { + console.log("Invocking function", fnNode); + } self.callback = cb; self.client.sendBERNode(fnNode.invoke(params)); }); }) } -DeviceTree.prototype.disconnect = function() { +DeviceTree.prototype.disconnect = function () { if (this.client !== undefined) { return this.client.disconnect(); } } -DeviceTree.prototype.makeRequest = function() { - var self=this; - if(self.activeRequest === null && self.pendingRequests.length > 0) { +DeviceTree.prototype.makeRequest = function () { + var self = this; + if (self.activeRequest === null && self.pendingRequests.length > 0) { self.activeRequest = self.pendingRequests.shift(); - const t = function(id) { - if (self._debug) {console.log(`Making request ${id}`,Date.now());} + const t = function (id) { + if (self._debug) { + console.log(`Making request ${id}`, Date.now()); + } self.timeout = setTimeout(() => { self.timeoutRequest(id); }, self.timeoutValue); @@ -208,40 +225,42 @@ DeviceTree.prototype.makeRequest = function() { } }; -DeviceTree.prototype.addRequest = function(cb) { - var self=this; +DeviceTree.prototype.addRequest = function (cb) { + var self = this; self.pendingRequests.push(cb); self.makeRequest(); } -DeviceTree.prototype.clearTimeout = function() { - if(this.timeout != null) { +DeviceTree.prototype.clearTimeout = function () { + if (this.timeout != null) { clearTimeout(this.timeout); this.timeout = null; } } -DeviceTree.prototype.finishRequest = function() { - var self=this; +DeviceTree.prototype.finishRequest = function () { + var self = this; self.callback = undefined; self.clearTimeout(); self.activeRequest = null; self.makeRequest(); } -DeviceTree.prototype.timeoutRequest = function(id) { +DeviceTree.prototype.timeoutRequest = function (id) { var self = this; self.root.cancelCallbacks(); self.activeRequest(new errors.EmberTimeoutError(`Request ${id !== undefined ? id : ""} timed out`)); } -DeviceTree.prototype.handleRoot = function(root) { - var self=this; +DeviceTree.prototype.handleRoot = function (root) { + var self = this; - if (self._debug) {console.log("handling root", JSON.stringify(root));} + if (self._debug) { + console.log("handling root", JSON.stringify(root)); + } var callbacks = self.root.update(root); - if(root.elements !== undefined) { - for(var i=0; i { self.addRequest((error) => { - if(error) { + if (error) { reject(error); self.finishRequest(); return; } self.root.getNodeByPath(self.client, path, (error, node) => { - if(error) { + if (error) { reject(error); } else { resolve(node); @@ -354,34 +373,33 @@ DeviceTree.prototype.getNodeByPath = function(path) { }); } -DeviceTree.prototype.subscribe = function(node, callback) { - if(node instanceof ember.Parameter && node.isStream()) { +DeviceTree.prototype.subscribe = function (node, callback) { + if (node instanceof ember.Parameter && node.isStream()) { // TODO: implement } else { node.addCallback(callback); } } -DeviceTree.prototype.unsubscribe = function(node, callback) { - if(node instanceof ember.Parameter && node.isStream()) { +DeviceTree.prototype.unsubscribe = function (node, callback) { + if (node instanceof ember.Parameter && node.isStream()) { // TODO: implement } else { node.addCallback(callback); } } -DeviceTree.prototype.setValue = function(node, value) { - var self=this; +DeviceTree.prototype.setValue = function (node, value) { + var self = this; return new Promise((resolve, reject) => { - if((!(node instanceof ember.Parameter)) && - (!(node instanceof ember.QualifiedParameter))) - { + if ((!(node instanceof ember.Parameter)) && + (!(node instanceof ember.QualifiedParameter))) { reject(new errors.EmberAccessError('not a property')); } else { // if (this._debug) { console.log('setValue', node.getPath(), value); } self.addRequest((error) => { - if(error) { + if (error) { self.finishRequest(); reject(error); return; @@ -399,7 +417,9 @@ DeviceTree.prototype.setValue = function(node, value) { }; self.callback = cb; - if (this._debug) { console.log('setValue sending ...', node.getPath(), value); } + if (this._debug) { + console.log('setValue sending ...', node.getPath(), value); + } self.client.sendBERNode(node.setValue(value)); }); } @@ -410,9 +430,9 @@ function TreePath(path) { this.identifiers = []; this.numbers = []; - if(path !== undefined) { - for(var i=0; i