mirror of
https://github.com/flyandi/mazda-custom-application-sdk
synced 2024-12-23 03:35:29 -06:00
More CMU backend works
This commit is contained in:
parent
fb1eb10596
commit
846dd7ea78
11 changed files with 830 additions and 55 deletions
5
apps/app.helloworld/app.json
Normal file
5
apps/app.helloworld/app.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"id": "app.helloworld",
|
||||
"name": "Hello World",
|
||||
"enabled": true
|
||||
}
|
1
apps/appdrive.json
Normal file
1
apps/appdrive.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"bla": "foo"}
|
93
gulpfile.js
93
gulpfile.js
|
@ -50,7 +50,9 @@ var
|
|||
del = require('del'),
|
||||
fs = require('fs'),
|
||||
glob = require('glob'),
|
||||
exec = require('child_process').exec;
|
||||
exec = require('child_process').exec,
|
||||
using = require('gulp-using'),
|
||||
flatten = require('gulp-flatten');
|
||||
|
||||
/**
|
||||
* @package
|
||||
|
@ -109,7 +111,7 @@ var buildJsonVersion = function(output, destination, name, attributes) {
|
|||
/**
|
||||
* (build) local apps
|
||||
*
|
||||
* These tasks handle the copy and build of the local apps
|
||||
* These tasks handles the example apps
|
||||
*/
|
||||
|
||||
var appsPathInput = "./apps/",
|
||||
|
@ -149,59 +151,59 @@ gulp.task('build-apps', function(callback) {
|
|||
|
||||
|
||||
/**
|
||||
* tasks to build the runtime
|
||||
* tasks to build the framework
|
||||
*/
|
||||
|
||||
var systemPathOutput = output + "system/",
|
||||
runtimePathInput = input + "runtime/",
|
||||
runtimePathOutput = systemPathOutput + "runtime/",
|
||||
frameworkPathInput = input + "framework/",
|
||||
frameworkPathOutput = systemPathOutput + "framework/",
|
||||
customPathInput = input + "custom/";
|
||||
|
||||
// (cleanup)
|
||||
gulp.task('system-cleanup', function() {
|
||||
gulp.task('framework-cleanup', function() {
|
||||
return del(
|
||||
[systemPathOutput + '**/*']
|
||||
);
|
||||
});
|
||||
|
||||
// (skeleton)
|
||||
gulp.task('system-runtime-skeleton', function() {
|
||||
gulp.task('framework-skeleton', function() {
|
||||
|
||||
return gulp.src(runtimePathInput + "skeleton/**/*", {
|
||||
base: runtimePathInput + "skeleton"
|
||||
return gulp.src(frameworkPathInput + "skeleton/**/*", {
|
||||
base: frameworkPathInput + "skeleton"
|
||||
})
|
||||
.pipe(gulp.dest(runtimePathOutput));
|
||||
.pipe(gulp.dest(frameworkPathOutput));
|
||||
});
|
||||
|
||||
|
||||
// (less)
|
||||
gulp.task('system-runtime-less', function() {
|
||||
gulp.task('framework-less', function() {
|
||||
|
||||
return gulp.src(runtimePathInput + "less/*", {
|
||||
base: runtimePathInput + "less"
|
||||
return gulp.src(frameworkPathInput + "less/*", {
|
||||
base: frameworkPathInput + "less"
|
||||
})
|
||||
.pipe(concat('runtime.css'))
|
||||
.pipe(concat('framework.css'))
|
||||
.pipe(less())
|
||||
.pipe(gulp.dest(runtimePathOutput));
|
||||
.pipe(gulp.dest(frameworkPathOutput));
|
||||
});
|
||||
|
||||
|
||||
// (Concatenate & Minify)
|
||||
gulp.task('system-runtime-js', function() {
|
||||
gulp.task('framework-js', function() {
|
||||
|
||||
return gulp.src(runtimePathInput + "js/*", {
|
||||
base: runtimePathInput + "js"
|
||||
return gulp.src(frameworkPathInput + "js/*", {
|
||||
base: frameworkPathInput + "js"
|
||||
})
|
||||
.pipe(concat('runtime.js'))
|
||||
.pipe(concat('framework.js'))
|
||||
.pipe(uglify())
|
||||
.pipe(concatutil.header(fs.readFileSync(runtimePathInput + "resources/header.txt", "utf8"), {
|
||||
.pipe(concatutil.header(fs.readFileSync(frameworkPathInput + "resources/header.txt", "utf8"), {
|
||||
pkg: package
|
||||
}))
|
||||
.pipe(gulp.dest(runtimePathOutput));
|
||||
.pipe(gulp.dest(frameworkPathOutput));
|
||||
});
|
||||
|
||||
// (copy custom app)
|
||||
gulp.task('system-custom', function() {
|
||||
gulp.task('framework-custom', function() {
|
||||
return gulp.src(customPathInput + "**/*", {
|
||||
base: customPathInput
|
||||
})
|
||||
|
@ -209,25 +211,25 @@ gulp.task('system-custom', function() {
|
|||
});
|
||||
|
||||
/** @job system-version */
|
||||
gulp.task('system-version', function() {
|
||||
gulp.task('framework-version', function() {
|
||||
|
||||
buildJsonVersion("runtime.json", runtimePathOutput, "runtime-package", function(package) {
|
||||
buildJsonVersion("framework.json", frameworkPathOutput, "framework-package", function(package) {
|
||||
return {
|
||||
runtime: true,
|
||||
framework: true,
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// (build system)
|
||||
gulp.task('build-system', function(callback) {
|
||||
// (build framework)
|
||||
gulp.task('build-framework', function(callback) {
|
||||
runSequence(
|
||||
'system-cleanup',
|
||||
'system-runtime-skeleton',
|
||||
'system-runtime-less',
|
||||
'system-runtime-js',
|
||||
'system-custom',
|
||||
'system-version',
|
||||
'framework-cleanup',
|
||||
'framework-skeleton',
|
||||
'framework-less',
|
||||
'framework-js',
|
||||
'framework-custom',
|
||||
'framework-version',
|
||||
callback
|
||||
);
|
||||
});
|
||||
|
@ -380,6 +382,8 @@ gulp.task('build-sdcard', function(callback) {
|
|||
});
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Build documentation
|
||||
*/
|
||||
|
@ -597,7 +601,7 @@ gulp.task('clean', function() {
|
|||
gulp.task('default', function(callback) {
|
||||
runSequence(
|
||||
'clean',
|
||||
'build-system',
|
||||
'build-framework',
|
||||
'build-install',
|
||||
'build-uninstall',
|
||||
'build-sdcard',
|
||||
|
@ -605,3 +609,24 @@ gulp.task('default', function(callback) {
|
|||
callback
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Node
|
||||
*/
|
||||
|
||||
var nodePathInput = input + 'node-cmu/',
|
||||
nodePathSource = input + 'node/latest/',
|
||||
nodePathOutput = output + 'node/';
|
||||
|
||||
|
||||
// (cleanup)
|
||||
gulp.task('node', function() {
|
||||
|
||||
// copy embeeded files
|
||||
gulp.src(nodePathInput + "**/*.js", {
|
||||
base: nodePathInput
|
||||
}).pipe(flatten()).pipe(gulp.dest(nodePathOutput + 'cmu'));
|
||||
|
||||
|
||||
});
|
|
@ -15,6 +15,7 @@
|
|||
"gulp-concat": "^2.6.0",
|
||||
"gulp-concat-util": "^0.5.5",
|
||||
"gulp-file": "^0.2.0",
|
||||
"gulp-flatten": "^0.2.0",
|
||||
"gulp-git": "^1.7.0",
|
||||
"gulp-jsdoc": "^0.1.5",
|
||||
"gulp-less": "^3.0.5",
|
||||
|
@ -23,6 +24,7 @@
|
|||
"gulp-replace": "^0.5.4",
|
||||
"gulp-tar": "^1.8.0",
|
||||
"gulp-uglify": "^1.5.2",
|
||||
"gulp-using": "^0.1.0",
|
||||
"gulp-webserver": "^0.9.1",
|
||||
"run-sequence": "^1.1.5"
|
||||
},
|
||||
|
|
51
src/node-cmu/cmu-utils.js
Normal file
51
src/node-cmu/cmu-utils.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* Custom Application SDK for Mazda Connect Infotainment System
|
||||
*
|
||||
* A micro 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/
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
/**
|
||||
* A minimal implementation of the extend algorithm
|
||||
* @param Any object
|
||||
* @return object Returns an objec
|
||||
*/
|
||||
exports.extend = function(out) {
|
||||
|
||||
out = out || {};
|
||||
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
if (!arguments[i])
|
||||
continue;
|
||||
|
||||
for (var key in arguments[i]) {
|
||||
if (arguments[i].hasOwnProperty(key))
|
||||
out[key] = arguments[i][key];
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
356
src/node-cmu/cmu.js
Normal file
356
src/node-cmu/cmu.js
Normal file
|
@ -0,0 +1,356 @@
|
|||
/**
|
||||
* Custom Application SDK for Mazda Connect Infotainment System
|
||||
*
|
||||
* A micro 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/
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
const VERSION = "0.0.1";
|
||||
|
||||
/**
|
||||
* Definitions
|
||||
* @const
|
||||
*/
|
||||
|
||||
const _webSocketServer = require("ws").Server;
|
||||
const _extend = require("./cmu-utils").extend;
|
||||
const fs = require("fs");
|
||||
|
||||
/**
|
||||
* Minimal Command
|
||||
* @constants
|
||||
*/
|
||||
|
||||
const REQUEST_VERSION = "version";
|
||||
const REQUEST_PING = "ping";
|
||||
const REQUEST_APPLICATIONS = "applications";
|
||||
|
||||
const RESULT_OK = 200;
|
||||
const RESULT_PONG = 201;
|
||||
const RESULT_NOTFOUND = 404;
|
||||
const RESULT_ERROR = 500;
|
||||
|
||||
|
||||
const MOUNTROOT_PATH = "/tmp/mnt/";
|
||||
const APPLICATIONS_PATH = "/apps/";
|
||||
|
||||
const APPLICATION_JSON = "app.json";
|
||||
const APPLICATION_CSS = "app.css";
|
||||
const APPLICATION_JS = "app.js";
|
||||
const APPLICATION_WORKER = "worker.js";
|
||||
|
||||
const APPDRIVE_JSON = "appdrive.json";
|
||||
|
||||
/**
|
||||
* This is the CMU that is compiled into the node binary and runs the actual link between the
|
||||
* custom applications and the CMU.
|
||||
* @node-cmu
|
||||
*/
|
||||
|
||||
function cmu() {
|
||||
|
||||
this.__construct();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prototypes
|
||||
* @type The prototype object
|
||||
*/
|
||||
cmu.prototype = {
|
||||
|
||||
/**
|
||||
* The version number
|
||||
* @var string
|
||||
*/
|
||||
version: VERSION,
|
||||
|
||||
/**
|
||||
* The network object
|
||||
* @var array
|
||||
*/
|
||||
network: {
|
||||
|
||||
/**
|
||||
* The network port
|
||||
*/
|
||||
port: 9700,
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs the CMU object
|
||||
* @constructor
|
||||
*/
|
||||
__construct: function()
|
||||
{
|
||||
this.applications = {};
|
||||
|
||||
this.__socket = new _webSocketServer({
|
||||
port: this.network.port
|
||||
});
|
||||
|
||||
this.__socket.on('connection', function(client) {
|
||||
|
||||
this.attachClient(client);
|
||||
|
||||
}.bind(this));
|
||||
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Preps a client
|
||||
* @param object client The client instance
|
||||
* @return void
|
||||
*/
|
||||
attachClient: function(client) {
|
||||
|
||||
client.on('message', function(message) {
|
||||
|
||||
this.handleClientData(client, message);
|
||||
|
||||
}.bind(this));
|
||||
|
||||
client.on('close', function() {
|
||||
|
||||
// do nothing
|
||||
});
|
||||
|
||||
client.on('error', function(e) {
|
||||
|
||||
// do nothing
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles a client message
|
||||
* @param object client The client instance
|
||||
* @param string message The message payload
|
||||
* @return void
|
||||
*/
|
||||
handleClientData: function(client, message, flags) {
|
||||
|
||||
try {
|
||||
var payload = JSON.parse(message);
|
||||
|
||||
// process minimal command interfae
|
||||
if(payload.request) {
|
||||
|
||||
switch(payload.request) {
|
||||
|
||||
/**
|
||||
* Returns the current CMU backend version
|
||||
* @type REQUEST_VERSION
|
||||
*/
|
||||
case REQUEST_VERSION:
|
||||
|
||||
return this.sendFromPayload(client, payload, {
|
||||
version: this.getVersion()
|
||||
});
|
||||
break;
|
||||
|
||||
/**
|
||||
* Heartbeat
|
||||
* @type REQUEST_PING
|
||||
*/
|
||||
case REQUEST_PING:
|
||||
|
||||
return this.sendFromPayload(client, payload, {
|
||||
outboundStamp: (new Date()).getTime()
|
||||
}, RESULT_PONG);
|
||||
break;
|
||||
|
||||
/**
|
||||
* Returns the current registered applications
|
||||
* @type REQUEST_APPLICATIONS
|
||||
*/
|
||||
case REQUEST_APPLICATIONS:
|
||||
|
||||
// find applications
|
||||
this.findApplications(function(applications, appdrive) {
|
||||
|
||||
this.sendFromPayload(client, payload, {
|
||||
applications: applications,
|
||||
appdrive: appdrive,
|
||||
});
|
||||
|
||||
}.bind(this));
|
||||
|
||||
break;
|
||||
|
||||
/**
|
||||
* Default - Pass to application handler
|
||||
* @type default
|
||||
*/
|
||||
default:
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends a payload back to the client
|
||||
* @param object client The client
|
||||
* @param object payload The payload in object format
|
||||
* @return boolean Returns the status of the operation
|
||||
*/
|
||||
sendFromPayload: function(client, payload, data, resultCode) {
|
||||
|
||||
var final = JSON.stringify(_extend({}, payload, data, {
|
||||
result: resultCode || RESULT_OK
|
||||
}));
|
||||
|
||||
client.send(final);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the version
|
||||
* @getter
|
||||
* @return string The version number
|
||||
*/
|
||||
getVersion: function() {
|
||||
return this.version;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Finds all applications in known locations
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
findApplications: function(callback) {
|
||||
|
||||
this.applications = {};
|
||||
|
||||
this.appdrive = false;
|
||||
|
||||
var result = [],
|
||||
mountPoints = ['sd_nav', 'sda', 'sdb', 'sdc', 'sdd', 'sde'];
|
||||
|
||||
mountPoints.forEach(function(mountPoint) {
|
||||
|
||||
var path = [MOUNTROOT_PATH, mountPoint, APPLICATIONS_PATH].join(""),
|
||||
|
||||
appdriveFilename = [path, APPDRIVE_JSON].join("");
|
||||
|
||||
if(this._isFile(appdriveFilename)) {
|
||||
|
||||
this.appdrive = require(appdriveFilename);
|
||||
}
|
||||
|
||||
if(this._isDir(path)) {
|
||||
|
||||
var files = fs.readdirSync(path);
|
||||
|
||||
if(files.length) files.forEach(function(appId) {
|
||||
|
||||
/**
|
||||
* currently we only allow the first application to be registered
|
||||
* otherwise you would need to restart the CMU
|
||||
*/
|
||||
|
||||
if(!this.applications[appId]) {
|
||||
|
||||
var applicationPath = [path, appId, "/"].join("");
|
||||
|
||||
if(this._isDir(applicationPath)) {
|
||||
|
||||
var profile = {
|
||||
appId: appId,
|
||||
appPath: applicationPath,
|
||||
files: {},
|
||||
},
|
||||
parts = [APPLICATION_JS, APPLICATION_JSON, APPLICATION_CSS, APPLICATION_WORKER],
|
||||
found = 0;
|
||||
|
||||
parts.forEach(function(filename) {
|
||||
|
||||
var fullFilename = [applicationPath, filename].join("");
|
||||
|
||||
if(this._isFile(fullFilename)) {
|
||||
|
||||
profile.files[filename] = fullFilename;
|
||||
found++;
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
|
||||
if(found >= 1) {
|
||||
this.applications[appId] = profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
}.bind(this));
|
||||
|
||||
if(callback) callback(this.applications, this.appdrive);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* __fileExists
|
||||
*/
|
||||
|
||||
_isFile: function(path) {
|
||||
try {
|
||||
return fs.lstatSync(path).isFile();
|
||||
} catch(e) {}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the directory exists
|
||||
* @param {[type]} path [description]
|
||||
* @return {Boolean} [description]
|
||||
*/
|
||||
_isDir: function(path) {
|
||||
try {
|
||||
return fs.lstatSync(path).isDirectory();
|
||||
} catch(e) {}
|
||||
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
exports = new cmu();
|
||||
|
||||
/**
|
||||
/** eof */
|
25
src/node-cmu/test/index.html
Normal file
25
src/node-cmu/test/index.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="../../system/CustomApplications.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
CustomApplications.initialize();
|
||||
|
||||
|
||||
Logger.subscribe(function(level, name, msg, color) {
|
||||
console.log(
|
||||
'%c[' + level + '] %c[' + name + '] ' + msg,
|
||||
'color:' + color,
|
||||
'color:black'
|
||||
);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<strong>CMU Protocol Test</strong>
|
||||
</body>
|
||||
</html>
|
|
@ -67,6 +67,7 @@ RUN cd ${NODE_SOURCE_PACKAGE}
|
|||
# Change work dir
|
||||
WORKDIR /armv7l/${NODE_SOURCE_PACKAGE}
|
||||
|
||||
|
||||
# Configure
|
||||
RUN ./configure --without-snapshot --dest-cpu=arm --dest-os=linux --fully-static --without-ssl --tag=CASDK-NODE
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/* eslint-disable require-buffer */
|
||||
'use strict';
|
||||
|
||||
//const binding = process.binding('cmu');
|
||||
const cmu = exports;
|
||||
|
||||
|
||||
cmu.version = function() {
|
||||
return "It a worked!";
|
||||
}
|
|
@ -24,28 +24,127 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* (GlobalError)
|
||||
* This is the main system file that manages everything between the CMU backend server and the frontend.
|
||||
*/
|
||||
|
||||
window.onerror = function() {
|
||||
console.error(arguments);
|
||||
}
|
||||
/**
|
||||
* (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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* (CustomApplicationsProxy)
|
||||
* (CustomApplications)
|
||||
*
|
||||
* Registers itself between the JCI system and CustomApplication runtime.
|
||||
*/
|
||||
|
||||
window.CustomApplicationsProxy = {
|
||||
window.CustomApplications = {
|
||||
|
||||
ID: 'system',
|
||||
|
||||
/**
|
||||
* (locals)
|
||||
*/
|
||||
|
||||
debug: false,
|
||||
bootstrapped: false,
|
||||
|
||||
|
@ -59,6 +158,226 @@ window.CustomApplicationsProxy = {
|
|||
targetAppName: 'custom',
|
||||
targetAppContext: 'Surface',
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*/
|
||||
configuration: {
|
||||
|
||||
networkHost: '127.0.0.1',
|
||||
networkPort: 9700,
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Commands
|
||||
*/
|
||||
commands: {
|
||||
|
||||
REQUEST_PING: 'ping',
|
||||
REQUEST_APPLICATIONS: 'applications',
|
||||
},
|
||||
|
||||
/**
|
||||
* Results
|
||||
*/
|
||||
results: {
|
||||
|
||||
RESULT_OK: 200,
|
||||
RESULT_PONG: 201,
|
||||
RESULT_NOTFOUND: 404,
|
||||
RESULT_ERROR: 500,
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes the proxy
|
||||
* @return void
|
||||
*/
|
||||
initialize: function() {
|
||||
|
||||
this.requests = {};
|
||||
|
||||
this.obtainConnection();
|
||||
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 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.requestApplications();
|
||||
|
||||
}.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 Custom Applications
|
||||
* @return void
|
||||
*/
|
||||
requestApplications: function() {
|
||||
|
||||
if(typeof(CustomApplicationsHandler) != "undefined") return false;
|
||||
|
||||
if(!this.request(this.commands.REQUEST_APPLICATIONS, false, function(error, result) {
|
||||
|
||||
if(error) {
|
||||
|
||||
return setTimeout(function() {
|
||||
|
||||
this.requestApplications();
|
||||
|
||||
}.bind(this), 100);
|
||||
}
|
||||
|
||||
console.log(result);
|
||||
|
||||
}.bind(this)));
|
||||
},
|
||||
|
||||
/**
|
||||
* (bootstrap)
|
||||
|
@ -66,7 +385,7 @@ window.CustomApplicationsProxy = {
|
|||
* Bootstraps the JCI system
|
||||
*/
|
||||
|
||||
bootstrap: function() {
|
||||
bootstrap: function() {
|
||||
|
||||
// verify that core objects are available
|
||||
if(typeof framework === 'object' && framework._currentAppUiaId === this.systemAppId && this.bootstrapped === false) {
|
||||
|
@ -349,7 +668,7 @@ window.CustomApplicationsProxy = {
|
|||
|
||||
if(window.opera) {
|
||||
window.opera.addEventListener('AfterEvent.load', function (e) {
|
||||
CustomApplicationsProxy.bootstrap();
|
||||
CustomApplications.initialize();
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in a new issue