-
-
Save quinkennedy/2668550 to your computer and use it in GitHub Desktop.
ecs.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// BIND FIX FOR OLDER BROWSERS | |
if( Function.prototype.bind ) { | |
} else { | |
/** safari, why you no bind!? */ | |
Function.prototype.bind = function (bind) { | |
var self = this; | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
return self.apply(bind || null, args); | |
}; | |
}; | |
} | |
/*! | |
* \namespace ECSjs | |
* \brief An javascript library to connect to ECS installation. | |
* <br />Copyright (C) 2012 LAB at Rockwell Group http://lab.rockwellgroup.com | |
* | |
* @author The Lab | |
* @modified 05/11/2012 | |
* @version 0.0.3 | |
*/ | |
var ECSjs = {} | |
/*! \class ECSjs::Connection | |
\brief Creates a new ECS connection with host | |
*/ | |
ECSjs.Connection = function( framework ){ | |
this.bConnected = false | |
this.framework = framework || ECSjs.ECS; | |
this.onConnectHooks = []; | |
this.onDisconnectHooks = []; | |
this.onMessageHooks = []; | |
this.onStartHooks = []; | |
this.onStopHooks = []; | |
this.onFileHooks = []; | |
this.onStartupHooks = []; | |
this.onActivateHooks = []; | |
this.onDeactivateHooks = []; | |
this.onShutdownHooks = []; | |
}; | |
/*! \fn ECSjs::Connection::connect | |
* \brief Setup ECS connection | |
* \memberof ECSjs::Connection | |
* \param host (optional) The host of the ecsc that this application should connect to. Defaults to 127.0.0.1. You must specify a host if you are connecting to a remote ECS server. | |
* \param port (optional) The port on the host of the ecsc that this application should connect to. Defaults to 7847 (ECS default). You must specify a port if you change the port your local or remote ECS server is running on. | |
* \param channel (optional) The websocket channel that this application should use to connect to the host. Defalut to "/" | |
* \param role (optional) The ECS role that this application is fulfilling | |
* | |
*/ | |
ECSjs.Connection.prototype.connect = function( host, port, channel, role ) { | |
this.role = role || ""; | |
this.host = host || "127.0.0.1"; | |
this.port = port || 7847; | |
this.channel = channel || "/"; | |
this.socket = new WebSocket("ws://"+this.host+":"+this.port+this.channel); | |
this.socket._parent = this; | |
this.socket.onmessage = this.onWSMessage.bind(this); | |
this.socket.onopen = this.onConnectionOpened.bind(this); | |
this.socket.onclose = this.onConnectionClosed.bind(this); | |
}; | |
/*! | |
* \fn ECSjs::Connection::sendMessage | |
* \brief Send an ECS message | |
* \memberof ECSjs::Connection | |
* \param key The name of the route you are sending. | |
* \param value the value you are sending | |
*/ | |
ECSjs.Connection.prototype.sendMessage = function( key, value ) { | |
if (!this.bConnected){ | |
if (console) console.warn("Not connected!"); | |
return; | |
} | |
if( this.framework == ECSjs.ECS ) { | |
this.socket.send( "<route_update><configs><config><name>"+key+"</name><value>"+value+"</value></config></configs></route_update>" ); | |
} else { | |
value['route'] = key; | |
this.socket.send( JSON.stringify(value) ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onMessage | |
* \brief Pass in a function to receive messages from ECS | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called; must catch (key, value) | |
*/ | |
ECSjs.Connection.prototype.onMessage = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onMessage is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onMessageHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onConnect | |
* \brief Pass in a function in your add a listener to "connect" events from ECS. | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onConnect = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onConnect is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onConnectHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onDisconnect | |
* \brief Pass in a function in your add a listener to "disconnect" events | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onDisconnect = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onDisconnect is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onDisconnectHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onStart | |
* \brief Pass in a function in your add a listener to "start" events from ECS. | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onStart = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onStart is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onStartHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onStop | |
* \brief Pass in a function in your add a listener to "stop" events from ECS. | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onStop = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onStop is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onStopHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onStartup | |
* \brief Pass in a function in your add a listener to "startup" events from Interactive Spaces. | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onStartup = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onStartup is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onStartupHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onActivate | |
* \brief Pass in a function in your add a listener to "activate" events from Interactive Spaces. | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onActivate = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onActivate is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onActivateHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onDeactivate | |
* \brief Pass in a function in your add a listener to "deactivate" events from Interactive Spaces. | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onDeactivate = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onDeactivate is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onDeactivateHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onShutdown | |
* \brief Pass in a function in your add a listener to "shutdown" events from Interactive Spaces. | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called | |
*/ | |
ECSjs.Connection.prototype.onShutdown = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onShutdown is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onShutdownHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onFile | |
* \brief Pass in a function to receive files from ECS | |
* \memberof ECSjs::Connection | |
* \param fun function you would like to be called; must catch (filepath) | |
*/ | |
ECSjs.Connection.prototype.onFile = function( fun ) { | |
if ( typeof fun !== "function" ){ | |
console.warn( "method passed to ECSjs.Connection.onFile is not a function"); | |
} else { | |
// DEV NOTE: SHOULD WE CHECK FOR DUPLICATES? | |
this.onFileHooks.push( fun ); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::onConnectionOpened | |
* \memberof ECSjs::Connection | |
* \private | |
*/ | |
ECSjs.Connection.prototype.onConnectionOpened = function() { | |
this.bConnected = true; | |
if (console) console.log("ECS connected"); | |
if( this.framework == ECSjs.ECS ) { | |
this.socket.send("<application_message><role>"+this.role+"</role></application_message>"); | |
} | |
this.callAllFuncInArray(this.onConnectHooks); | |
}; | |
/*! | |
* \fn ECSjs::Connection::onConnectionClosed | |
* \memberof ECSjs::Connection | |
* \private | |
*/ | |
ECSjs.Connection.prototype.onConnectionClosed = function() { | |
this.bConnected = false; | |
this.callAllFuncInArray(this.onDisconnectHooks); | |
}; | |
/*! | |
* \fn ECSjs::Connection::callAllFuncInArray | |
* \brief A utility function to call every function in an array of functions without any arguments | |
* \memberof ECSjs::Connection | |
* \private | |
*/ | |
ECSjs.Connection.prototype.callAllFuncInArray = function(array){ | |
for(var i in array){ | |
array[i](); | |
}; | |
}; | |
/*! | |
* \fn ECSjs::Connection::onWSMessage | |
* \memberof ECSjs::Connection | |
* \private | |
*/ | |
ECSjs.Connection.prototype.onWSMessage = function( evt ) { | |
if( this.framework == ECSjs.ECS ) { | |
var xml; | |
if (window.DOMParser){ | |
var parser=new DOMParser(); | |
xml = parser.parseFromString(evt.data, "text/xml"); | |
} else { | |
// Internet Explorer | |
xml = new ActiveXObject("Microsoft.XMLDOM"); | |
xml.async=false; | |
xml.loadXML(evt.data); | |
} | |
if (evt.data.indexOf("route_update") >= 0) { | |
var configs = xml.getElementsByTagName("configs")[0].childNodes; | |
for (var i=0; i < configs.length; i++) { | |
var name = null; | |
var value = null; | |
var curConfig = configs[i]; | |
// Config name | |
var n = curConfig.getElementsByTagName("name")[0]; | |
name = n.childNodes[0].nodeValue; | |
// Config value | |
var val = curConfig.getElementsByTagName("value")[0]; | |
value = val.childNodes[0].nodeValue; | |
// Invoke route update method if we have a complete name/value pair | |
if (name != null && value != null) { | |
for (var i=0; i<this.onMessageHooks.length; i++){ | |
this.onMessageHooks[i](name, value); | |
}; | |
} | |
} | |
} else if (evt.data.indexOf("application_message") >= 0) { | |
var action = xml.getElementsByTagName("action")[0]; | |
var a = action.childNodes[0].nodeValue; | |
if (a == "start"){ | |
this.callAllFuncInArray(this.onStartHooks); | |
} else if (a == "stop"){ | |
this.callAllFuncInArray(this.onStopHooks); | |
} | |
} else if (evt.data.indexOf("file_transfer") >= 0) { | |
var action = xml.getElementsByTagName("filepath")[0]; | |
var fp = action.childNodes[0].nodeValue; | |
// Invoke the file transfer method with the file path | |
if (fp != null && !fp.equals("")) { | |
for (var i=0; i<this.onFileHooks.length; i++){ | |
this.onFileHooks[i](fp); | |
} | |
} | |
} | |
} else if (this.framework == ECSjs.INTERACTIVE_SPACES){ | |
var dataObj = JSON.parse( evt.data ); | |
if (dataObj.route == "state"){ | |
switch (dataObj.data.state){ | |
case "startup": | |
this.callAllFuncInArray(this.onStartupHooks); | |
break; | |
case "activate": | |
this.callAllFuncInArray(this.onActivateHooks); | |
break; | |
case "deactivate": | |
this.callAllFuncInArray(this.onDeactivateHooks); | |
break; | |
case "shutdown": | |
this.callAllFuncInArray(this.onShutdownHooks); | |
break; | |
default: | |
console.warn( "state passed via websocket is unexpected:"); | |
console.warn(dataObj); | |
break; | |
} | |
} else { | |
this.defaultMessageHandling(evt); | |
} | |
} else { | |
this.defaultMessageHandling(evt); | |
} | |
}; | |
/*! | |
* \fn ECSjs::Connection::defaultMessageHandling | |
* \brief Handles the default functionality for onWSMessage | |
* \memberof ECSjs::Connection | |
* \private | |
*/ | |
ECSjs.Connection.prototype.defaultMessageHandling = function(evt){ | |
var dataObj = JSON.parse( evt.data ); | |
if ( dataObj.route ) { | |
for (var i=0; i<this.onMessageHooks.length; i++){ | |
this.onMessageHooks[i](dataObj.route, dataObj.data); | |
}; | |
} else { | |
for (var i=0; i<this.onMessageHooks.length; i++){ | |
this.onMessageHooks[i]( "route", dataObj ); | |
}; | |
} | |
} | |
/** @constant */ | |
ECSjs.ECS = "ecs"; | |
/** @constant */ | |
ECSjs.INTERACTIVE_SPACES = "interactiveSpaces"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment