Added change detection and automatic reloading for config.js

Centralized console logging
This commit is contained in:
Mark van Renswoude 2016-08-07 11:02:21 +02:00
parent 93b5e9d7c6
commit d0baa00dfd
8 changed files with 183 additions and 44 deletions

View File

@ -1,5 +1,6 @@
var util = require('util');
var http = require('http');
var logger = require('./logger');
var BaseProcessor = require('./baseprocessor');
@ -51,7 +52,7 @@ BaseHTTPStreamProcessor.prototype.run = function()
req.on('error', function(e)
{
console.log(e);
logger.error(e);
doCleanup();
});

View File

@ -1,7 +1,6 @@
var http = require('http');
var stream = require('stream');
var config = require('./config');
var logger = require('./logger');
function runCommand(command, displayName, callback)
@ -18,7 +17,7 @@ function runCommand(command, displayName, callback)
if (command.url)
{
console.log('Running command: ' + (command.displayName ? command.displayName : displayName));
logger.verbose('Running command: ' + (command.displayName ? command.displayName : displayName));
req = http.request(command.url, function(res)
{
@ -28,7 +27,7 @@ function runCommand(command, displayName, callback)
req.on('error', function(e)
{
console.log(e);
logger.error(e);
wait();
});

170
index.js
View File

@ -1,70 +1,174 @@
var moment = require('moment');
var fs = require('fs');
var chokidar = require('chokidar');
var express = require('express');
var config = require('./config');
var capture = require('./capture');
var logger = require('./logger');
var app = express();
var server = null;
var serverPort = 0;
var config = null;
var configError = null;
// Some sanity checking to avoid issues later on
if (!config.cams)
config.cams = [];
var loadConfig = function()
{
try
{
// Unload existing config
if (config !== null)
{
var name = require.resolve('./config');
delete require.cache[name];
}
config = require('./config');
// Some sanity checking to avoid issues later on
if (!config.cams)
config.cams = [];
capture.init(config.cams);
configError = null;
if (server === null || config.port !== serverPort)
{
if (server !== null)
{
server.close();
server = null;
}
serverPort = config.port;
server = app.listen(config.port, function()
{
logger.info('SecurityCam.js running on port ' + config.port);
});
}
}
catch (e)
{
config = null;
configError = e.message;
// Don't close the server if it was running before. The port is
// unlikely to change, and this will allow the status page to
// report the error.
logger.error('Error loading configuration:');
// Tried to use e.stack to get more information about where the syntax
// error is, but it seems SyntaxError doesn't provide it yet:
// http://stackoverflow.com/questions/20570477/line-number-of-syntaxerror-in-node-js
logger.error(e);
}
}
capture.init(config.cams);
app.get('/', function(req, res)
{
res.send(JSON.stringify(
if (config !== null)
{
status: 'running',
cams: Object.keys(config.cams)
}));
res.send(JSON.stringify(
{
status: 'running',
cams: Object.keys(config.cams)
}));
}
else if (configError !== null)
{
res.send(JSON.stringify(
{
status: 'error',
error: configError
}));
}
else
{
res.send(JSON.stringify(
{
status: 'error',
error: 'An unhandled error has occured. See the console for more information, hopefully.'
}));
}
});
app.get('/capture', function(req, res)
{
var now = moment();
var cams = [];
for (var camId in config.cams)
if (config !== null)
{
if (config.cams.hasOwnProperty(camId))
var now = moment();
var cams = [];
for (var camId in config.cams)
{
cams.push(camId);
capture.start(camId, config.cams[camId], now);
if (config.cams.hasOwnProperty(camId))
{
cams.push(camId);
capture.start(camId, config.cams[camId], now);
}
}
logger.info('Started capture for: ' + cams.join(', '));
res.send(JSON.stringify(cams));
}
else
{
res.status(500).send({ error: 'See / for more information' });
}
console.log('Started capture for: ' + cams.join(', '));
res.send(JSON.stringify(cams));
});
app.get('/capture/:camId', function(req, res)
{
var camId = req.params.camId;
if (config.cams.hasOwnProperty(camId))
if (config !== null)
{
capture.start(camId, config.cams[camId], moment());
var camId = req.params.camId;
console.log('Started capture for: ' + camId);
res.send(JSON.stringify([camId]));
if (config.cams.hasOwnProperty(camId))
{
capture.start(camId, config.cams[camId], moment());
logger.info('Started capture for: ' + camId);
res.send(JSON.stringify([camId]));
}
else
{
logger.warning('Cam not found: ' + camId);
res.sendStatus(404);
}
}
else
{
console.log('Cam not found: ' + camId);
res.sendStatus(404);
res.status(500).send({ error: 'See / for more information' });
}
});
var watcher = chokidar.watch('./config.js');
var firstLoad = true;
app.listen(config.port, function()
watcher.on('all', function()
{
console.log('SecurityCam.js running on port ' + config.port);
});
if (!firstLoad)
logger.verbose('Configuration change detected, reloading...');
loadConfig();
firstLoad = false;
});
// It looks like the add event from chokidar will always be fired immediately,
// at least on Windows, but I couldn't find anything in the documentation so
// let's not make that assumption and double-check.
setTimeout(function()
{
if (firstLoad)
{
loadConfig();
firstLoad = false;
}
}, 1000);

32
logger.js Normal file
View File

@ -0,0 +1,32 @@
var moment = require('moment');
var logger = {};
function log(level, message)
{
console.log('[' + moment().format() + '] ' + level + ': ' + message);
}
logger.verbose = function(message)
{
log('Verbose', message);
}
logger.info = function(message)
{
log('Info', message);
}
logger.warning = function(message)
{
log('Warning', message);
}
logger.error = function(message)
{
log('Error', message);
}
module.exports = logger;

View File

@ -9,6 +9,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"chokidar": "^1.6.0",
"express": "^4.14.0",
"file-on-write": "^1.1.1",
"fluent-ffmpeg": "^2.1.0",

View File

@ -1,10 +1,10 @@
var fs = require('fs');
var util = require('util');
var stream = require('stream');
var FfmpegCommand = require('fluent-ffmpeg');
var helpers = require('./helpers');
var logger = require('./logger');
var BaseProcessor = require('./baseprocessor');
@ -30,7 +30,7 @@ FFMPEGProcessor.prototype.run = function()
{
fs.rename(tempFilename, filename, function(err)
{
console.log('Error: could not move ' + tempFilename + ' to ' + filename + ': ' + err.message);
logger.error('Could not move ' + tempFilename + ' to ' + filename + ': ' + err.message);
self.doEnd();
});
}
@ -55,7 +55,7 @@ FFMPEGProcessor.prototype.run = function()
command.on('error', function(err, stdout, stderr)
{
console.log('Error: FFmpeg output:' + err.message);
logger.error('FFmpeg output:' + err.message);
cleanup();
});

View File

@ -5,6 +5,7 @@ var stream = require('stream');
var FfmpegCommand = require('fluent-ffmpeg');
var helpers = require('./helpers');
var logger = require('./logger');
var BaseHTTPStreamProcessor = require('./basehttpstreamprocessor');
@ -43,7 +44,7 @@ HTTPFFMPEGProcessor.prototype.run = function()
command.on('error', function(err, stdout, stderr)
{
console.log('Error: FFmpeg output:' + err.message);
logger.error('FFmpeg output:' + err.message);
});
command.run();
@ -68,7 +69,7 @@ HTTPFFMPEGProcessor.prototype.cleanup = function()
fs.rename(this.tempFilename, this.filename, function(err)
{
console.log('Error: could not move ' + this.tempFilename + ' to ' + this.filename + ': ' + err.message);
logger.error('Could not move ' + this.tempFilename + ' to ' + this.filename + ': ' + err.message);
});
}

View File

@ -2,6 +2,7 @@ var fs = require('fs');
var util = require('util');
var helpers = require('./helpers');
var logger = require('./logger');
var BaseHTTPStreamProcessor = require('./basehttpstreamprocessor');
function HTTPRawProcessor()
@ -47,7 +48,7 @@ HTTPRawProcessor.prototype.cleanup = function()
fs.rename(this.tempFilename, this.filename, function(err)
{
console.log('Error: could not move ' + this.tempFilename + ' to ' + this.filename + ': ' + err.message);
logger.error('Could not move ' + this.tempFilename + ' to ' + this.filename + ': ' + err.message);
});
}