2016-04-08 22:16:22 +02:00
/ * M a g i c M i r r o r
* The Core App ( Server )
*
* By Michael Teeuw http : //michaelteeuw.nl
* MIT Licensed .
* /
var fs = require ( "fs" ) ;
var Server = require ( _ _dirname + "/server.js" ) ;
var defaultModules = require ( _ _dirname + "/../modules/default/defaultmodules.js" ) ;
var path = require ( "path" ) ;
2016-10-13 16:42:15 +02:00
// Get version number.
global . version = JSON . parse ( fs . readFileSync ( "package.json" , "utf8" ) ) . version ;
console . log ( "Starting MagicMirror: v" + global . version ) ;
2016-12-27 14:31:35 -03:00
// global absolute root path
global . root _path = path . resolve ( _ _dirname + "/../" ) ;
2017-01-24 02:59:20 -03:00
if ( process . env . MM _CONFIG _FILE ) {
global . configuration _file = process . env . MM _CONFIG _FILE ;
}
2017-01-31 21:58:46 -03:00
//Hotfix PullRequest #673
if ( process . env . MM _PORT ) {
global . mmPort = process . env . MM _PORT ;
}
2016-04-19 11:25:50 +02:00
// The next part is here to prevent a major exception when there
// is no internet connection. This could probable be solved better.
2016-05-03 19:09:38 -04:00
process . on ( "uncaughtException" , function ( err ) {
console . log ( "Whoops! There was an uncaught exception..." ) ;
console . error ( err ) ;
console . log ( "MagicMirror will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?" ) ;
console . log ( "If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues" ) ;
2016-04-19 11:25:50 +02:00
} ) ;
2016-04-08 22:16:22 +02:00
/ * A p p - T h e c o r e a p p .
* /
var App = function ( ) {
var nodeHelpers = [ ] ;
/ * l o a d C o n f i g ( c a l l b a c k )
* Loads the config file . combines it with the defaults ,
* and runs the callback with the found config as argument .
*
* argument callback function - The callback function .
* /
var loadConfig = function ( callback ) {
console . log ( "Loading config ..." ) ;
var defaults = require ( _ _dirname + "/defaults.js" ) ;
2017-01-24 02:59:20 -03:00
// For this check proposed to TestSuite
// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
2017-01-26 18:33:37 -03:00
var configFilename = path . resolve ( global . root _path + "/config/config.js" ) ;
2017-01-26 21:13:58 -03:00
if ( typeof ( global . configuration _file ) !== "undefined" ) {
2017-01-26 18:33:37 -03:00
configFilename = path . resolve ( global . configuration _file ) ;
2017-01-24 02:59:20 -03:00
}
2016-04-08 22:16:22 +02:00
try {
fs . accessSync ( configFilename , fs . F _OK ) ;
var c = require ( configFilename ) ;
2016-12-14 18:54:44 +01:00
checkDeprecatedOptions ( c ) ;
2016-04-08 22:16:22 +02:00
var config = Object . assign ( defaults , c ) ;
callback ( config ) ;
} catch ( e ) {
2016-08-05 19:18:31 +02:00
if ( e . code == "ENOENT" ) {
console . error ( "WARNING! Could not find config file. Please create one. Starting with default configuration." ) ;
callback ( defaults ) ;
} else if ( e instanceof ReferenceError || e instanceof SyntaxError ) {
console . error ( "WARNING! Could not validate config file. Please correct syntax errors. Starting with default configuration." ) ;
callback ( defaults ) ;
} else {
console . error ( "WARNING! Could not load config file. Starting with default configuration. Error found: " + e ) ;
callback ( defaults ) ;
}
2016-04-08 22:16:22 +02:00
}
} ;
2016-12-14 18:54:44 +01:00
var checkDeprecatedOptions = function ( userConfig ) {
var deprecatedOptions = require ( _ _dirname + "/../config/deprecated.js" ) ;
var usedDeprecated = [ ] ;
deprecatedOptions . forEach ( function ( option ) {
if ( userConfig . hasOwnProperty ( option ) ) {
usedDeprecated . push ( option ) ;
}
} ) ;
if ( usedDeprecated . length > 0 ) {
console . error ( "WARNING! Your config is using deprecated options: " + usedDeprecated . join ( ", " ) + ". Check README and CHANGELOG for more up-to-date ways of getting the same functionality." ) ;
}
}
2016-04-08 22:16:22 +02:00
/ * l o a d M o d u l e ( m o d u l e )
* Loads a specific module .
*
* argument module string - The name of the module ( including subpath ) .
* /
2016-12-07 17:19:05 +01:00
var loadModule = function ( module , callback ) {
2016-04-08 22:16:22 +02:00
var elements = module . split ( "/" ) ;
var moduleName = elements [ elements . length - 1 ] ;
var moduleFolder = _ _dirname + "/../modules/" + module ;
if ( defaultModules . indexOf ( moduleName ) !== - 1 ) {
moduleFolder = _ _dirname + "/../modules/default/" + module ;
}
var helperPath = moduleFolder + "/node_helper.js" ;
var loadModule = true ;
try {
fs . accessSync ( helperPath , fs . R _OK ) ;
} catch ( e ) {
loadModule = false ;
console . log ( "No helper found for module: " + moduleName + "." ) ;
}
if ( loadModule ) {
var Module = require ( helperPath ) ;
var m = new Module ( ) ;
2016-10-13 16:42:15 +02:00
if ( m . requiresVersion ) {
console . log ( "Check MagicMirror version for node helper '" + moduleName + "' - Minimum version: " + m . requiresVersion + " - Current version: " + global . version ) ;
if ( cmpVersions ( global . version , m . requiresVersion ) >= 0 ) {
console . log ( "Version is ok!" ) ;
} else {
console . log ( "Version is incorrect. Skip module: '" + moduleName + "'" ) ;
return ;
}
}
2016-04-08 22:16:22 +02:00
m . setName ( moduleName ) ;
m . setPath ( path . resolve ( moduleFolder ) ) ;
nodeHelpers . push ( m ) ;
2016-12-07 17:19:05 +01:00
m . loaded ( callback ) ;
} else {
callback ( ) ;
2016-04-08 22:16:22 +02:00
}
} ;
/ * l o a d M o d u l e s ( m o d u l e s )
* Loads all modules .
*
* argument module string - The name of the module ( including subpath ) .
* /
2016-12-07 17:19:05 +01:00
var loadModules = function ( modules , callback ) {
2016-04-08 22:16:22 +02:00
console . log ( "Loading module helpers ..." ) ;
2016-12-07 17:19:05 +01:00
var loadNextModule = function ( ) {
if ( modules . length > 0 ) {
var nextModule = modules [ 0 ] ;
loadModule ( nextModule , function ( ) {
modules = modules . slice ( 1 ) ;
loadNextModule ( ) ;
} ) ;
} else {
// All modules are loaded
console . log ( "All module helpers loaded." ) ;
callback ( ) ;
}
} ;
2016-04-08 22:16:22 +02:00
2016-12-07 17:19:05 +01:00
loadNextModule ( ) ;
2016-04-08 22:16:22 +02:00
} ;
2016-10-13 16:42:15 +02:00
/ * c m p V e r s i o n s ( a , b )
* Compare two symantic version numbers and return the difference .
*
* argument a string - Version number a .
* argument a string - Version number b .
* /
function cmpVersions ( a , b ) {
var i , diff ;
var regExStrip0 = /(\.0+)+$/ ;
var segmentsA = a . replace ( regExStrip0 , "" ) . split ( "." ) ;
var segmentsB = b . replace ( regExStrip0 , "" ) . split ( "." ) ;
var l = Math . min ( segmentsA . length , segmentsB . length ) ;
for ( i = 0 ; i < l ; i ++ ) {
diff = parseInt ( segmentsA [ i ] , 10 ) - parseInt ( segmentsB [ i ] , 10 ) ;
if ( diff ) {
return diff ;
}
}
return segmentsA . length - segmentsB . length ;
}
2016-04-08 22:16:22 +02:00
/ * s t a r t ( c a l l b a c k )
* This methods starts the core app .
* It loads the config , then it loads all modules .
2016-05-03 19:09:38 -04:00
* When it " s done it executs the callback with the config as argument .
2016-04-08 22:16:22 +02:00
*
* argument callback function - The callback function .
* /
this . start = function ( callback ) {
loadConfig ( function ( c ) {
config = c ;
var modules = [ ] ;
for ( var m in config . modules ) {
var module = config . modules [ m ] ;
2016-11-14 14:43:30 -03:00
if ( modules . indexOf ( module . module ) === - 1 && ! module . disabled ) {
2016-04-08 22:16:22 +02:00
modules . push ( module . module ) ;
}
}
2016-12-07 17:19:05 +01:00
loadModules ( modules , function ( ) {
var server = new Server ( config , function ( app , io ) {
console . log ( "Server started ..." ) ;
2016-04-08 22:16:22 +02:00
2016-12-07 17:19:05 +01:00
for ( var h in nodeHelpers ) {
var nodeHelper = nodeHelpers [ h ] ;
nodeHelper . setExpressApp ( app ) ;
nodeHelper . setSocketIO ( io ) ;
nodeHelper . start ( ) ;
}
2016-04-08 22:16:22 +02:00
2016-12-07 17:19:05 +01:00
console . log ( "Sockets connected & modules started ..." ) ;
2016-04-08 22:16:22 +02:00
2016-12-07 17:19:05 +01:00
if ( typeof callback === "function" ) {
callback ( config ) ;
}
2016-04-08 22:16:22 +02:00
2016-12-07 17:19:05 +01:00
} ) ;
2016-04-08 22:16:22 +02:00
} ) ;
} ) ;
} ;
} ;
2016-11-14 14:43:30 -03:00
module . exports = new App ( ) ;