mirror of
https://gitlab.silvrtree.co.uk/martind2000/SODashServer.git
synced 2025-01-26 22:36:17 +00:00
466 lines
13 KiB
JavaScript
466 lines
13 KiB
JavaScript
'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;
|
|
|