UNPKG

node-red-contrib-denon

Version:

Node-RED nodes for communicating with a Denon AVR.

169 lines (159 loc) 7.95 kB
~function (undefined) { module.exports = function (options) { var denon = require('denon-avr'); var machina = require('machina'); function receiveData(data) { connectionFSM && connectionFSM.emit('data', data); } var connectionFSM = new machina.Fsm({ debug: options.debug ? true : false, host: options.host || '127.0.0.1', port: options.port || 23, CONNECT_TIMEOUT: options.connectTimeout || options['connect-timeout'] || 10000, PING_TIMEOUT: options.pingTimeout || options['ping-timeout'] || 5000, PING_INTERVAL: options.pingInterval || options['ping-interval'] || 60000, RECONNECT_INTERVAL: options.reconnectInterval || options['reconnect-interval'] || 5000, initialize: function (options) { this.connected = false; this.disconnectingManually = false; }, namespace: "denon-connection", initialState: "uninitialized", states: { uninitialized: { "*": function () { this.deferUntilTransition(); this.transition("connecting"); } }, connecting: { _onEnter: function () { this.disconnectingManually = false; this.connected = false; this.emit('connecting'); this.debug && console.log('Connecting to: ' + this.host + ':' + this.port); this.connectingTimeout = setTimeout(function () { this.debug && console.log('Connecting timeouted!'); this.transition("scheduleReconnect"); }.bind(this), this.CONNECT_TIMEOUT); var connection = this.connection = new denon(new denon.transports.telnet({ host: this.host, port: this.port, debug: this.debug })); var self = this; connection.on('connect', function () { self.debug && console.log('Successfully connected!'); self.transition("connected"); }); function errorHandler(error) { self.debug && console.log('Error connecting, cause: ' + error); self.debug && console.log('Schedule reconnecting...'); self.handle('scheduleReconnect') } connection.getConnection().on('error', errorHandler); connection.on('timeout', errorHandler); connection.on('error', function (cause) { self.debug && console.log('Denon connection event[error], cause: ' + cause); if (!self.disconnectingManually) self.transition('scheduleReconnect'); }); connection.on('close', function (cause) { self.debug && console.log('Denon connection event[close], cause: ' + cause); if (!self.disconnectingManually) self.handle('scheduleReconnect'); }); connection.on('end', function (cause) { self.debug && console.log('Denon connection event[end], cause: ' + cause); if (!self.disconnectingManually) self.handle('scheduleReconnect'); }); connection.connect(); }, _onExit: function (connection) { clearTimeout(this.connectingTimeout); } }, scheduleReconnect: { _onEnter: function () { { this.connected = false; this.emit('disconnected'); this.connection && this.connection.getConnection().destroy(); this.connection = null; } this.debug && console.log('Scheduling reconnect'); clearTimeout(this.connectingTimeout); this.emit('reconnect'); this.reconnectTimer = setTimeout(function () { this.debug && console.log('Reconnecting...'); this.transition("connecting"); }.bind(this), this.RECONNECT_INTERVAL); }, _onExit: function (connection) { clearTimeout(this.reconnectTimer); } }, connected: { _onEnter: function () { if (!this.connected) { this.connected = true; this.emit('connected'); } this.debug && console.log('Starting ping interval'); this.pingTimer = setTimeout(function () { this.transition("pinging"); }.bind(this), this.PING_INTERVAL); this.connection.getConnection().on('data', receiveData); }, _onExit: function () { clearTimeout(this.pingTimer); const connection = this.connection.getConnection(); if(connection) { connection.off('data', receiveData); } } }, pinging: { _onEnter: function () { var self = this; this.pingTimeout = setTimeout(function () { self.debug && console.log('Ping timeout'); self.transition('connecting'); }.bind(this), this.PING_TIMEOUT); this.connection.getPowerState(function (error, pong) { if (error) { self.debug && console.log('Ping failed, error[' + error + ']'); if (!self.disconnectingManually) self.handle('scheduleReconnect'); } self.debug && console.log('Ping success, pong[' + pong + ']'); self.transition('connected'); }); }, _onExit: function () { clearTimeout(this.pingTimeout); } }, disconnecting: { _onEnter: function () { this.debug && console.log('Disconnecting'); this.connected = false; this.disconnectingManually = true; this.emit('disconnected'); this.connection && this.connection.getConnection().destroy(); this.connection = null; this.transition('uninitialized'); } } }, connect: function () { this.handle("_reset"); }, disconnect: function () { this.transition("disconnecting"); } }); return connectionFSM; } }();