'use strict'; var calendar = require('./calendarInterface'); var mqttClient = require('../mqtt/mqttClient'); var cron = require('node-cron'); var log4js = require('log4js'); var logger = log4js.getLogger(); var events = require('events'); var eventBus ; var util = require('util'); var apn = require('apn'); var jsonfile = require('jsonfile'); var file = 'data/iostokens.json'; require('sugar'); var apnService = new apn.connection({ key: 'conf/key.pem', cert: 'conf/cert.pem', production: false }); apnService.on('connected', function() { logger.debug('APN Connected'); }); apnService.on('transmitted', function(notification, device) { logger.debug('APN Notification transmitted to:' + device.token.toString('hex')); }); apnService.on('transmissionError', function(errCode, notification, device) { logger.error('APNNotification caused error: ' + errCode + ' for device ', device, notification); if (errCode === 8) { logger.error('A error code of 8 indicates that the device token is invalid. This could be for a number of reasons - are you using the correct environment? i.e. Production vs. Sandbox'); } }); apnService.on('timeout', function() { logger.debug('Connection Timeout'); }); apnService.on('disconnected', function() { logger.debug('Disconnected from APNS'); }); apnService.on('socketError', logger.error); var officeController = function(neweventBus) { this.iosTokens = []; this.masterCRON = {}; logger.debug((typeof neweventBus)); if ((typeof neweventBus !== 'undefined') && (neweventBus !== null)) { eventBus = neweventBus; } else { eventBus = new events(); } console.log('~~~ officeController'); this.cloneObject = function(from, to) { if (Object.keys(from).length !== 0) { for (var key in from) { if (from.hasOwnProperty(key)) { if (key !== 'cronJOBS') { to[key] = from[key]; } } } } }; jsonfile.readFile(file, function(err, obj) { if (err) { logger.error(err); } this.iosTokens = obj; }.bind(this)); this.saveTimer = 0; var self = this; this.schedule = {}; this.todaysList = {}; this.calendarControl = new calendar.calendarInterface(); this.calendarControl.getRoomStatusV2((todaysList) => { this.todaysList = todaysList; this.setupNextMeeting(todaysList); }); this.mqtt = new mqttClient.mqttClient(); this.task = cron.schedule('* * * * *', function() { var n = new Date(); var curMeeting = {}; this.cloneObject(this.todaysList.current, curMeeting); curMeeting.cronJobs = {}; eventBus.emit('sendSocket', {id: 'calendar',current: curMeeting}); }.bind(this)); this.task = cron.schedule('*/5 * * * *', function() { //This.task = cron.schedule('*/2 * * * *', function() { this.calendarControl.getRoomStatusV2((todaysList) => { var _iEnd; var _iStart; var _now; logger.debug('+ getRoomStatusV2 CB'); if (Object.has(todaysList.current, 'uid')) { if (Object.has(this.schedule, todaysList.current.uid)) { todaysList.current.actualEnd = this.schedule[todaysList.current.uid].actualEnd; } } else { // There is no current meeting, check if there should be a meeting _now = new Date(); for (var item in this.schedule) { if (this.schedule.hasOwnProperty(item)) { if (!this.schedule[item].hasOwnProperty('done')) { _iStart = Date.create(this.schedule[item].dtstart); _iEnd = Date.create(this.schedule[item].actualEnd).addSeconds(-1); logger.debug(_now, ' between ', _iStart, _iEnd); if (_now.isBetween(_iStart, _iEnd)) { todaysList.current = this.schedule[item]; } } else { logger.debug('Meeting ', item , ' is done with.'); } } } } this.todaysList = todaysList; this.setupNextMeeting(todaysList); var data = todaysList; data.id = 'calendarData'; eventBus.emit('sendSocket', data); logger.debug('- getRoomStatusV2 CB'); }); }.bind(this)); eventBus.on('setupNextMeeting', this.setupNextMeeting.bind(this, this.todaysList)); logger.debug('Todayslist', this.todaysList); eventBus.on('cleanUp', (id) => { logger.debug('+ => cleanUp'); this.cleanUpMeeting(id); }); eventBus.on('announce', (meeting) => { logger.debug('+ => announce'); this.announceMeetingEnd(meeting); }); }; officeController.prototype.saveData = function() { jsonfile.writeFile(file, this.iosTokens, function(err, obj) { if (err) { logger.error(err); } }); }; officeController.prototype.sendiOSAPN = function(packet) { logger.info('Sending the iOS Push Notifications.'); var note = new apn.notification(); note.setAlertText(packet.msg); note.setAlertTitle('Smart Office'); note.setBadge(1); note.setSound('dong.aiff'); note.badge = 1; apnService.pushNotification(note, this.iosTokens); }; officeController.prototype.announceMeetingEnd = function(meeting) { logger.debug('announceMeetingEnd',meeting); var msg = ['The meeting "', meeting.summary, '" is due to end in five minutes. Would you like to extend it?'].join(''); var packet = {id: 'announce', msg: msg, uid: meeting.uid}; eventBus.emit('sendSocket', packet); this.sendiOSAPN(packet); }; officeController.prototype.cleanUpMeeting = function(id) { this.schedule[id].done = true; delete this.masterCRON[id]; eventBus.emit('sendSocket', {id: 'calendar', current: {}, finished: 'true'}); }; officeController.prototype.createMeeting = function(obj,delayStart) { var newMeeting = obj; var _delayStart = delayStart || false; var cronStartStr; var uid = newMeeting.uid; var now = new Date.create(); var self = this; if (_delayStart) { cronStartStr = now.addSeconds(5).format('{s} {m} {H} * * *'); } else { cronStartStr = newMeeting.cronStart; } if (!this.masterCRON.hasOwnProperty(uid)) { this.masterCRON[uid] = {start: null, stop: null, alert: null}; } this.masterCRON[uid].start = cron.schedule(cronStartStr, function() { var n = new Date(); logger.debug('MEETING STARTED!!!!' , n); var key = Object.keys(self.schedule)[0]; var curMeeting = {}; self.cloneObject(self.schedule[key], curMeeting); // Lets turn on some lights! eventBus.emit('lightingOn','o'); eventBus.emit('lightingOn','n'); logger.debug('masterCRON', self.masterCRON); eventBus.emit('sendSocket', {id: 'calendar',current: curMeeting}); }, true); this.masterCRON[uid].alert = cron.schedule(newMeeting.cronAlert, function() { logger.error('ORIGINAL MEETING ends in 5 minutes'); logger.debug(this); // Announce there are five minutes remaining.. eventBus.emit('announce', newMeeting); }.bind(this), true); this.masterCRON[uid].stop = cron.schedule(newMeeting.cronStop, function() { var n = new Date(); logger.debug('ORIGINAL MEETING ENDED' + n); this.masterCRON[uid].start = null; this.masterCRON[uid].stop = null; this.masterCRON[uid].alert = null; eventBus.emit('lightingOn','f'); eventBus.emit('lightingOn','g'); logger.debug(this.masterCRON[uid]); eventBus.emit('cleanUp',uid); }.bind(this), true); this.schedule[newMeeting.uid] = newMeeting; newMeeting = null; }; officeController.prototype.setupNextMeeting = function(calData) { logger.debug('+ setupNextMeeting'); var self = this; if (Object.keys(calData.current).length > 0) { if (this.schedule.hasOwnProperty(calData.current.uid)) { logger.debug('Current Meeting exists in schedule'); logger.debug(this.schedule[calData.current.uid]); } else { logger.debug('Current Meeting does NOT exist in schedule'); this.createMeeting(calData.current, true); } } if (calData.upcoming.length > 0) { for (var uCount = 0; uCount < calData.upcoming.length; uCount++) { var uEntry = calData.upcoming[uCount]; if (this.schedule.hasOwnProperty(uEntry.uid)) { logger.debug('Upcoming Meeting exists in schedule'); // Lets check to see if it's changed in anyway.. var origEntry, origStart, origEnd, newStart, newEnd; origEntry = this.schedule[uEntry.uid]; origStart = Date.create(origEntry.dtstart); origEnd = Date.create(origEntry.dtend); newStart = Date.create(uEntry.dtstart); newEnd = Date.create(uEntry.dtend); if ((origStart.getTime() !== newStart.getTime()) || (origEnd.getTime() !== newEnd.getTime())) { logger.error('WE HAVE A CHANGED ENTRY!!'); self.masterCRON[uEntry.uid].start.destroy(); self.masterCRON[uEntry.uid].stop.destroy(); self.masterCRON[uEntry.uid].alert.destroy(); origEntry = uEntry; this.createMeeting(origEntry); } } else { logger.debug('Upcoming meeting does NOT exist in schedule'); var newMeeting = uEntry; this.createMeeting(newMeeting); } } } }; officeController.prototype.startController = function(eventBus) { console.log('Starting.'); getRoomStatus(); this.timer = setInterval(function() { getRoomStatus(); }, 300000); }; officeController.prototype.stopController = function() { console.log('Stopping.'); clearInterval(this.timer); }; officeController.prototype.returnCalendar = function() { var exportList; exportList = this.calendarControl.getCachedStatus(); logger.debug(exportList); return exportList; }; officeController.prototype.registeriOSToken = function(id) { if (this.iosTokens.indexOf(id) === -1) { this.iosTokens.push(id); logger.info('C - IOS Device registered.'); clearTimeout(this.saveTimer); this.saveTimer = setTimeout(function() {this.saveData();}.bind(this), 10000); } }; officeController.prototype.extendMeeting = function(data) { logger.debug('+ officeController.extendMeeting'); var self = this; if (Object.has(this.todaysList.current, 'uid')) { if (this.todaysList.current.uid === data.uid) { var newActualEnd = Date.create(this.todaysList.current.actualEnd).addMinutes(data.extendBy); this.todaysList.current.actualEnd = newActualEnd; logger.debug(this.todaysList); if (this.schedule.hasOwnProperty(data.uid)) { logger.info('updating ', data.uid); var updateSchedule = this.schedule[data.uid]; updateSchedule.actualEnd = newActualEnd; updateSchedule.timeEnd = updateSchedule.actualEnd.format('{24hr}:{mm}:{ss} {tt}'); updateSchedule.cronStop = updateSchedule.actualEnd.format('{m} {H} * * *'); var fiveMins = Date.create(updateSchedule.actualEnd).addMinutes('-5'); updateSchedule.cronAlert = fiveMins.format('{m} {H} * * *'); logger.debug('cronAlert now ' + updateSchedule.cronAlert); logger.debug('cronStop now ' + updateSchedule.cronStop); self.masterCRON[data.uid].stop.destroy(); self.masterCRON[data.uid].alert.destroy(); logger.debug('!!Extended', self.masterCRON); self.masterCRON[data.uid].alert = cron.schedule(updateSchedule.cronAlert, function() { logger.error('EXTENDED MEETING ends in 5 minutes'); // Announce there are five minutes remaining.. eventBus.emit('announce', updateSchedule); }.bind(this), true); self.masterCRON[data.uid].stop = cron.schedule(updateSchedule.cronStop, function() { var n = new Date(); logger.debug('EXTENDED MEETING ENDED' + n); self.masterCRON[data.uid].start.destroy(); self.masterCRON[data.uid].stop.destroy(); self.masterCRON[data.uid].alert.destroy(); eventBus.emit('lightingOn','f'); eventBus.emit('lightingOn','g'); logger.debug(self.masterCRON[data.uid]); eventBus.emit('cleanUp',data.uid); }.bind(this), true); this.schedule[data.uid] = updateSchedule; this.todaysList.current = updateSchedule; eventBus.emit('sendSocket', {id: 'calendar',current: this.todaysList.current, extended: 'true'}); logger.warn('-=-=-=-=-'); logger.debug(this.schedule); logger.warn('#=#=#=#=#'); logger.debug(this.todaysList); } } } logger.debug('- officeController.extendMeeting'); }; var meetingStates = { STARTING: 0, INPROGRESS: 1, NONE: 2, FINISHED: 3 }; function getRoomStatus() { return; // Var calendarControl = new calendar.calendarInterface(); // var status = calendarControl.getRoomStatusV2(); var status = officeController.calendarControl.getRoomStatusV2(); if (status == meetingStates.STARTING) { console.log('Meeting about to start - turning on.'); this.mqtt.projectorOn(); this.mqtt.lightsOn(); } if (status == meetingStates.INPROGRESS) { console.log('Meeting in progress - do nothing.'); } if (status == meetingStates.NONE) { console.log('No meeting - do nothing.'); } if (status == meetingStates.FINISHED) { console.log('No meeting - do nothing.'); this.mqtt.projectorOff(); this.mqtt.lightsOff(); } } module.exports.officeController = officeController;