An ideal solution would dynamically generate the html pages. However, I do not have the time, nor the intention, to create a generic application that can be used by anyone. This means that the current demo has a very limited usability, but I hope you can use the javascript objects and the documentation below to quickly create your own application, corresponding to your needs.
The extended demo is a real-life setup. In this setup, we have
Some of the devices are input sources for the Bose V30 system :
The Philips Television can have other input sources as well. Only one is connected permanently (the Bose V30 system), but other sources can be added (PC media server, memory sticks, …)
This demo is available at index.html, and introduces some new javascript objects that allow to build a more generic web application.
We need to explain some new concepts.
e.g. if the active device is a blu-ray player, then the Play action will start playing the movie. If the active device is a media player, the Play action will start playing the playlist.
These concepts are translated into html through specific attributes, e.g.
<td class="oo_power" data-myuraction="OO_1"><div> </div></td>
The attributes are
attribute | info | usage |
---|---|---|
data-myurcontext | name of a context | added to buttons that allow to switch the context |
data-myuraction | name of an action to perform, or an alias of this action | added to an action button |
data-myurcomponent | name of a widget, to show or hide depending on the current context | add to a div element grouping some action buttons. This is related to our simplified, static implementation of widgets. |
data-myurparams | additional parameters when performing this action | added to some action buttons |
data-myurcallbackparams | additional parameters to pass to a callback function when performing this action | added to some action buttons |
attribute | info | usage |
---|---|---|
data-myurroom | name of a room in a Bose multi-room setup | added to buttons used dedicated to select a Bose room |
data-myursource | name of a source in a Bose setup | added to source switching buttons, specifically for Bose |
data-myurpower | name of a source to power on/off in a Bose setup | added to power buttons, specifically for Bose |
attribute | info | usage |
---|---|---|
data-myurbticino | name of a group of components in a bTicino MyHome setup | added to a container containing lights or shutters |
First we need to include some jquery files
<script src="js/jquery-1.7.2.min.js"></script> <script src="js/jquery.base64.min.js"></script> <script src="js/jquery.jsonp-2.1.2.js"></script> <script src="js/jquery-ui-1.8.20.custom.min.js"></script>
file | info | mandatory ? |
---|---|---|
jquery-1.7.2.min.js | jquery core file | yes |
jquery.base64.min.js | used for base64 encoding | only for Samsung SmartTV |
jquery.jsonp-2.1.2.js | used for communication with the MyURemote app | yes |
jquery-ui-1.8.20.custom.min.js | used for layout components (tabs) | yes (because our ui javascript object relies on this) |
<!-- Client-independent files Contain classes for communication with the MyURemote app --> <script src="js/devices.js"></script> <script src="js/myuremote.js"></script> <script src="js/gc.js"></script> <script src="js/rest.js"></script> <script src="js/own.js"></script> <script src="js/samsung.js"></script> <script src="js/viera.js"></script> <!-- Client-dependent configuration This will normally be created dynamically from a database The format is fixed. See the file clientconfig.js for a description of the format --> <script src="js/clientconfig.js"></script>
file | info |
---|---|
devices.js | contains all commands and templates for known devices |
myuremote.js | defines javascript object responsible for working with contexts, sending commands, logging |
gc.js | javascript object for GlobalCaché communication |
rest.js | javascript object for rest and http communication (Philips, Panasonic blu-ray) |
own.js | javascript object for communication with an OpenWebNet gateway (bTicino) |
samsung.js | javascript object for communication with a Samsung SmartTv |
viera.js | javascript object for communication with a Panasonic Viera television |
clientconfig.js | defines javascript objects specific to the end-user, e.g. an object containing the ip and mac address of the current machine, an object containing all extender instances, an object containing all device configuration info |
<!-- MyURemote ui setup --> <script src="js/ui/myurbose.js"></script> <script src="js/ui/myurbticino.js"></script> <script src="js/ui/myuremote-ui.js"></script>
file | info |
---|---|
myurbose.js | javascript object used to initialize and interpret the html attributes data-myurroom, data-myursource, data-myurpower |
myurbticino.js | javascript object used to initialize and interpret the html attribute data-myurbticino |
myuremote-ui.js | javascript object used to initialize and interpret the html attributes data-myurcontext, data-myurcomponent, data-myuraction |
When the document is loaded, everything is initialized using the call
<script type="text/javascript"> $(document).ready(function(){ initMyURemoteUi(); }); </script>
This calls the initMyURemoteUi() function, defined in the file myuremote-ui.js.
What happens when the page is loaded ?
Because the content is defined in a tab, we need to initialize the content from the moment the tab has been loaded. This is done by defining a load handler for the tab.
function initMyURemoteUi() { $.myuremote.startProfile("init"); $("#tabs").tabs({ load: function(event, ui) { initMyURemoteContexts(); } }); $("#tabs").tabs('select',0); $.myuremote.endProfile("init"); };
Note that the first tab is explicitly selected after the load handler is defined. The load handler itself calls the initMyURemoteContexts function, found in the same file.
Once the contents of the tab are loaded, the real work begins :
/** * Initialize the context buttons * For each button, we find the label as defined in the client_devices object, and add * it as the value of the button. * Furthermore, we assign an onclick handler */ for (var device in client_devices) { if (client_devices[device].type == "BOSE V30") { // initialize the Bose system, if available var myurbose = new MyURBose(device); myurbose.init(); } else if (client_devices[device].type == "OpenWebnet") { // initialize the bTicino domotics system, if available var myurbticino = new MyURBticino(device); myurbticino.init(); } }
$("[data-myuraction]").each(function(index, element) { $(this).bind('click', function(event) { $.myuremote.executeAction($(this).attr("data-myuraction"), $.parseJSON($(this).attr("data-myurparams")), $.parseJSON($(this).attr("data-myurcallbackparams"))); }); });
$("[data-myurcontext]").each(function(index, element) { $.myuremote.startProfile("change context"); var context = $(this).attr("data-myurcontext"); $.myuremote.log("log", "setting up context " + context); var device = client_devices[context]; $(this).prop('value',device.label); $(this).find("span").text(device.label); $(this).bind('click', function(event, ui) { var context = $(this).attr("data-myurcontext"); $.myuremote.log("log", "clicked context " + context); $.myuremote.setContext(context); $("[data-myurcomponent]").each(function(index, element) { var component = $(this).attr("data-myurcomponent"); if ($.myuremote.myuremoteContext.components.indexOf(component) >= 0) { $(this).show(); } else { $(this).hide(); } }); // layout changes $("[data-myurcontext]").removeClass("selected"); $("[data-myurcontext='"+context+"']").addClass("selected"); // now we are going to evaluate all action buttons, and // check which buttons to show or hide $("[data-myuraction]").each(function(index, element) { var action = $(this).attr("data-myuraction"); // check if an alias has been defined for the action. // if so, use the alias, otherwise continue with the action if ($.myuremote.myuremoteContext.aliases) { var alias = $.myuremote.checkAlias(action); if (alias) { action = alias; } } // check if the action is defined for this device, and enable/disable the button if (devices[$.myuremote.myuremoteContext.type][$.myuremote.myuremoteContext.technology] && devices[$.myuremote.myuremoteContext.type][$.myuremote.myuremoteContext.technology][action]) { $(this).removeClass("invisible"); $(this).find("span").text(action); } else { $(this).addClass("invisible"); $(this).find("span").text(""); } }); }); $.myuremote.endProfile("change context"); });
$("[data-myurcomponent]").each(function(index, element) { $(this).hide(); });
One of the steps described above consists of initializing the Bose system. When the function init() is called, the following happens (see the myurbose.js file) :
This initialization needs to be performed only once.
When the function init() is called, the following happens (see the myurbticino.js file) :
this.templates = { "lights" : '<tr>' + '<td>{0}</td><td><img src="img/default/light_on.png" data-myuraction="LIGHT" data-myurparams="[1,{1}]"></td>' + '<td><img src="img/default/light_off.png" data-myuraction="LIGHT" data-myurparams="[0,{1}]"></td>' + '<td> </td>' + '</tr>', "shutters" : '<tr>' + '<td>{0}</td><td><img src="img/default/shutter_up.png" data-myuraction="SHUTTER" data-myurparams="[1,{1}]"></td>' + '<td><img src="img/default/shutter_stop.png" data-myuraction="SHUTTER" data-myurparams="[0,{1}]"></td>' + '<td><img src="img/default/shutter_down.png" data-myuraction="SHUTTER" data-myurparams="[2,{1}]"></td>' + '<td> </td>' + '</tr>' };
This initialization needs to be performed only once.