mirror of
https://github.com/flyandi/mazda-custom-application-sdk
synced 2024-12-23 03:35:29 -06:00
sync stuff - NOT READY FOR PROD
This commit is contained in:
parent
55310971c8
commit
0fb8aea2f6
15 changed files with 982 additions and 1366 deletions
|
@ -1,25 +1,25 @@
|
||||||
/**
|
/**
|
||||||
* Custom Applications SDK for Mazda Connect Infotainment System
|
* Custom Applications SDK for Mazda Connect Infotainment System
|
||||||
*
|
*
|
||||||
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
||||||
* that includes an easy to use abstraction layer to the JCI system.
|
* that includes an easy to use abstraction layer to the JCI system.
|
||||||
*
|
*
|
||||||
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
||||||
* Copyright (c) 2016. All rights reserved.
|
* Copyright (c) 2016. All rights reserved.
|
||||||
*
|
*
|
||||||
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
||||||
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
||||||
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||||
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
* License, or (at your option) any later version.
|
* License, or (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
* License for more details.
|
* License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License along with this program.
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
* If not, see http://www.gnu.org/licenses/
|
* If not, see http://www.gnu.org/licenses/
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
* NOTICE: It's important that you target your application with the [app] attribute
|
* NOTICE: It's important that you target your application with the [app] attribute
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[app="app.helloworld"] .smallerText {
|
[app="app.helloworld"] .smallerText {
|
||||||
font-size:0.8em;
|
font-size:0.8em;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
margin-bottom:20px;
|
margin-bottom:20px;
|
||||||
|
|
|
@ -52,12 +52,6 @@ CustomApplicationsHandler.register("app.helloworld", new CustomApplication({
|
||||||
|
|
||||||
js: [],
|
js: [],
|
||||||
|
|
||||||
/**
|
|
||||||
* (css) defines css includes
|
|
||||||
*/
|
|
||||||
|
|
||||||
css: ['app.css'],
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (images) defines images that are being preloaded
|
* (images) defines images that are being preloaded
|
||||||
*
|
*
|
||||||
|
|
|
@ -170,7 +170,7 @@ gulp.task('appdrive-framework-js', function() {
|
||||||
base: frameworkPathInput + "js"
|
base: frameworkPathInput + "js"
|
||||||
})
|
})
|
||||||
.pipe(concat('framework.js'))
|
.pipe(concat('framework.js'))
|
||||||
.pipe(uglify())
|
//.pipe(uglify())
|
||||||
.pipe(concatutil.header(fs.readFileSync(frameworkPathInput + "resources/header.txt", "utf8"), {
|
.pipe(concatutil.header(fs.readFileSync(frameworkPathInput + "resources/header.txt", "utf8"), {
|
||||||
pkg: package
|
pkg: package
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -140,6 +140,15 @@ var CustomApplication = (function() {
|
||||||
CCW: 'ccw',
|
CCW: 'ccw',
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Life Cycles
|
||||||
|
* @type enum
|
||||||
|
*/
|
||||||
|
lifecyles: {
|
||||||
|
CREATED: 'created',
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the custom application's log object. This method is called during the initialization of the
|
* Creates the custom application's log object. This method is called during the initialization of the
|
||||||
* custom application.
|
* custom application.
|
||||||
|
@ -164,17 +173,17 @@ var CustomApplication = (function() {
|
||||||
},
|
},
|
||||||
|
|
||||||
debug: function() {
|
debug: function() {
|
||||||
CustomApplicationLog.debug.apply(CustomApplicationLog, this.__toArray(arguments));
|
Logger.debug.apply(this, this.__toArray(arguments));
|
||||||
},
|
},
|
||||||
|
|
||||||
// info
|
// info
|
||||||
info: function() {
|
info: function() {
|
||||||
CustomApplicationLog.info.apply(CustomApplicationLog, this.__toArray(arguments));
|
Logger.info.apply(this, this.__toArray(arguments));
|
||||||
},
|
},
|
||||||
|
|
||||||
// error
|
// error
|
||||||
error: function() {
|
error: function() {
|
||||||
CustomApplicationLog.error.apply(CustomApplicationLog, this.__toArray(arguments));
|
Logger.error.apply(this, this.__toArray(arguments));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -203,8 +212,8 @@ var CustomApplication = (function() {
|
||||||
this.__currentContextIndex = false;
|
this.__currentContextIndex = false;
|
||||||
|
|
||||||
// global specific
|
// global specific
|
||||||
this.is = CustomApplicationHelpers.is();
|
this.is = CMU.helpers.is;
|
||||||
this.sprintr = CustomApplicationHelpers.sprintr;
|
this.sprintr = CMU.helpers.sprintr;
|
||||||
|
|
||||||
// initialize log
|
// initialize log
|
||||||
this.__log();
|
this.__log();
|
||||||
|
@ -222,7 +231,7 @@ var CustomApplication = (function() {
|
||||||
|
|
||||||
}.bind(this), this.CHANGED);
|
}.bind(this), this.CHANGED);
|
||||||
|
|
||||||
this.__region = CustomApplicationDataHandler.get(VehicleData.general.region, 'na').value;
|
this.__region = false; // CustomApplicationDataHandler.get(VehicleData.general.region, 'na').value;
|
||||||
|
|
||||||
// set loader status
|
// set loader status
|
||||||
this.__loaded = false;
|
this.__loaded = false;
|
||||||
|
@ -250,7 +259,7 @@ var CustomApplication = (function() {
|
||||||
this.__created = true;
|
this.__created = true;
|
||||||
|
|
||||||
// execute life cycle
|
// execute life cycle
|
||||||
this.__lifecycle("created");
|
this.__lifecycle(this.lifecyles.CREATED);
|
||||||
|
|
||||||
// all done
|
// all done
|
||||||
this.__initialized = true;
|
this.__initialized = true;
|
||||||
|
@ -298,7 +307,7 @@ var CustomApplication = (function() {
|
||||||
// load javascripts
|
// load javascripts
|
||||||
if (this.require.js && !this.is.empty(this.require.js)) {
|
if (this.require.js && !this.is.empty(this.require.js)) {
|
||||||
toload++;
|
toload++;
|
||||||
CustomApplicationResourceLoader.loadJavascript(this.require.js, this.location, function() {
|
CMU.requestResource(CMU.resource.JAVASCRIPT, this.require.js, this.location, function() {
|
||||||
loaded++;
|
loaded++;
|
||||||
isFinished();
|
isFinished();
|
||||||
});
|
});
|
||||||
|
@ -307,25 +316,12 @@ var CustomApplication = (function() {
|
||||||
// load css
|
// load css
|
||||||
if (this.require.css && !this.is.empty(this.require.css)) {
|
if (this.require.css && !this.is.empty(this.require.css)) {
|
||||||
toload++;
|
toload++;
|
||||||
CustomApplicationResourceLoader.loadCSS(this.require.css, this.location, function() {
|
CMU.requestResource(CMU.resource.CSS, this.require.css, this.location, function() {
|
||||||
loaded++;
|
loaded++;
|
||||||
isFinished();
|
isFinished();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// load images
|
|
||||||
if (this.require.images && !this.is.empty(this.require.images)) {
|
|
||||||
toload++;
|
|
||||||
CustomApplicationResourceLoader.loadImages(this.require.images, this.location, function(loadedImages) {
|
|
||||||
|
|
||||||
// assign images
|
|
||||||
this.images = loadedImages;
|
|
||||||
|
|
||||||
loaded++;
|
|
||||||
isFinished();
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
/**
|
|
||||||
* Custom Applications SDK for Mazda Connect Infotainment System
|
|
||||||
*
|
|
||||||
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
|
||||||
* that includes an easy to use abstraction layer to the JCI system.
|
|
||||||
*
|
|
||||||
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
|
||||||
* Copyright (c) 2016. All rights reserved.
|
|
||||||
*
|
|
||||||
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
|
||||||
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
|
||||||
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program.
|
|
||||||
* If not, see http://www.gnu.org/licenses/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (CustomApplicationLog)
|
|
||||||
*
|
|
||||||
* A logger
|
|
||||||
*/
|
|
||||||
|
|
||||||
var CustomApplicationLog = {
|
|
||||||
|
|
||||||
levels: {
|
|
||||||
debug: 'DEBUG',
|
|
||||||
info: 'INFO',
|
|
||||||
error: 'ERROR',
|
|
||||||
},
|
|
||||||
|
|
||||||
enabledLogger: false,
|
|
||||||
enabledConsole: false,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (enable) enables the log
|
|
||||||
*/
|
|
||||||
|
|
||||||
enableLogger: function(value) {
|
|
||||||
|
|
||||||
this.enabledLogger = value;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (enable) enables the log
|
|
||||||
*/
|
|
||||||
|
|
||||||
enableConsole: function(value) {
|
|
||||||
|
|
||||||
this.enabledConsole = value;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (debug) debug message
|
|
||||||
*/
|
|
||||||
|
|
||||||
debug: function() {
|
|
||||||
this.__message(this.levels.debug, "#006600", Array.apply(null, arguments));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (error) error message
|
|
||||||
*/
|
|
||||||
|
|
||||||
error: function() {
|
|
||||||
this.__message(this.levels.error, "#FF0000", Array.apply(null, arguments));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (info) info message
|
|
||||||
*/
|
|
||||||
|
|
||||||
info: function() {
|
|
||||||
this.__message(this.levels.info, "#0000FF", Array.apply(null, arguments));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (message)
|
|
||||||
*/
|
|
||||||
|
|
||||||
__message: function(level, color, values) {
|
|
||||||
|
|
||||||
if(this.enabledLogger || this.enabledConsole || typeof(DevLogger) != "undefined") {
|
|
||||||
|
|
||||||
var msg = [];
|
|
||||||
if(values.length > 1) {
|
|
||||||
values.forEach(function(value, index) {
|
|
||||||
|
|
||||||
if(index > 0) {
|
|
||||||
|
|
||||||
switch(true) {
|
|
||||||
|
|
||||||
case CustomApplicationHelpers.is().iterable(value):
|
|
||||||
|
|
||||||
CustomApplicationHelpers.iterate(value, function(key, value, obj) {
|
|
||||||
|
|
||||||
msg.push(obj ? CustomApplicationHelpers.sprintr("[{0}={1}]", key, value) : CustomApplicationHelpers.sprintr("[{0}]", value));
|
|
||||||
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
msg.push(value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(this.enabledLogger && typeof(Logger) != "undefined") {
|
|
||||||
Logger.log(level, values[0], msg.join(" "), color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeof(DevLogger) != "undefined") {
|
|
||||||
DevLogger.log(level, values[0], msg.join(" "), color);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(this,enabledConsole) {
|
|
||||||
console.log(
|
|
||||||
CustomApplicationHelpers.sprintr("%c[{0}] [{1}] ", (new Date()).toDateString(), values[0]) +
|
|
||||||
CustomApplicationHelpers.sprintr("%c{0}", msg.join(" ")),
|
|
||||||
"color:black",
|
|
||||||
CustomApplicationHelpers.sprintr("color:{0}", color)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,652 +0,0 @@
|
||||||
/**
|
|
||||||
* Custom Applications SDK for Mazda Connect Infotainment System
|
|
||||||
*
|
|
||||||
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
|
||||||
* that includes an easy to use abstraction layer to the JCI system.
|
|
||||||
*
|
|
||||||
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
|
||||||
* Copyright (c) 2016. All rights reserved.
|
|
||||||
*
|
|
||||||
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
|
||||||
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
|
||||||
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program.
|
|
||||||
* If not, see http://www.gnu.org/licenses/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the main system file that manages everything between the CMU backend server and the frontend.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Logger)
|
|
||||||
*/
|
|
||||||
|
|
||||||
window.Logger = {
|
|
||||||
|
|
||||||
levels: {
|
|
||||||
debug: 'DEBUG',
|
|
||||||
info: 'INFO',
|
|
||||||
error: 'ERROR',
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscriptions
|
|
||||||
* @array
|
|
||||||
*/
|
|
||||||
subscriptions: [],
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (debug) debug message
|
|
||||||
*/
|
|
||||||
|
|
||||||
debug: function() {
|
|
||||||
this.__message(this.levels.debug, "#006600", Array.apply(null, arguments));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (error) error message
|
|
||||||
*/
|
|
||||||
|
|
||||||
error: function() {
|
|
||||||
this.__message(this.levels.error, "#FF0000", Array.apply(null, arguments));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (info) info message
|
|
||||||
*/
|
|
||||||
|
|
||||||
info: function() {
|
|
||||||
this.__message(this.levels.info, "#0000FF", Array.apply(null, arguments));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscribe
|
|
||||||
* @return {[type]} [description]
|
|
||||||
*/
|
|
||||||
subscribe: function(callback) {
|
|
||||||
|
|
||||||
if(typeof(callback) == "function") {
|
|
||||||
this.subscriptions.push(callback);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [__message description]
|
|
||||||
* @param {[type]} level [description]
|
|
||||||
* @param {[type]} color [description]
|
|
||||||
* @param {[type]} values [description]
|
|
||||||
* @return {[type]} [description]
|
|
||||||
*/
|
|
||||||
__message: function(level, color, values) {
|
|
||||||
|
|
||||||
var msg = [];
|
|
||||||
|
|
||||||
if(values.length > 1) {
|
|
||||||
values.forEach(function(value, index) {
|
|
||||||
|
|
||||||
if(index > 0) {
|
|
||||||
|
|
||||||
if(typeof(value) == "object") {
|
|
||||||
|
|
||||||
var keys = value, o = false;
|
|
||||||
|
|
||||||
if(Object.prototype.toString.call(value) == "[object Object]") {
|
|
||||||
var keys = Object.keys(value),
|
|
||||||
o = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(keys.forEach) {
|
|
||||||
|
|
||||||
keys.forEach(function(v, index) {
|
|
||||||
msg.push(o ? '[' + v + '=' + value[v]+ ']' : '[' + v + ']');
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
msg.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = msg.join(" ");
|
|
||||||
|
|
||||||
this.subscriptions.forEach(function(subscription) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
subscription(level, values[0], msg, color);
|
|
||||||
} catch(e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (CustomApplications)
|
|
||||||
*
|
|
||||||
* Registers itself between the JCI system and CustomApplication framework.
|
|
||||||
*/
|
|
||||||
|
|
||||||
window.CustomApplications = {
|
|
||||||
|
|
||||||
ID: 'system',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (locals)
|
|
||||||
*/
|
|
||||||
debug: false,
|
|
||||||
bootstrapped: false,
|
|
||||||
|
|
||||||
systemAppId: 'system',
|
|
||||||
systemAppCategory: 'Applications',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overwrites
|
|
||||||
*/
|
|
||||||
proxyAppName: 'vdt',
|
|
||||||
proxyAppContext: 'DriveChartDetails',
|
|
||||||
proxyMmuiEvent: 'SelectDriveRecord',
|
|
||||||
|
|
||||||
targetAppName: 'custom',
|
|
||||||
targetAppContext: 'Surface',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration
|
|
||||||
*/
|
|
||||||
configuration: {
|
|
||||||
|
|
||||||
networkHost: '127.0.0.1',
|
|
||||||
networkPort: 9700,
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commands
|
|
||||||
*/
|
|
||||||
commands: {
|
|
||||||
|
|
||||||
REQUEST_PING: 'ping',
|
|
||||||
REQUEST_APPDRIVE: 'appdrive',
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Results
|
|
||||||
*/
|
|
||||||
results: {
|
|
||||||
|
|
||||||
RESULT_OK: 200,
|
|
||||||
RESULT_PONG: 201,
|
|
||||||
RESULT_NOTFOUND: 404,
|
|
||||||
RESULT_ERROR: 500,
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the proxy
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
initialize: function(callback) {
|
|
||||||
|
|
||||||
if(!this.initialized) {
|
|
||||||
|
|
||||||
this.initialized = true;
|
|
||||||
|
|
||||||
this.requests = {};
|
|
||||||
|
|
||||||
this.obtainConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
return callback ? callback() : true;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Establishes a connection between the front and backend
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
obtainConnection: function() {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
this.client = new WebSocket('ws://' + this.configuration.networkHost + ':' + this.configuration.networkPort);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ping
|
|
||||||
*/
|
|
||||||
this.client.ping = function() {
|
|
||||||
|
|
||||||
this.request(this.commands.REQUEST_PING, {
|
|
||||||
inboundStamp: (new Date()).getTime()
|
|
||||||
}, function(error, result) {
|
|
||||||
|
|
||||||
Logger.info(this.ID, "ping", {
|
|
||||||
lost: error,
|
|
||||||
time: !error ? result.outboundStamp - result.inboundStamp : 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* onOpen
|
|
||||||
* @event
|
|
||||||
*/
|
|
||||||
this.client.onopen = function() {
|
|
||||||
|
|
||||||
Logger.info(this.ID, "connection open");
|
|
||||||
|
|
||||||
this.client.ping();
|
|
||||||
|
|
||||||
this.requestAppDrive();
|
|
||||||
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* onMessage
|
|
||||||
* @event
|
|
||||||
*/
|
|
||||||
this.client.onmessage = function(message) {
|
|
||||||
|
|
||||||
this.handleReturnRequest(message);
|
|
||||||
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* onError
|
|
||||||
* @event
|
|
||||||
*/
|
|
||||||
this.client.onerror = function(error) {
|
|
||||||
|
|
||||||
Logger.error(CustomApplications.ID, 'ClientError', error);
|
|
||||||
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* onClose
|
|
||||||
* @event
|
|
||||||
*/
|
|
||||||
this.client.onclose = function(event) {
|
|
||||||
|
|
||||||
this.client = null;
|
|
||||||
|
|
||||||
if(event.code == 3110) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
|
|
||||||
CustomApplications.obtainConnection();
|
|
||||||
|
|
||||||
}, 5000); // retry later
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
|
|
||||||
this.client = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [request description]
|
|
||||||
* @return {[type]} [description]
|
|
||||||
*/
|
|
||||||
request: function(request, payload, callback) {
|
|
||||||
|
|
||||||
// check connection state
|
|
||||||
if(!this.client || this.client.readyState != 1) return callback(true, {});
|
|
||||||
|
|
||||||
// prepare id
|
|
||||||
var id = false;
|
|
||||||
while(!id || this.requests[id]) {
|
|
||||||
id = (new Date()).getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
// register request
|
|
||||||
this.requests[id] = callback;
|
|
||||||
|
|
||||||
// sanity check
|
|
||||||
payload = payload || {};
|
|
||||||
|
|
||||||
// add request id
|
|
||||||
payload.requestId = id;
|
|
||||||
|
|
||||||
payload.request = request;
|
|
||||||
|
|
||||||
// execute
|
|
||||||
return this.client.send(JSON.stringify(payload));
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes a request
|
|
||||||
* @param {[type]} data [description]
|
|
||||||
* @return {[type]} [description]
|
|
||||||
*/
|
|
||||||
handleReturnRequest: function(message) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
// parse message
|
|
||||||
var payload = JSON.parse(message.data);
|
|
||||||
|
|
||||||
// check against active requests
|
|
||||||
if(payload.requestId && this.requests[payload.requestId]) {
|
|
||||||
|
|
||||||
var callback = this.requests[payload.requestId];
|
|
||||||
|
|
||||||
if(typeof(callback) == "function") {
|
|
||||||
|
|
||||||
callback(payload.result == this.results.RESULT_ERROR, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete this.requests[payload.requestId];
|
|
||||||
|
|
||||||
return; // all done
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
|
|
||||||
Logger.error(CustomApplications.ID, 'handleReturnRequest', e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trys to load the AppDrive
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
requestAppDrive: function() {
|
|
||||||
|
|
||||||
if(typeof(CustomApplicationsHandler) != "undefined") return false;
|
|
||||||
|
|
||||||
if(!this.request(this.commands.REQUEST_APPDRIVE, false, function(error, result) {
|
|
||||||
|
|
||||||
if(error || !result.appdrive) {
|
|
||||||
return setTimeout(function() {
|
|
||||||
|
|
||||||
this.requestAppDrive();
|
|
||||||
|
|
||||||
}.bind(this), 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// load appdrive
|
|
||||||
this.loadAppDrive(result.appdrive, function() {
|
|
||||||
|
|
||||||
// boot strap system
|
|
||||||
this.bootstrap();
|
|
||||||
|
|
||||||
// update applications
|
|
||||||
this.updateApplications();
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
}.bind(this)));
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to load the AppDrive
|
|
||||||
* @param object appdrive The AppDrive object
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
loadAppDrive: function(appdrive, callback) {
|
|
||||||
|
|
||||||
this.appdrive = appdrive;
|
|
||||||
|
|
||||||
if(this.appdrive) {
|
|
||||||
|
|
||||||
// load css
|
|
||||||
this.loadCSS(this.appdrive.css);
|
|
||||||
|
|
||||||
// load js
|
|
||||||
this.loadJS(this.appdrive.js, callback);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (bootstrap)
|
|
||||||
*
|
|
||||||
* Bootstraps the JCI system
|
|
||||||
*/
|
|
||||||
|
|
||||||
bootstrap: function() {
|
|
||||||
|
|
||||||
// verify that core objects are available
|
|
||||||
if(typeof framework === 'object' && framework._currentAppUiaId === this.systemAppId && this.bootstrapped === false) {
|
|
||||||
|
|
||||||
// retrieve system app
|
|
||||||
var systemApp = framework.getAppInstance(this.systemAppId);
|
|
||||||
|
|
||||||
// verify bootstrapping - yeah long name
|
|
||||||
if(systemApp) {
|
|
||||||
|
|
||||||
// set to strap - if everything fails - no harm is done :-)
|
|
||||||
this.bootstrapped = true;
|
|
||||||
|
|
||||||
// let's boostrap
|
|
||||||
try {
|
|
||||||
|
|
||||||
// overwrite list2 handler
|
|
||||||
systemApp._contextTable[this.systemAppCategory].controlProperties.List2Ctrl.selectCallback = this.menuItemSelectCallback.bind(systemApp);
|
|
||||||
|
|
||||||
// for usb changes - we do this right now but might
|
|
||||||
if(typeof(systemApp.overwriteStatusMenuUSBAudioMsgHandler) == "undefined") {
|
|
||||||
systemApp.overwriteStatusMenuUSBAudioMsgHandler = systemApp._StatusMenuUSBAudioMsgHandler;
|
|
||||||
systemApp._StatusMenuUSBAudioMsgHandler = this.StatusMenuUSBAudioMsgHandler.bind(systemApp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// overwrite framework route handler
|
|
||||||
if(typeof(framework.overwriteRouteMmmuiMsg) == "undefined") {
|
|
||||||
framework.overwriteRouteMmmuiMsg = framework.routeMmuiMsg;
|
|
||||||
framework.routeMmuiMsg = this.routeMmuiMsg.bind(framework);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ovewrite framework MMUI sender
|
|
||||||
if(typeof(framework.overwriteSendEventToMmui) == "undefined") {
|
|
||||||
framework.overwriteSendEventToMmui = framework.sendEventToMmui;
|
|
||||||
framework.sendEventToMmui = this.sendEventToMmui.bind(framework);
|
|
||||||
}
|
|
||||||
|
|
||||||
// assign template transition
|
|
||||||
framework.transitionsObj._genObj._TEMPLATE_CATEGORIES_TABLE.SurfaceTmplt = 'Detail with UMP';
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
// bootstrapping process failed - we just leave it here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Overwrite) menuItemSelectCallback
|
|
||||||
*/
|
|
||||||
|
|
||||||
menuItemSelectCallback: function(listCtrlObj, appData, params) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if(appData.mmuiEvent == "SelectCustomApplication") {
|
|
||||||
|
|
||||||
// exit if handler is not available
|
|
||||||
if(typeof(CustomApplicationsHandler) != "undefined") {
|
|
||||||
|
|
||||||
// launch app
|
|
||||||
if(CustomApplicationsHandler.launch(appData)) {
|
|
||||||
|
|
||||||
// clone app data
|
|
||||||
try {
|
|
||||||
appData = JSON.parse(JSON.stringify(appData));
|
|
||||||
|
|
||||||
// set app data
|
|
||||||
appData.appName = CustomApplicationsProxy.proxyAppName;
|
|
||||||
appData.mmuiEvent = CustomApplicationsProxy.proxyMmuiEvent;
|
|
||||||
} catch(e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass to original handler
|
|
||||||
this._menuItemSelectCallback(listCtrlObj, appData, params);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Overwrite) sendEventToMmui
|
|
||||||
*/
|
|
||||||
|
|
||||||
sendEventToMmui: function(uiaId, eventId, params, fromVui) {
|
|
||||||
|
|
||||||
var currentUiaId = this.getCurrentApp(),
|
|
||||||
currentContextId = this.getCurrCtxtId();
|
|
||||||
|
|
||||||
// proxy overwrites
|
|
||||||
if(typeof(CustomApplicationsHandler) === 'object' && currentUiaId == CustomApplicationsProxy.targetAppName) {
|
|
||||||
currentUiaId = CustomApplicationsProxy.proxyAppName;
|
|
||||||
currentContextId = CustomApplicationsProxy.proxyAppContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass to original handler
|
|
||||||
framework.overwriteSendEventToMmui(uiaId, eventId, params, fromVui, currentUiaId, currentContextId);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Overwrite) routeMmuiMsg
|
|
||||||
*/
|
|
||||||
|
|
||||||
routeMmuiMsg: function(jsObject) {
|
|
||||||
|
|
||||||
if(typeof(CustomApplicationsHandler) === 'object') {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
var proxy = CustomApplications;
|
|
||||||
|
|
||||||
// validate routing message
|
|
||||||
switch(jsObject.msgType) {
|
|
||||||
|
|
||||||
// magic switch
|
|
||||||
case 'ctxtChg':
|
|
||||||
if(jsObject.uiaId == proxy.proxyAppName) {
|
|
||||||
jsObject.uiaId = proxy.targetAppName;
|
|
||||||
jsObject.ctxtId = proxy.targetAppContext;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// check if our proxy app is in the focus stack
|
|
||||||
case 'focusStack':
|
|
||||||
|
|
||||||
if(jsObject.appIdList && jsObject.appIdList.length) {
|
|
||||||
for(var i = 0; i < jsObject.appIdList.length; i++) {
|
|
||||||
var appId = jsObject.appIdList[i];
|
|
||||||
if(appId.id == proxy.proxyAppName) {
|
|
||||||
appId.id = proxy.targetAppName;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'msg':
|
|
||||||
case 'alert':
|
|
||||||
|
|
||||||
if(jsObject.uiaId == proxy.proxyAppName) {
|
|
||||||
jsObject.uiaId = proxy.targetAppName;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// do nothing
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pass to framework
|
|
||||||
framework.overwriteRouteMmmuiMsg(jsObject);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Overwrite) StatusMenuUSBAudioMsgHandler
|
|
||||||
*/
|
|
||||||
|
|
||||||
StatusMenuUSBAudioMsgHandler: function(msg) {
|
|
||||||
|
|
||||||
// pass to original handler
|
|
||||||
this.overwriteStatusMenuUSBAudioMsgHandler(msg);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (updateApplications)
|
|
||||||
*/
|
|
||||||
|
|
||||||
updateApplications: function() {
|
|
||||||
// extend with custom applications
|
|
||||||
try {
|
|
||||||
if(typeof(CustomApplicationsHandler) != "undefined") {
|
|
||||||
|
|
||||||
CustomApplicationsHandler.retrieve(function(items) {
|
|
||||||
|
|
||||||
var systemApp = framework.getAppInstance(this.systemAppId);
|
|
||||||
|
|
||||||
items.forEach(function(item) {
|
|
||||||
|
|
||||||
systemApp._masterApplicationDataList.items.push(item);
|
|
||||||
|
|
||||||
framework.localize._appDicts[this.systemAppId][item.appData.appName.replace(".", "_")] = item.title;
|
|
||||||
|
|
||||||
framework.common._contextCategory._contextCategoryTable[item.appData.appName + '.*'] = 'Applications';
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
// failed to register applications
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runtime Caller
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(window.opera) {
|
|
||||||
window.opera.addEventListener('AfterEvent.load', function (e) {
|
|
||||||
CustomApplications.initialize(function() {
|
|
||||||
CustomApplications.bootstrap();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** EOF **/
|
|
|
@ -1,195 +0,0 @@
|
||||||
/**
|
|
||||||
* Custom Applications SDK for Mazda Connect Infotainment System
|
|
||||||
*
|
|
||||||
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
|
||||||
* that includes an easy to use abstraction layer to the JCI system.
|
|
||||||
*
|
|
||||||
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
|
||||||
* Copyright (c) 2016. All rights reserved.
|
|
||||||
*
|
|
||||||
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
|
||||||
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
|
||||||
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program.
|
|
||||||
* If not, see http://www.gnu.org/licenses/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (CustomApplicationResourceLoader)
|
|
||||||
*
|
|
||||||
* The resource loader for applications
|
|
||||||
*/
|
|
||||||
|
|
||||||
var CustomApplicationResourceLoader = {
|
|
||||||
|
|
||||||
__name: 'ResourceLoader',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (loadJavascript)
|
|
||||||
*/
|
|
||||||
|
|
||||||
loadJavascript: function(scripts, path, callback, options, async) {
|
|
||||||
|
|
||||||
this.__loadInvoker(scripts, path, function(filename, next) {
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.type = 'text/javascript';
|
|
||||||
script.src = filename;
|
|
||||||
script.onload = next;
|
|
||||||
document.body.appendChild(script);
|
|
||||||
}, callback, options, async);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (loadCSS)
|
|
||||||
*/
|
|
||||||
|
|
||||||
loadCSS: function(css, path, callback, options, async) {
|
|
||||||
|
|
||||||
this.__loadInvoker(css, path, function(filename, next) {
|
|
||||||
var css = document.createElement('link');
|
|
||||||
css.rel = "stylesheet";
|
|
||||||
css.type = "text/css";
|
|
||||||
css.href = filename
|
|
||||||
css.onload = async ? callback : next;
|
|
||||||
document.body.appendChild(css);
|
|
||||||
}, callback, options, async);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (loadImages)
|
|
||||||
*/
|
|
||||||
|
|
||||||
loadImages: function(images, path, callback, options, async) {
|
|
||||||
|
|
||||||
this.__loadInvoker(images, path, function(filename, next, id) {
|
|
||||||
var img = document.createElement('img');
|
|
||||||
img.onload = function() {
|
|
||||||
|
|
||||||
if(async) {
|
|
||||||
var result = false;
|
|
||||||
if(id) {
|
|
||||||
result = {};
|
|
||||||
result[id] = this;
|
|
||||||
}
|
|
||||||
callback(id ? result : this);
|
|
||||||
} else {
|
|
||||||
next(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
img.src = filename;
|
|
||||||
}, callback, options, async);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (fromFormatted)
|
|
||||||
*/
|
|
||||||
|
|
||||||
fromFormatted: function(format, items) {
|
|
||||||
|
|
||||||
items.forEach(function(value, index) {
|
|
||||||
items[index] = CustomApplicationHelpers.sprintr(format, value);
|
|
||||||
});
|
|
||||||
|
|
||||||
return items;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (__loadInvoker)
|
|
||||||
*/
|
|
||||||
|
|
||||||
__loadInvoker: function(items, path, build, callback, options, async) {
|
|
||||||
|
|
||||||
var ids = false, result = false, options = options ? options : {}, timeout = false;
|
|
||||||
|
|
||||||
// assign default object
|
|
||||||
this.logger = CustomApplicationLog;
|
|
||||||
|
|
||||||
// support for arrays and objects
|
|
||||||
if(CustomApplicationHelpers.is().object(items)) {
|
|
||||||
|
|
||||||
var idsObject = items, ids = [], items = [];
|
|
||||||
|
|
||||||
Object.keys(idsObject).map(function(key) {
|
|
||||||
ids.push(key);
|
|
||||||
items.push(idsObject[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// return as object
|
|
||||||
result = {};
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if(!CustomApplicationHelpers.is().array(items)) items = [items];
|
|
||||||
}
|
|
||||||
|
|
||||||
// loaded handler
|
|
||||||
var loaded = 0, next = function(failure) {
|
|
||||||
loaded++;
|
|
||||||
if(loaded >= items.length) {
|
|
||||||
if(CustomApplicationHelpers.is().fn(callback)) {
|
|
||||||
callback(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// process items
|
|
||||||
items.forEach(function(filename, index) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
filename = path + filename;
|
|
||||||
|
|
||||||
this.logger.debug(this.__name, "Attempting to load resource from", filename);
|
|
||||||
|
|
||||||
if(!async && options.timeout) {
|
|
||||||
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(function() {
|
|
||||||
|
|
||||||
this.logger.error(this.__name, "Timeout occured while loading resource", filename);
|
|
||||||
|
|
||||||
// just do the next one
|
|
||||||
next(true);
|
|
||||||
|
|
||||||
}.bind(this), options.timeout);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
build(filename, function(resource) {
|
|
||||||
|
|
||||||
this.logger.info(this.__name, "Successfully loaded resource", filename);
|
|
||||||
|
|
||||||
if(resource && ids != false) {
|
|
||||||
this.logger.debug(this.__name, "Loaded resource assigned to id", {id: ids[index], filename: filename});
|
|
||||||
|
|
||||||
result[ids[index]] = resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(async) {
|
|
||||||
if(CustomApplicationHelpers.is().fn(callback)) callback();
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
}.bind(this), ids ? ids[index] : false);
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
this.logger.error(this.__name, "Failed to load resource", {filename: filename, error: e.message});
|
|
||||||
}
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,283 +0,0 @@
|
||||||
/**
|
|
||||||
* Custom Applications SDK for Mazda Connect Infotainment System
|
|
||||||
*
|
|
||||||
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
|
||||||
* that includes an easy to use abstraction layer to the JCI system.
|
|
||||||
*
|
|
||||||
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
|
||||||
* Copyright (c) 2016. All rights reserved.
|
|
||||||
*
|
|
||||||
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
|
||||||
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
|
||||||
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with this program.
|
|
||||||
* If not, see http://www.gnu.org/licenses/
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (CustomApplicationsHandler)
|
|
||||||
*
|
|
||||||
* This is the custom handler that manages the application between the JCI system and the mini framework
|
|
||||||
*/
|
|
||||||
|
|
||||||
var CustomApplicationsHandler = {
|
|
||||||
|
|
||||||
__name: 'ApplicationsHandler',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Applications) storage for applications
|
|
||||||
*/
|
|
||||||
|
|
||||||
applications: {},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Paths)
|
|
||||||
*/
|
|
||||||
|
|
||||||
paths: {
|
|
||||||
framework: 'apps/custom/runtime/',
|
|
||||||
applications: 'apps/custom/apps/',
|
|
||||||
vendor: 'apps/custom/runtime/vendor/',
|
|
||||||
surface: 'apps/custom/runtime/surface/',
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Mapping)
|
|
||||||
*/
|
|
||||||
|
|
||||||
mapping: {
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (initialize) Initializes some of the core objects
|
|
||||||
*/
|
|
||||||
|
|
||||||
initialize: function() {
|
|
||||||
|
|
||||||
this.initialized = true;
|
|
||||||
|
|
||||||
this.loader = CustomApplicationResourceLoader;
|
|
||||||
|
|
||||||
this.log = CustomApplicationLog;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Retrieve) loads the current application list and returns the additional items
|
|
||||||
*/
|
|
||||||
|
|
||||||
retrieve: function(callback) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
// initialize
|
|
||||||
if(!this.initialized) this.initialize();
|
|
||||||
|
|
||||||
// load libraries
|
|
||||||
this.loader.loadJavascript("jquery.js", this.paths.vendor, function() {
|
|
||||||
|
|
||||||
this.loader.loadCSS("runtime.css", this.paths.framework, function() {
|
|
||||||
|
|
||||||
this.loader.loadJavascript("apps.js", this.paths.applications, function() {
|
|
||||||
|
|
||||||
// this has been completed
|
|
||||||
if(typeof(CustomApplications) != "undefined") {
|
|
||||||
|
|
||||||
// load applications
|
|
||||||
this.loader.loadJavascript(
|
|
||||||
this.loader.fromFormatted("{0}/app.js", CustomApplications),
|
|
||||||
this.paths.applications,
|
|
||||||
function() {
|
|
||||||
// all applications are loaded, run data
|
|
||||||
CustomApplicationDataHandler.initialize();
|
|
||||||
|
|
||||||
// create menu items
|
|
||||||
callback(this.getMenuItems());
|
|
||||||
}.bind(this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}.bind(this)); // apps.js
|
|
||||||
|
|
||||||
}.bind(this)); // bootstrap css
|
|
||||||
|
|
||||||
}.bind(this)); // jquery library
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
|
|
||||||
// error message
|
|
||||||
this.log.error(this.__name, "Error while retrieving applications", e);
|
|
||||||
|
|
||||||
// make sure that we notify otherwise we don't get any applications
|
|
||||||
callback(this.getMenuItems());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (get) returns an application by id
|
|
||||||
*/
|
|
||||||
|
|
||||||
get: function(id) {
|
|
||||||
|
|
||||||
return this.applications[id] ? this.applications[id] : false;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Register) registers all the custom applications
|
|
||||||
*/
|
|
||||||
|
|
||||||
register: function(id, application) {
|
|
||||||
|
|
||||||
// unregister previous instance
|
|
||||||
if(this.applications[id]) {
|
|
||||||
this.applications[id].__terminate();
|
|
||||||
this.applications[id] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// registering
|
|
||||||
this.log.info(this.__name, {id:id}, "Registering application");
|
|
||||||
|
|
||||||
application.id = id;
|
|
||||||
|
|
||||||
application.location = this.paths.applications + id + "/";
|
|
||||||
|
|
||||||
application.__initialize();
|
|
||||||
|
|
||||||
this.applications[id] = application;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (launch) launches an application
|
|
||||||
*/
|
|
||||||
|
|
||||||
launch: function(id) {
|
|
||||||
|
|
||||||
this.log.info(this.__name, {id: id}, "Launch request for application");
|
|
||||||
|
|
||||||
if(CustomApplicationHelpers.is().object(id)) {
|
|
||||||
|
|
||||||
id = id.appId ? id.appId : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.applications[id]) {
|
|
||||||
|
|
||||||
this.currentApplicationId = id;
|
|
||||||
|
|
||||||
this.log.info(this.__name, {id: id}, "Launching application");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.error(this.__name, {id: id}, "Launch failed because application was not registered");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (sleep) sleeps an application
|
|
||||||
*/
|
|
||||||
|
|
||||||
sleep: function(application) {
|
|
||||||
|
|
||||||
if(application.id == this.currentApplicationId) {
|
|
||||||
// remember last state
|
|
||||||
this.lastApplicationId = this.currentApplicationId;
|
|
||||||
|
|
||||||
// clear current
|
|
||||||
this.currentApplicationId = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
application.__sleep();
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (getCurrentApplication) returns the current application
|
|
||||||
*/
|
|
||||||
|
|
||||||
getCurrentApplication: function(allowLast) {
|
|
||||||
|
|
||||||
var applicationId = this.currentApplicationId || (allowLast ? this.lastApplicationId : false);
|
|
||||||
|
|
||||||
if(applicationId) {
|
|
||||||
|
|
||||||
this.log.debug(this.__name, "Invoking current set application", {id: applicationId});
|
|
||||||
|
|
||||||
if(this.applications[applicationId]) {
|
|
||||||
|
|
||||||
this.currentApplicationId = applicationId;
|
|
||||||
|
|
||||||
return this.applications[applicationId];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.error(this.__name, "Application was not registered", {id: applicationId});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.error(this.__name, "Missing currentApplicationId");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (notifyDataChange) notifies the active application about a data change
|
|
||||||
*/
|
|
||||||
|
|
||||||
notifyDataChange: function(id, payload) {
|
|
||||||
|
|
||||||
if(this.currentApplicationId && this.applications[this.currentApplicationId]) {
|
|
||||||
|
|
||||||
this.applications[this.currentApplicationId].__notify(id, payload);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (getMenuItems) returns the items for the main application menu
|
|
||||||
*/
|
|
||||||
|
|
||||||
getMenuItems: function(callback) {
|
|
||||||
|
|
||||||
return CustomApplicationHelpers.iterate(this.applications, function(id, application) {
|
|
||||||
|
|
||||||
this.log.info(this.__name, {id:id}, "Adding application to menu", {
|
|
||||||
title: application.getTitle(),
|
|
||||||
});
|
|
||||||
|
|
||||||
// set localized language - for now it's just the title
|
|
||||||
return {
|
|
||||||
appData : {
|
|
||||||
appName : application.getId(),
|
|
||||||
appId: application.getId(),
|
|
||||||
isVisible : true,
|
|
||||||
mmuiEvent : 'SelectCustomApplication',
|
|
||||||
},
|
|
||||||
title: application.getTitle(),
|
|
||||||
text1Id : application.getId().replace(".", "_"),
|
|
||||||
disabled : false,
|
|
||||||
itemStyle : 'style02',
|
|
||||||
hasCaret : application.getHasMenuCaret(),
|
|
||||||
};
|
|
||||||
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
260
src/framework/js/Handler.js
Normal file
260
src/framework/js/Handler.js
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
/**
|
||||||
|
* Custom Applications SDK for Mazda Connect Infotainment System
|
||||||
|
*
|
||||||
|
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
||||||
|
* that includes an easy to use abstraction layer to the JCI system.
|
||||||
|
*
|
||||||
|
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
||||||
|
* Copyright (c) 2016. All rights reserved.
|
||||||
|
*
|
||||||
|
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
||||||
|
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
||||||
|
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
* If not, see http://www.gnu.org/licenses/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Handler)
|
||||||
|
*
|
||||||
|
* Responsibe to handle applications
|
||||||
|
*/
|
||||||
|
|
||||||
|
CMU.attach("handler", function(cmu) {
|
||||||
|
|
||||||
|
|
||||||
|
function Handler() {
|
||||||
|
|
||||||
|
|
||||||
|
CMU.waitFor("proxy", function(proxy) {
|
||||||
|
|
||||||
|
proxy.add({
|
||||||
|
|
||||||
|
// We use the old vdt-DriveChartDetails app as our proxy
|
||||||
|
proxyAppName: 'vdt',
|
||||||
|
proxyAppContext: 'DriveChartDetails',
|
||||||
|
proxyMmuiEvent: 'SelectDriveRecord',
|
||||||
|
|
||||||
|
targetAppName: 'custom',
|
||||||
|
targetAppContext: 'Surface',
|
||||||
|
|
||||||
|
mmuiEvent: 'SelectCustomApplication',
|
||||||
|
|
||||||
|
callback: function(appData) {
|
||||||
|
|
||||||
|
return this.launch(appData);
|
||||||
|
|
||||||
|
}.bind(this),
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
CMU.waitFor("helpers", function(helpers) {
|
||||||
|
|
||||||
|
this.initialize();
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Handler.prototype = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (initialize)
|
||||||
|
*/
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
|
||||||
|
this.applications = CMU.appdrive ? CMU.appdrive.applications : false;
|
||||||
|
|
||||||
|
console.log(this.applications);
|
||||||
|
|
||||||
|
if(this.applications) {
|
||||||
|
|
||||||
|
CMU.requestApplications();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (get) returns an application by id
|
||||||
|
*/
|
||||||
|
|
||||||
|
get: function(id) {
|
||||||
|
|
||||||
|
return this.applications[id] ? this.applications[id] : false;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Register) registers all the custom applications
|
||||||
|
*/
|
||||||
|
|
||||||
|
register: function(id, application) {
|
||||||
|
|
||||||
|
if(!this.applications[id]) return false;
|
||||||
|
|
||||||
|
console.log(this.applications[id]);
|
||||||
|
|
||||||
|
// unregister previous instance
|
||||||
|
if(this.applications[id].instance) {
|
||||||
|
this.applications[id].instance.__terminate();
|
||||||
|
this.applications[id].instance = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// registering
|
||||||
|
Logger.info(this.__name, {id:id}, "Registering application");
|
||||||
|
|
||||||
|
this.applications[id].instance = application;
|
||||||
|
|
||||||
|
this.applications[id].instance.id = id;
|
||||||
|
|
||||||
|
this.applications[id].instance.location = this.applications[id].info.path;
|
||||||
|
|
||||||
|
this.applications[id].instance.__initialize();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (launch) launches an application
|
||||||
|
*/
|
||||||
|
|
||||||
|
launch: function(id) {
|
||||||
|
|
||||||
|
this.log.info(this.__name, {id: id}, "Launch request for application");
|
||||||
|
|
||||||
|
if(CustomApplicationHelpers.is().object(id)) {
|
||||||
|
|
||||||
|
id = id.appId ? id.appId : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.applications[id]) {
|
||||||
|
|
||||||
|
this.currentApplicationId = id;
|
||||||
|
|
||||||
|
this.log.info(this.__name, {id: id}, "Launching application");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log.error(this.__name, {id: id}, "Launch failed because application was not registered");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (sleep) sleeps an application
|
||||||
|
*/
|
||||||
|
|
||||||
|
sleep: function(application) {
|
||||||
|
|
||||||
|
if(application.id == this.currentApplicationId) {
|
||||||
|
// remember last state
|
||||||
|
this.lastApplicationId = this.currentApplicationId;
|
||||||
|
|
||||||
|
// clear current
|
||||||
|
this.currentApplicationId = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
application.__sleep();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (getCurrentApplication) returns the current application
|
||||||
|
*/
|
||||||
|
|
||||||
|
getCurrentApplication: function(allowLast) {
|
||||||
|
|
||||||
|
var applicationId = this.currentApplicationId || (allowLast ? this.lastApplicationId : false);
|
||||||
|
|
||||||
|
if(applicationId) {
|
||||||
|
|
||||||
|
this.log.debug(this.__name, "Invoking current set application", {id: applicationId});
|
||||||
|
|
||||||
|
if(this.applications[applicationId]) {
|
||||||
|
|
||||||
|
this.currentApplicationId = applicationId;
|
||||||
|
|
||||||
|
return this.applications[applicationId];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log.error(this.__name, "Application was not registered", {id: applicationId});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log.error(this.__name, "Missing currentApplicationId");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (notifyDataChange) notifies the active application about a data change
|
||||||
|
*/
|
||||||
|
|
||||||
|
notifyDataChange: function(id, payload) {
|
||||||
|
|
||||||
|
if(this.currentApplicationId && this.applications[this.currentApplicationId]) {
|
||||||
|
|
||||||
|
this.applications[this.currentApplicationId].__notify(id, payload);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (getMenuItems) returns the items for the main application menu
|
||||||
|
*/
|
||||||
|
|
||||||
|
getMenuItems: function(callback) {
|
||||||
|
|
||||||
|
|
||||||
|
return CustomApplicationHelpers.iterate(this.applications, function(id, application) {
|
||||||
|
|
||||||
|
this.log.info(this.__name, {id:id}, "Adding application to menu", {
|
||||||
|
title: application.getTitle(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// set localized language - for now it's just the title
|
||||||
|
return {
|
||||||
|
appData : {
|
||||||
|
appName : application.getId(),
|
||||||
|
appId: application.getId(),
|
||||||
|
isVisible : true,
|
||||||
|
mmuiEvent : 'SelectCustomApplication',
|
||||||
|
},
|
||||||
|
title: application.getTitle(),
|
||||||
|
text1Id : application.getId().replace(".", "_"),
|
||||||
|
disabled : false,
|
||||||
|
itemStyle : 'style02',
|
||||||
|
hasCaret : application.getHasMenuCaret(),
|
||||||
|
};
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var handler = new Handler();
|
||||||
|
|
||||||
|
// global alias
|
||||||
|
window.CustomApplicationsHandler = handler;
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
});
|
||||||
|
|
||||||
|
/** eof */
|
|
@ -25,21 +25,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (CustomApplicationHelpers)
|
* (Helpers)
|
||||||
*
|
*
|
||||||
* A abstract collection of helpers for the framework
|
* A abstract collection of helpers for the framework
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var CustomApplicationHelpers = {
|
|
||||||
|
|
||||||
/**
|
CMU.attach("helpers", function(cmu) {
|
||||||
* (is) a implemention of the flyandi:is library
|
|
||||||
*/
|
|
||||||
|
|
||||||
is: function() {
|
return {
|
||||||
|
|
||||||
return {
|
|
||||||
|
|
||||||
|
is: {
|
||||||
|
/** undefined */
|
||||||
undefined: 'undefined',
|
undefined: 'undefined',
|
||||||
|
|
||||||
__toString: function() {
|
__toString: function() {
|
||||||
|
@ -120,41 +117,41 @@ var CustomApplicationHelpers = {
|
||||||
same: function(a, b) {
|
same: function(a, b) {
|
||||||
return a == b;
|
return a == b;
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (iterate) a iterate that supports arrays and objects
|
* (iterate) a iterate that supports arrays and objects
|
||||||
*/
|
*/
|
||||||
|
|
||||||
iterate: function(o, item) {
|
iterate: function(o, item) {
|
||||||
|
|
||||||
if(this.is().object(o)) {
|
if(this.is().object(o)) {
|
||||||
return Object.keys(o).map(function(key) {
|
return Object.keys(o).map(function(key) {
|
||||||
return item(key, o[key], true);
|
return item(key, o[key], true);
|
||||||
});
|
});
|
||||||
} else if (this.is().array(o)) {
|
} else if (this.is().array(o)) {
|
||||||
return o.map(function(value, key) {
|
return o.map(function(value, key) {
|
||||||
return item(key, value);
|
return item(key, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (sprintr) (https://gist.github.com/flyandi/395816232c70de327801)
|
* (sprintr) (https://gist.github.com/flyandi/395816232c70de327801)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sprintr: function() {
|
sprintr: function() {
|
||||||
var
|
var
|
||||||
args = Array.prototype.slice.call(arguments),
|
args = Array.prototype.slice.call(arguments),
|
||||||
subject = arguments[0];
|
subject = arguments[0];
|
||||||
|
|
||||||
args.shift();
|
args.shift();
|
||||||
|
|
||||||
for(var i = 0; i < args.length; i++)
|
for(var i = 0; i < args.length; i++)
|
||||||
subject = subject.split("{" + i + "}").join(args[i]);
|
subject = subject.split("{" + i + "}").join(args[i]);
|
||||||
|
|
||||||
return subject;
|
return subject;
|
||||||
},
|
},
|
||||||
|
}
|
||||||
};
|
});
|
||||||
|
/** eof */
|
139
src/framework/js/Logger.js
Normal file
139
src/framework/js/Logger.js
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/**
|
||||||
|
* Custom Applications SDK for Mazda Connect Infotainment System
|
||||||
|
*
|
||||||
|
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
||||||
|
* that includes an easy to use abstraction layer to the JCI system.
|
||||||
|
*
|
||||||
|
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
||||||
|
* Copyright (c) 2016. All rights reserved.
|
||||||
|
*
|
||||||
|
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
||||||
|
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
||||||
|
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
* If not, see http://www.gnu.org/licenses/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Logger)
|
||||||
|
*
|
||||||
|
* A logger
|
||||||
|
*/
|
||||||
|
|
||||||
|
CMU.attach("logger", function(cmu) {
|
||||||
|
|
||||||
|
return window.Logger = {
|
||||||
|
|
||||||
|
levels: {
|
||||||
|
debug: 'DEBUG',
|
||||||
|
info: 'INFO',
|
||||||
|
error: 'ERROR',
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscriptions
|
||||||
|
* @array
|
||||||
|
*/
|
||||||
|
subscriptions: [],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (debug) debug message
|
||||||
|
*/
|
||||||
|
|
||||||
|
debug: function() {
|
||||||
|
this.__message(this.levels.debug, "#006600", Array.apply(null, arguments));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (error) error message
|
||||||
|
*/
|
||||||
|
|
||||||
|
error: function() {
|
||||||
|
this.__message(this.levels.error, "#FF0000", Array.apply(null, arguments));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (info) info message
|
||||||
|
*/
|
||||||
|
|
||||||
|
info: function() {
|
||||||
|
this.__message(this.levels.info, "#0000FF", Array.apply(null, arguments));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
subscribe: function(callback) {
|
||||||
|
|
||||||
|
if(typeof(callback) == "function") {
|
||||||
|
this.subscriptions.push(callback);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [__message description]
|
||||||
|
* @param {[type]} level [description]
|
||||||
|
* @param {[type]} color [description]
|
||||||
|
* @param {[type]} values [description]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
__message: function(level, color, values) {
|
||||||
|
|
||||||
|
var msg = [];
|
||||||
|
|
||||||
|
if(values.length > 1) {
|
||||||
|
values.forEach(function(value, index) {
|
||||||
|
|
||||||
|
if(index > 0) {
|
||||||
|
|
||||||
|
if(typeof(value) == "object") {
|
||||||
|
|
||||||
|
var keys = value, o = false;
|
||||||
|
|
||||||
|
if(Object.prototype.toString.call(value) == "[object Object]") {
|
||||||
|
var keys = Object.keys(value),
|
||||||
|
o = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(keys.forEach) {
|
||||||
|
|
||||||
|
keys.forEach(function(v, index) {
|
||||||
|
msg.push(o ? '[' + v + '=' + value[v]+ ']' : '[' + v + ']');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
msg.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = msg.join(" ");
|
||||||
|
|
||||||
|
this.subscriptions.forEach(function(subscription) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
subscription(level, values[0], msg, color);
|
||||||
|
} catch(e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/** eof */
|
307
src/framework/js/Proxy.js
Normal file
307
src/framework/js/Proxy.js
Normal file
|
@ -0,0 +1,307 @@
|
||||||
|
/**
|
||||||
|
* Custom Applications SDK for Mazda Connect Infotainment System
|
||||||
|
*
|
||||||
|
* A mini framework that allows to write custom applications for the Mazda Connect Infotainment System
|
||||||
|
* that includes an easy to use abstraction layer to the JCI system.
|
||||||
|
*
|
||||||
|
* Written by Andreas Schwarz (http://github.com/flyandi/mazda-custom-applications-sdk)
|
||||||
|
* Copyright (c) 2016. All rights reserved.
|
||||||
|
*
|
||||||
|
* WARNING: The installation of this application requires modifications to your Mazda Connect system.
|
||||||
|
* If you don't feel comfortable performing these changes, please do not attempt to install this. You might
|
||||||
|
* be ending up with an unusuable system that requires reset by your Dealer. You were warned!
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with this program.
|
||||||
|
* If not, see http://www.gnu.org/licenses/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Proxy)
|
||||||
|
*
|
||||||
|
* Registers itself between the JCI system and CustomApplication framework.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CMU.attach("proxy", function(cmu) {
|
||||||
|
|
||||||
|
function Proxy() {
|
||||||
|
|
||||||
|
let that = this;
|
||||||
|
|
||||||
|
// register bootstrap event
|
||||||
|
|
||||||
|
if(window.opera) {
|
||||||
|
window.opera.addEventListener('AfterEvent.load', function (e) {
|
||||||
|
that.bootstrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Proxy.prototype = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SYSTEM_APP_ID constant
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
SYSTEM_APP_ID: 'system',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SYSTEM_APP_CATEGORY constant
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
SYSTEM_APP_CATEGORY: 'Applications',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array that stores the registered proxies
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
proxies: {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An translation array that converts a uiaId to a proxy
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
uiaIds: {},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new proxy
|
||||||
|
* @param void
|
||||||
|
*/
|
||||||
|
add: function(proxy) {
|
||||||
|
|
||||||
|
if(!proxy.mmuiEvent || this.has(proxy.mmuiEvent)) return false;
|
||||||
|
|
||||||
|
this.proxies[proxy.mmuiEvent] = proxy;
|
||||||
|
|
||||||
|
this.uiaIds[proxy.proxyAppName] = proxy.mmuiEvent;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a proxy exists
|
||||||
|
* @param {[type]} mmuiEvent [description]
|
||||||
|
* @return {Boolean} [description]
|
||||||
|
*/
|
||||||
|
has: function(mmuiEvent) {
|
||||||
|
return this.proxies[mmuiEvent] ? true : false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a proxy
|
||||||
|
* @param {[type]} mmuiEvent [description]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
get: function(mmuiEvent) {
|
||||||
|
return this.proxies[mmuiEvent];
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a uiaId to a prixy
|
||||||
|
* @param {[type]} uiaId [description]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
fromUiaId: function(uiaId) {
|
||||||
|
|
||||||
|
var entry = this.uiaIds[uiaId];
|
||||||
|
|
||||||
|
if(entry && this.has(entry)) {
|
||||||
|
return this.get(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstraps the JCI system
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
bootstrap: function() {
|
||||||
|
|
||||||
|
// verify that core objects are available
|
||||||
|
if(typeof framework === 'object' && framework._currentAppUiaId === this.SYSTEM_APP_ID && this.bootstrapped === false) {
|
||||||
|
|
||||||
|
// retrieve system app
|
||||||
|
var systemApp = framework.getAppInstance(this.SYSTEM_APP_ID);
|
||||||
|
|
||||||
|
// verify bootstrapping - yeah long name
|
||||||
|
if(systemApp) {
|
||||||
|
|
||||||
|
// set to strap - if everything fails - no harm is done :-)
|
||||||
|
this.bootstrapped = true;
|
||||||
|
|
||||||
|
// let's boostrap
|
||||||
|
try {
|
||||||
|
|
||||||
|
// overwrite list2 handler
|
||||||
|
systemApp._contextTable[this.systemAppCategory].controlProperties.List2Ctrl.selectCallback = this.menuItemSelectCallback.bind(systemApp);
|
||||||
|
|
||||||
|
// overwrite framework route handler
|
||||||
|
if(typeof(framework.overwriteRouteMmmuiMsg) == "undefined") {
|
||||||
|
framework.overwriteRouteMmmuiMsg = framework.routeMmuiMsg;
|
||||||
|
framework.routeMmuiMsg = this.routeMmuiMsg.bind(framework);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ovewrite framework MMUI sender
|
||||||
|
if(typeof(framework.overwriteSendEventToMmui) == "undefined") {
|
||||||
|
framework.overwriteSendEventToMmui = framework.sendEventToMmui;
|
||||||
|
framework.sendEventToMmui = this.sendEventToMmui.bind(framework);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign template transition
|
||||||
|
framework.transitionsObj._genObj._TEMPLATE_CATEGORIES_TABLE.SurfaceTmplt = 'Detail with UMP';
|
||||||
|
|
||||||
|
} catch(e) {
|
||||||
|
// bootstrapping process failed - we just leave it here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Overwrite) menuItemSelectCallback
|
||||||
|
*/
|
||||||
|
|
||||||
|
menuItemSelectCallback: function(listCtrlObj, appData, params) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if(CMU.proxy.has(appData.mmuiEvent)) {
|
||||||
|
|
||||||
|
var proxy = CMU.proxy.getProxyForEvent(appData.mmuiEvent);
|
||||||
|
|
||||||
|
if(proxy && typeof(proxy.callback == "function") && proxy.callback(appData)) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// clone app data
|
||||||
|
appData = JSON.parse(JSON.stringify(appData));
|
||||||
|
|
||||||
|
// overwrite proxy
|
||||||
|
appData.appName = proxy.proxyAppName;
|
||||||
|
appData.mmuiEvent = proxy.proxyMmuiEvent;
|
||||||
|
|
||||||
|
} catch(e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch(e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass to original handler
|
||||||
|
this._menuItemSelectCallback(listCtrlObj, appData, params);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Overwrite) sendEventToMmui
|
||||||
|
*/
|
||||||
|
|
||||||
|
sendEventToMmui: function(uiaId, eventId, params, fromVui) {
|
||||||
|
|
||||||
|
var currentUiaId = this.getCurrentApp(),
|
||||||
|
currentContextId = this.getCurrCtxtId(),
|
||||||
|
proxy = CMU.proxy.fromUiaId(currentUiaId);
|
||||||
|
|
||||||
|
// check proxy
|
||||||
|
if(proxy) {
|
||||||
|
currentUiaId = proxy.proxyAppName;
|
||||||
|
currentContextId = proxy.proxyAppContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass to original handler
|
||||||
|
framework.overwriteSendEventToMmui(uiaId, eventId, params, fromVui, currentUiaId, currentContextId);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Overwrite) routeMmuiMsg
|
||||||
|
*/
|
||||||
|
|
||||||
|
routeMmuiMsg: function(jsObject) {
|
||||||
|
|
||||||
|
if(CMU.has("handler")) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// validate routing message
|
||||||
|
switch(jsObject.msgType) {
|
||||||
|
|
||||||
|
// magic switch
|
||||||
|
case 'ctxtChg':
|
||||||
|
|
||||||
|
var proxy = CMU.proxy.fromUiaId(jsObject.uiaId);
|
||||||
|
|
||||||
|
if(proxy) {
|
||||||
|
jsObject.uiaId = proxy.targetAppName;
|
||||||
|
jsObject.ctxtId = proxy.targetAppContext;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// check if our proxy is in the focus stack
|
||||||
|
case 'focusStack':
|
||||||
|
|
||||||
|
if(jsObject.appIdList && jsObject.appIdList.length) {
|
||||||
|
for(var i = 0; i < jsObject.appIdList.length; i++) {
|
||||||
|
|
||||||
|
var appId = jsObject.appIdList[i],
|
||||||
|
proxy = CMU.proxy.fromUiaId(appId.id);
|
||||||
|
|
||||||
|
if(proxy) {
|
||||||
|
appId.id = proxy.targetAppName;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'msg':
|
||||||
|
case 'alert':
|
||||||
|
|
||||||
|
var proxy = CMU.proxy.fromUiaId(jsObject.uiaId);
|
||||||
|
|
||||||
|
if(proxy) {
|
||||||
|
jsObject.uiaId = proxy.targetAppName;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch(e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass to framework
|
||||||
|
framework.overwriteRouteMmmuiMsg(jsObject);
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial Handler
|
||||||
|
*/
|
||||||
|
|
||||||
|
return new Proxy();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/** EOF **/
|
|
@ -48,12 +48,17 @@ const fs = require("fs");
|
||||||
const REQUEST_VERSION = "version";
|
const REQUEST_VERSION = "version";
|
||||||
const REQUEST_PING = "ping";
|
const REQUEST_PING = "ping";
|
||||||
const REQUEST_SETUP = "setup";
|
const REQUEST_SETUP = "setup";
|
||||||
|
const REQUEST_APPLICATIONS = "applications";
|
||||||
|
const REQUEST_RESOURCES = "resource";
|
||||||
|
|
||||||
const RESULT_OK = 200;
|
const RESULT_OK = 200;
|
||||||
const RESULT_PONG = 201;
|
const RESULT_PONG = 201;
|
||||||
const RESULT_NOTFOUND = 404;
|
const RESULT_NOTFOUND = 404;
|
||||||
const RESULT_ERROR = 500;
|
const RESULT_ERROR = 500;
|
||||||
|
|
||||||
|
const RESOURCE_TYPE_JAVASCRIPT = "js";
|
||||||
|
const RESOURCE_TYPE_CSS = "css";
|
||||||
|
const RESOURCE_TYPE_JSON = "json";
|
||||||
|
|
||||||
const MOUNTROOT_PATH = "/tmp/mnt/";
|
const MOUNTROOT_PATH = "/tmp/mnt/";
|
||||||
const APPDRIVE_PATH = "/appdrive/";
|
const APPDRIVE_PATH = "/appdrive/";
|
||||||
|
@ -70,6 +75,7 @@ const SYSTEM_PATH = "system/";
|
||||||
const SYSTEM_FRAMEWORK_PATH = "framework/";
|
const SYSTEM_FRAMEWORK_PATH = "framework/";
|
||||||
const SYSTEM_FRAMEWORK_JS = "framework.js";
|
const SYSTEM_FRAMEWORK_JS = "framework.js";
|
||||||
const SYSTEM_FRAMEWORK_CSS = "framework.css";
|
const SYSTEM_FRAMEWORK_CSS = "framework.css";
|
||||||
|
const SYSTEM_FRAMEWORK_VENDOR_PATH = "vendor/";
|
||||||
const SYSTEM_CUSTOM_PATH = "custom/";
|
const SYSTEM_CUSTOM_PATH = "custom/";
|
||||||
|
|
||||||
const JCI_MOUNT_PATH = "/tmp/mnt/data_persist/appdrive/"; // we link our resources in here
|
const JCI_MOUNT_PATH = "/tmp/mnt/data_persist/appdrive/"; // we link our resources in here
|
||||||
|
@ -217,16 +223,82 @@ cmu.prototype = {
|
||||||
|
|
||||||
if(this.appdrive && this.appdrive.enabled) {
|
if(this.appdrive && this.appdrive.enabled) {
|
||||||
|
|
||||||
// load javascripts
|
try {
|
||||||
this.requestLoadJavascript(this.resources.js);
|
|
||||||
|
|
||||||
// load css
|
// send appdrive
|
||||||
this.requestLoadCSS(this.resources.css);
|
this.sendFromPayload(client, payload, {
|
||||||
|
appdrive: this.appdrive
|
||||||
|
});
|
||||||
|
|
||||||
|
// load javascripts
|
||||||
|
this.requestLoadJavascript(this.resources.js);
|
||||||
|
|
||||||
|
// load css
|
||||||
|
this.requestLoadCSS(this.resources.css);
|
||||||
|
|
||||||
|
} catch(e) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applications
|
||||||
|
* @type REQUEST_APPLICATIONS
|
||||||
|
*/
|
||||||
|
case REQUEST_APPLICATIONS:
|
||||||
|
|
||||||
|
if(this.appdrive && this.appdrive.enabled) {
|
||||||
|
|
||||||
|
Object.keys(this.appdrive.applications).forEach(function(key) {
|
||||||
|
|
||||||
|
try{
|
||||||
|
let application = this.appdrive.applications[key];
|
||||||
|
|
||||||
|
this.requestLoadJavascript(application.files[APPLICATION_JS]);
|
||||||
|
|
||||||
|
this.requestLoadCSS(application.files[APPLICATION_CSS]);
|
||||||
|
|
||||||
|
}catch(e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource
|
||||||
|
* @type REQUEST_RESOURCES
|
||||||
|
*/
|
||||||
|
case REQUEST_RESOURCES:
|
||||||
|
|
||||||
|
console.log(payload);
|
||||||
|
|
||||||
|
/* switch(payload.type) {
|
||||||
|
|
||||||
|
case RESOURCE_TYPE_JSON:
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RESOURCE_TYPE_CSS:
|
||||||
|
|
||||||
|
console.log(request);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RESOURCE_TYPE_JAVASCRIPT:
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default - Pass to application handler
|
* Default - Pass to application handler
|
||||||
* @type default
|
* @type default
|
||||||
|
@ -304,8 +376,11 @@ cmu.prototype = {
|
||||||
*/
|
*/
|
||||||
invokeLoadCommand: function(command, files) {
|
invokeLoadCommand: function(command, files) {
|
||||||
|
|
||||||
let source = files instanceof Array ? files : ([].push(files)),
|
let data = [], source = files;
|
||||||
data = [];
|
|
||||||
|
if(!Array.isArray(files)) {
|
||||||
|
(source = []).push(files);
|
||||||
|
}
|
||||||
|
|
||||||
source.forEach(function(filename) {
|
source.forEach(function(filename) {
|
||||||
|
|
||||||
|
@ -410,6 +485,19 @@ cmu.prototype = {
|
||||||
// create symbolic link for this session
|
// create symbolic link for this session
|
||||||
fs.symlinkSync([systemPath, SYSTEM_CUSTOM_PATH].join(""), mountPath);
|
fs.symlinkSync([systemPath, SYSTEM_CUSTOM_PATH].join(""), mountPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find Vendor
|
||||||
|
*/
|
||||||
|
|
||||||
|
let vendorPath = [systemPath, SYSTEM_FRAMEWORK_PATH, SYSTEM_FRAMEWORK_VENDOR_PATH].join(""),
|
||||||
|
vendorFiles = fs.readdirSync(vendorPath);
|
||||||
|
|
||||||
|
if(vendorFiles.length) vendorFiles.forEach(function(fileName) {
|
||||||
|
|
||||||
|
this.resources.js.push([vendorPath, fileName].join(""));
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find Applications
|
* Find Applications
|
||||||
*/
|
*/
|
||||||
|
@ -430,9 +518,11 @@ cmu.prototype = {
|
||||||
if(this._isDir(applicationPath)) {
|
if(this._isDir(applicationPath)) {
|
||||||
|
|
||||||
let profile = {
|
let profile = {
|
||||||
id: appId,
|
|
||||||
path: applicationPath,
|
|
||||||
files: {},
|
files: {},
|
||||||
|
info: {
|
||||||
|
id: appId,
|
||||||
|
path: applicationPath,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
parts = [APPLICATION_JS, APPLICATION_JSON, APPLICATION_CSS, APPLICATION_WORKER],
|
parts = [APPLICATION_JS, APPLICATION_JSON, APPLICATION_CSS, APPLICATION_WORKER],
|
||||||
found = 0;
|
found = 0;
|
||||||
|
|
|
@ -47,6 +47,8 @@ window.CMU = {
|
||||||
|
|
||||||
REQUEST_PING: 'ping',
|
REQUEST_PING: 'ping',
|
||||||
REQUEST_SETUP: 'setup',
|
REQUEST_SETUP: 'setup',
|
||||||
|
REQUEST_APPLICATIONS: 'applications',
|
||||||
|
REQUEST_APPDRIVE: 'appdrive',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,6 +72,16 @@ window.CMU = {
|
||||||
RESULT_ERROR: 500,
|
RESULT_ERROR: 500,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource
|
||||||
|
*/
|
||||||
|
|
||||||
|
resource: {
|
||||||
|
JAVASCRIPT: 'js',
|
||||||
|
CSS: 'css',
|
||||||
|
JSON: 'json',
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the proxy
|
* Initializes the proxy
|
||||||
* @return void
|
* @return void
|
||||||
|
@ -82,6 +94,8 @@ window.CMU = {
|
||||||
|
|
||||||
this.requestBuffer = {};
|
this.requestBuffer = {};
|
||||||
|
|
||||||
|
this.waitForQueue = {};
|
||||||
|
|
||||||
this.obtainConnection();
|
this.obtainConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,13 +191,48 @@ window.CMU = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [requestSetup description]
|
* Request initial setup
|
||||||
* @return {[type]} [description]
|
* @return {[type]} [description]
|
||||||
*/
|
*/
|
||||||
requestSetup: function() {
|
requestSetup: function(callback) {
|
||||||
|
|
||||||
this.request(this.requests.REQUEST_SETUP);
|
this.request(this.requests.REQUEST_SETUP, false, function(error, result) {
|
||||||
|
|
||||||
|
this.appdrive = result.appdrive;
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the applicationst to be loaded
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
requestApplications: function() {
|
||||||
|
|
||||||
|
this.request(this.requests.REQUEST_APPLICATIONS);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [requestResource description]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
requestResource: function(type, files, location, callback) {
|
||||||
|
|
||||||
|
if(typeof(location) == "function") callback = location;
|
||||||
|
|
||||||
|
if(typeof(files) != "object") {
|
||||||
|
(files = []).push(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(files, location);
|
||||||
|
|
||||||
|
if(typeof(location) == "string") {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,8 +261,6 @@ window.CMU = {
|
||||||
|
|
||||||
payload.request = request;
|
payload.request = request;
|
||||||
|
|
||||||
console.log(payload);
|
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
return this.client.send(JSON.stringify(payload));
|
return this.client.send(JSON.stringify(payload));
|
||||||
},
|
},
|
||||||
|
@ -294,6 +341,53 @@ window.CMU = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (attach)
|
||||||
|
*/
|
||||||
|
|
||||||
|
attach: function(key, callback) {
|
||||||
|
|
||||||
|
if(this.has(key) || typeof(callback) != "function") return false;
|
||||||
|
|
||||||
|
this[key] = callback(this);
|
||||||
|
|
||||||
|
if(this.waitForQueue[key]) {
|
||||||
|
|
||||||
|
this.waitForQueue[key].forEach(function(callback) {
|
||||||
|
callback(this[key]);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
this.waitForQueue[key] = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (has)
|
||||||
|
*/
|
||||||
|
|
||||||
|
has: function(key) {
|
||||||
|
|
||||||
|
return this[key] ? true : false;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (waitFor)
|
||||||
|
*/
|
||||||
|
|
||||||
|
waitFor: function(key, callback) {
|
||||||
|
|
||||||
|
if(typeof(callback) != 'function') return false;
|
||||||
|
|
||||||
|
if(this.has(key)) return callback(this[key]);
|
||||||
|
|
||||||
|
if(!this.waitForQueue[key]) this.waitForQueue[key] = [];
|
||||||
|
|
||||||
|
this.waitForQueue[key].push(callback);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (__loadInvoker)
|
* (__loadInvoker)
|
||||||
|
@ -307,6 +401,8 @@ window.CMU = {
|
||||||
|
|
||||||
if(item.location && item.contents) {
|
if(item.location && item.contents) {
|
||||||
|
|
||||||
|
this.__unload(item.location);
|
||||||
|
|
||||||
var element = document.createElement(tag);
|
var element = document.createElement(tag);
|
||||||
element.setAttribute("data-script-url", item.location);
|
element.setAttribute("data-script-url", item.location);
|
||||||
element.appendChild(document.createTextNode(item.contents));
|
element.appendChild(document.createTextNode(item.contents));
|
||||||
|
@ -315,7 +411,21 @@ window.CMU = {
|
||||||
document.head.appendChild(element);
|
document.head.appendChild(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [__unload description]
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
__unload: function(location) {
|
||||||
|
|
||||||
|
var element = document.querySelector('[data-script-url="' + location + '"]');
|
||||||
|
|
||||||
|
if(element) {
|
||||||
|
document.head.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -353,7 +463,7 @@ window.CMU = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(window.opera) {
|
if(window.opera) {
|
||||||
window.opera.addEventListener('AfterEvent.load', function (e) {
|
window.opera.addEventListener('load', function (e) {
|
||||||
CMU.initialize();
|
CMU.initialize();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue