/** * Created by Martin on 08/02/2016. */ 'use strict'; var mqtt = require('mqtt'); var Messaging = require('mqtt_over_websockets'); var log4js = require('log4js'); var logger = log4js.getLogger(); var mqttConfig = { orgId: 'qz0da4', userName: 'martind2000', appKey: 'MPReoa43', prefix: 'iot-2/type/Ti-CC3200/id/' }; function randomString(length) { return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1); } /* Projector: 'ProjectorISP15', lighting: 'LightingISP15', heating: 'HeatingISP15', */ var live = true; logger.warn('!!! Live? ', live); module.exports = { restartTimer : 0, pingTimer: 0, statuses: {}, sockets: null, wsClient: null, watches: {}, client: null, projector: live ? 'Projector' : 'ProjectorISP15', lighting: live ? 'Lighting' : 'LightingISP15', heating: live ? 'Heating' : 'HeatingISP15', myID: 0, connected: false, options: { // Keepalive: 3600, keepalive: 60, clientId: 'a:' + mqttConfig.orgId + ':' + Date.now(), username: mqttConfig.userName, password: new Buffer(mqttConfig.appKey) }, lightList: {o: 'frontLight', f: 'frontLight',n: 'backLight', g: 'backLight'}, updateStatus: function(id, packet) { this.statuses[id] = packet; logger.info('Statuses:', this.statuses); }, setEmitter: function(newEmitter) { this.emitter = newEmitter; }, doConnection: function(cb) { console.log('Do connection'); var self = this; if (this.client === null) { this.client = mqtt.connect('mqtt://' + 'silvrtree.co.uk', this.options); this.client.on('connect', function() { logger.info('Connected to SilvrBroker'); self.connected = this.connected; }); this.client.on('connected', function() { logger.debug('mqttConnect - doConnection - Connected'); }); this.client.on('disconnect', function(e) { logger.error('mqttConnect - doConnection - disconnect'); logger.error(e); }); this.client.on('error', function(e) { logger.error('mqttConnect - doConnection - disconnect'); logger.error(e); }); } return this; }, isConnected: function() { return this.connected; }, sendCommand: function(deviceID, command) { var payload = { id: 'd', text: command }; }, projectorOn: function(callback) { var packet; console.log('projectorOn:'); var _callback = callback || {}; if (!this.client) { return -1; } packet = {id: this.projector, status: true}; var destinationName = mqttConfig.prefix + this.projector + '/cmd/' + 'ON' + '/fmt/json'; this.client.publish(destinationName, 'ON', _callback); this.emitter.emit('sendSocket',packet); logger.debug('Storing status...'); this.updateStatus('projector', packet); }, projectorOff: function(callback) { var packet; var _callback = callback || {}; if (!this.client) { return -1; } packet = {id: this.projector, status: false}; var destinationName = mqttConfig.prefix + this.projector + '/cmd/' + 'OFF' + '/fmt/json'; this.client.publish(destinationName, 'OFF', _callback); this.emitter.emit('sendSocket',packet); console.log('Storing status...'); this.updateStatus('projector', packet); }, projectorCmd: function(id, callback) { var packet; var _callback = callback || {}; if (!this.client) { return -1; } var destinationName = mqttConfig.prefix + this.projector + '/cmd/' + id + '/fmt/json'; this.client.publish(destinationName, 'cmd', _callback); }, heatingOn: function(callback) { console.log('Turn heating on...'); var _callback = callback || null; if (!this.client) { return -1; } var destinationName = mqttConfig.prefix + this.heating + '/cmd/' + 'on' + '/fmt/json'; this.client.publish(destinationName, 'ON', _callback); this.emitter.emit('sendSocket',{id: this.heating, status: true}); }, heatingOff: function(callback) { var _callback = callback || {}; if (!this.client) { return -1; } var destinationName = mqttConfig.prefix + this.heating + '/cmd/' + 'off' + '/fmt/json'; this.client.publish(destinationName, 'OFF', _callback); this.emitter.emit('sendSocket',{id: this.heating, status: false}); }, lightingOn: function(id, callback) { var packet; console.log('lightingOn:' + id); var _callback = callback || null; if (!this.client) { return -1; } var destinationName = mqttConfig.prefix + this.lighting + '/cmd/' + id + '/fmt/json'; this.client.publish(destinationName, 'ON', _callback); packet = {id: this.lighting, device: id, status: true}; this.emitter.emit('sendSocket',packet); logger.debug('Storing status...'); this.updateStatus(this.lightList[id], packet); }, lightingOff: function(id, callback) { var packet; var _callback = callback || null; if (!this.client) { return -1; } var destinationName = mqttConfig.prefix + this.lighting + '/cmd/' + id + '/fmt/json'; this.client.publish(destinationName, 'OFF', _callback); packet = {id: this.lighting, device: id, status: false}; this.emitter.emit('sendSocket', packet); this.updateStatus(this.lightList[id], packet); }, lightingCommand: function(id, callback) { var packet; var _callback = callback || null; if (!this.client) { return -1; } var destinationName = mqttConfig.prefix + this.lighting + '/cmd/' + id + '/fmt/json'; this.client.publish(destinationName, 'cmd', _callback); }, setupEvents: function() { this.emitter.on('lightingOn', this.lightingOn); this.emitter.on('lightingOff', this.lightingOff); this.emitter.on('heatingOn', this.heatingOn); this.emitter.on('heatingOff', this.heatingOff); this.emitter.on('projectorOn', this.projectorOn); this.emitter.on('projectorOff', this.projectorOff); }, setupPing: function() { logger.warn('Starting ping timer...'); this.pingTimer = setTimeout(function() {this.ping();}.bind(this), 10000); }, ping: function() { //Logger.error('Ping!'); this.sendRefresh(); var now = new Date; var mod = 10000 - (now.getTime() % 10000); setTimeout(function() {this.ping();}.bind(this),mod + 10); }, sendRefresh: function() { // logger.debug('+ Send refresh', this.statuses); for (var item in this.statuses) { if (this.statuses.hasOwnProperty(item)) { console.log(this.statuses[item]); this.emitter.emit('sendSocket', this.statuses[item]); } } // logger.debug('+ Send refresh'); }, preRestartConnection: function() { logger.debug('Restart connection...'); //this.emitter.emit('restartMQTTSocket', this); //logger.debug(this); this.restartMQTTSocket(); }, startMQTTSocket:function() { logger.warn('Restarting socket?'); this.connectWS(); }, restartMQTTSocket: function() { this.wsClient.disconnect(); // setTimeout(this.startMQTTSocket.bind(this), 15000); }, connectWS: function(connectCB) { logger.debug('Going to connect WS'); var self = this; var hostname = 'silvrtree.co.uk'; var clientId = 'a:' + 'qz0da4' + ':' + Date.now(); var api_key = 'martind2000'; var auth_token = 'MPReoa43'; this.wsClient =new Messaging.Client(hostname, 8883, clientId); //var wsClient = new Messaging.Client(hostname, 8883, clientId); var wsClient = this.wsClient; var clientStatus = {connected: false, subscribed: false, deviceConnected: false}; var sensorData = {}; this.restartTimer = setTimeout(this.preRestartConnection.bind(this), 60000); wsClient.onMessageArrived = function(msg) { //logger.info("Message from :" + msg.destinationName); clearTimeout(self.restartTimer); self.restartTimer = setTimeout(self.preRestartConnection.bind(self), 60000); clientStatus.deviceConnected = true; sensorData = JSON.parse(msg.payloadString); // Logger.debug(sensorData); var temp = msg.destinationName.split('/'); if (self.watches.hasOwnProperty(temp[4])) { // Logger.info('Emit: ' + JSON.stringify({id:self.watches[temp[4]],sensorData:sensorData})); self.emitter.emit('sendSocket',{id: self.watches[temp[4]],sensorData: sensorData}); } }; wsClient.onConnectionLost = function(e) { logger.error('+ wsClient.onConnectionLost'); logger.error(e); logger.warn('Going to force a restart of the Socket.. Hold on.'); setTimeout(self.startMQTTSocket.bind(self), 15000); //self.emitter.emit('sendSocket',{id: 'deviceLost',data: e}); //var wsReconnectTimer = setTimeout(function() {logger.debug('TRYING TO RECONNECT TO MQTT');self.emitter.emit('connectWS');}.bind(this),30000); logger.error('- wsClient.onConnectionLost'); }; var connectOptions = {}; connectOptions.keepAliveInterval = 3600; connectOptions.useSSL = true; connectOptions.userName = api_key; connectOptions.password = auth_token; connectOptions.onSuccess = function() { clientStatus.connected = true; logger.info('MQTT connected to host: ' + wsClient.host + ' port : ' + wsClient.port + ' at ' + Date.now()); self.emitter.emit('clientStatusUpdated', clientStatus); self.emitter.emit('clientConnected', self.sockets); }; connectOptions.onFailure = function(e) { self.emitter.emit('sendSocket',{id: 'deviceNotConnecting'}); logger.error('wsClient onFailure', e); logger.error('MQTT connection failed at ' + Date.now() + '\nerror: ' + e.errorCode + ' : ' + e.errorMessage); //var wsReconnectTimer = setTimeout(function() {logger.debug('TRYING TO RECONNECT TO MQTT');self.emitter.emit('connectWS');}.bind(this),30000); }; logger.debug('about to connect to ' + wsClient.host); wsClient.connect(connectOptions); this.sockets = { getClientStatus: function() { return clientStatus; }, subscribe: function(deviceId, emitterId) { logger.debug('trying to subscribe'); var subscribeTopic = 'iot-2/type/Ti-CC3200/id/' + deviceId + '/evt/+/fmt/json'; logger.debug(subscribeTopic); var subscribeOptions = { qos: 0, onSuccess: function() { logger.info('subscribed to ' + subscribeTopic); clientStatus.subscribed = true; // $rootScope.$broadcast("clientStatusUpdated", clientStatus); self.emitter.emit('clientStatusUpdated', clientStatus); self.watches[deviceId] = emitterId; }, onFailure: function() { logger.error('Failed to subscribe to ' + subscribeTopic); logger.error('As messages are not available, visualization is not possible'); } }; /*If (IoTFconnector.prototype.clientStatus.subscribeTopic != "") { console.log("Unsubscribing to " + subscribeTopic); wsClient.unsubscribe(IoTFconnector.prototype.clientStatus.subscribeTopic); };*/ wsClient.subscribe(subscribeTopic, subscribeOptions); } }; return this.sockets; } };