1. HZG/WPN
  2. TangoREST
  3. mTango

Wiki

Clone wiki

mTango / Home

Welcome to mTangoSDK

mTangoSDK (mobile Tango Software Development Kit)'s main goal is to give developers tools for rapid development of web/mobile tango applications.

SDK consists of the following tools:

  1. mTangoREST.server -- a java web application that provides Tango REST API implementation. Basically it is a bridge from "http://" to "tango://". For more information please refer to this page ...
  2. mTangoREST-client -- a maven artifact. This artifact provides java classes for mTango-REST java client development. Refer to this page for more information...
  3. jsTangORB -- a javascript library for mTango-REST javascript client development. Refer to this page for more information...
  4. mTangoUI -- a framework for rapid web/mobile UI development. Refer to this page for more information...

Tools stack is described here:

The image is clickable!

stack

*-asterixed blocks represent tools of mTangoSDK

Technology's stack "for kids" was presented on DESY open doors day 2013 where a fischertechnik robot was controlled by an application developed using this SDK

Features

mTangoREST.server:

  • easy setup
  • two steps authorization
  • DatabaseDs and TangoAccessControl integration
  • events support
  • server side caches and optimizations
  • images into response injection

mTangoREST-client for Java:

  • distributed via maven
  • predefined type tokens

jsTangORB:

  • easy setup
  • high level abstraction API to mTangoREST.server
  • client side caches and optimizations

mTangoUI:

  • easy integration with Apache Cordova
  • predefined UI components
  • reliable error handling
  • client side optimizations

Prerequisites

  • Java SE 1.7u51 server runtime environment *)
  • Servlet 3.0 compatible container, i.e. Apache Tomcat 7.0.x (Tested on: 7.0.54 win7 64; //TODO)
  • Tango 8
  • Apache Cordova 4.0 (Tested on 4.2) for mobile platforms
  • Mobile device (Tested on Asus TF700T[Android 4.2.1] and Sony Xperia Z1 compact[Android 4.4.4])
*)  u55 and above has a problem with starting CORBA client, i.e. TangORB is not working.
This seems to be fixed in Java SE 8u25 and above

Getting started with mTangoREST.server

Refer to the mTangoREST server project page: hzgwpn/mtangorest.server

Getting started with mTangoUI

This section describes how to develop a web/mobile application using mTangoSDK. In this section you will be guided through a process of development an application that uses WebCam jTango Server to operate an USB webcam. WebCam server is chosen because most of the aspects of the development with this SDK can be demonstrated using it + it has real life application (at HZG we use it for tomography sample precharacterization) + it is very easy to setup.

In the end you will have a two-paged application. On the main page there will be Status displayed, a "Live" button and a video output; on the second page user will be able to change video output format. An example of the resulting application is presented in this image.

It is assumed that user has already set up Tango platform, i.e. TANGO_HOST is defined, DataBaseDs[sys/database/2] and TangoAccessControl[sys/access_control/1] are set up and running. For more information on how to set up Tango please refer to the Green site and the readme of the Tango distribution

It is also assumed that user runs windows system, even though everything should run smoothly on Linuxes as well.

Finally it is assumed that user runs standalone servlet container, i.e. downloaded Apache Tomcat 7 zip distribution. Apache Tomcat root is referred as {CATALINA_HOME} below.

Downloads

Setup

This section will guide you through setting up the components before starting development.

WebCam jTango server

Define WebCam device server local/webcam/0 in the Tango DB (class name = WebCam). Here is short tutorial on how to define java servers using jive

On windows unzip the distribution to somewhere (like c:\Programs). Open cmd, goto {WEBCAM_HOME}/bin and run start.bat local. Server must automatically recognize a webcam connected to your computer. Normally this is indicated by turning it on (a window with video output must appear).

For Linux a special setup is required, please refer to the WebCam's Wiki

mtango.server

See Getting started with mTangoREST.server

TangoAccessControl

User "mtango-js" must have write-access to the local/webcam/0 device. For this execute sys/access_control/1/AddDeviceForUser with argument ["mtango-js","local/webcam/0","write"].

mTangoUI

If you want *) to develop a mobile application then you need to set up cordova first. Please refer to the cordova's platforms guide

No setup is required for mTangoUI itself. You will unzip it into cordova's project www folder in the next section.

*) If not then just do nothing and skip cordova's stuff in the next section

Developing WebCam android app tutorial

In this tutorial we will develop an android application to operate our webcam.

If instead of android application you just want to develop a web application -- just skip cordova's stuff in this section.

NOTE: with cordova you can develop applications for any supported platform. Just follow cordova's documentation for your platform instead of android in the following sections.

Setting up cordova project

First create a cordova's project somewhere (cordova create WebCam my.tango.webcam WebCam) you should see the following output:

Creating a new cordova project with name "WebCam" and id "my.tango.webcam" at location
"D:\Projects\hzg.wpn.projects\mTango\cordova\WebCam"

Location from the output is later referred as {CORDOVA_PRJ_ROOT}

Delete everything from {CORDOVA_PRJ_ROOT}/www

Now unzip mTangoUI into {CORDOVA_PRJ_ROOT}/www

{CORDOVA_PRJ_ROOT}/www now must have the following structure:

d---------+ 1 khokhria Domain Users    0 Mar  5 16:36 .
d---------+ 1 khokhria Domain Users    0 Mar  5 16:25 ..
d---------+ 1 khokhria Domain Users    0 Mar  5 15:12 apps
d---------+ 1 khokhria Domain Users    0 Mar  5 15:12 controllers
d---------+ 1 khokhria Domain Users    0 Mar  5 16:34 docs
d---------+ 1 khokhria Domain Users    0 Mar  5 16:34 engines
d---------+ 1 khokhria Domain Users    0 Mar  5 16:34 jmvc
d---------+ 1 khokhria Domain Users    0 Mar  5 16:34 libs
d---------+ 1 khokhria Domain Users    0 Mar  5 15:12 models
d---------+ 1 khokhria Domain Users    0 Mar  5 15:12 pages
d---------+ 1 khokhria Domain Users    0 Mar  5 15:12 resources
d---------+ 1 khokhria Domain Users    0 Mar  5 16:34 stylesheets
d---------+ 1 khokhria Domain Users    0 Mar  5 16:34 test
d---------+ 1 khokhria Domain Users    0 Mar  5 15:12 views

----------+ 1 khokhria Domain Users  639 Mar  5 15:12 changelog.txt
----------+ 1 khokhria Domain Users  863 Mar  5 15:12 js
----------+ 1 khokhria Domain Users 1101 Mar  5 15:12 js.bat
----------+ 1 khokhria Domain Users  163 Mar  5 15:12 readme.txt

Now alter {CORDOVA_PRJ_ROOT}/config.xml. Specifically change src attribute of the content tag:

<!--<content src="index.html" />-->
<content src="apps/web_cam/index.html" />

Developing WebCam application

Development process itself is completely platform independent, if you develop web app just ignore cordova related stuff

Below {MTANGO_ROOT} is a directory where mTangoUI was unzipped (in case of cordova it is {CORDOVA_PRJ_ROOT}/www)

The resulting application can be downloaded from here.

Create a new WebCam application

Open console and goto {MTANGO_ROOT}. Execute the following:

Windows: js jmvc\mtango\app web_cam

Linux: ./js jmvc/mtango/app web_cam -- note ./

NOTE: there is an under_scoped naming convention (web_cam).

The following output indicates that application has been successfully created:

Generating ... apps/web_cam/web_cam.json
               apps/web_cam
               apps/web_cam/compress.js
               apps/web_cam/index.html
               apps/web_cam/run_unit.js
               apps/web_cam/test.js
               apps/web_cam.js
               controllers/web_cam/main_controller.js

Make sure to add new files to your application and test file!

               apps/web_cam.js
               apps/web_cam/test.js
json file has been saved.

               apps/web_cam/index.html
               apps/web_cam.js
               apps/web_cam/compress.js
               controllers/web_cam/main_controller.js
               controllers/web_cam/cordova_controller.js
               pages/web_cam/main/header.ejs
               pages/web_cam/main/content.ejs
               pages/web_cam/main/footer.ejs

               Done generating mTango app!

This has created an empty stub of the application. Lets highlight important things were created:

  1. apps/web_cam folder. The most important file in this folder is index.html -- an entry point to the application. You refer to this in the config.xml.
  2. apps/web_cam.js file -- this file defines structure of the application, i.e. which libraries, plugins and other javascript files to include into this application.
  3. controllers/web_cam -- this folder contains application's specific controllers. Initially it has two: main_controller.js and cordova_controller.js. Main has load method which is like main method in Java or C++. Cordova has methods (handlers) related to cordova API specific events.
  4. pages/web_cam/main -- this folder contains Main's page related templates: header.ejs, content.ejs and footer.ejs. These are correspond to jQuery mobile page's structure. In this tutorial we will alter only content.ejs

For more detailed information on mTangoUI application structure please refere to mTangoUI page

Create WebCam jTango Server javascript proxy

To interact with WebCam tango server we need a proxy (Similar to DeviceProxy from TangORB). For this open console goto {MTANGO_ROOT} and execute js jmvc/mtango/proxy tango://localhost:10000/local/webcam/0

The following output indicates that command has been successfully executed:

Generating ... models/WebCam.js

               Done!

Now you should notice a new file in the {MTANGO_ROOT}/models folder -- WebCam.js. This javascript file contains a model of WebCam jTango Server with all attributes and commands.

To use this model in the application add it into web_cam.js:

//{MTANGO_ROOT}/apps/web_cam.js

//include.models(
//    "web_cam/main_page"
//);
include.models(
    "web_cam/main_page","WebCam"
);

And finally create an instance of the proxy in main_controller.js:

//{MTANGO_ROOT}/controllers/web_cam/main_controller.js

//load: function(params){
//        var main = new MainPage();
//        main.load();
//...

load: function(params){
    //the first argument is an URL to the deployed mtango.server
    //the second -- tango device
    gWebCamProxy = new WebCam("http://localhost:8080/mtango","local/webcam/0");//here we create a global variable
                                                                               // and reflect it by 'g' in the name

    var main = new MainPage();
    main.load();
//...

Now we will add UI elements to our application...

Adjust {MTANGO_ROOT}/pages/WebCam/main/content.ejs. Part 1

NOTE to understand the following section you must understand WebCam jTango server API. For this please refer to its User manual

Here is the short capture from it:

To start video capture device execute [start] method of the server. To stop - [stop].

To capture current image - execute [capture] command. WebCam must be in RUNNING state

To get the image - read an attribute [image].

[supportedFormats] - is a spectrum attribute that enumerates all formats supported be the webcam

[currentFormat] - is a Read/Write attribute that defines current format in which webcam captures images.
    This attribute can not be set when webcam is in RUNNING state.

In this section we will add predefined in mTangoUI components to our application.

Open {MTANGO_ROOT}/pages/web_cam/main/content.ejs in your favorite editor. NOTE .ejs is an HTML file with embedded javascript. Javascript is enclosed in <% %>

Add the following:

<mtango:attr src="local/webcam/0/Status"
             view="fld_text_ro"
             poll="3000">
</mtango:attr>

<div class="ui-grid-a">
    <div class="ui-block-a">
        <mtango:cmd src="local/webcam/0/start">
        </mtango:cmd>
        <mtango:cmd src="local/webcam/0/capture">
        </mtango:cmd>
        <mtango:cmd src="local/webcam/0/stop">
        </mtango:cmd>
    </div>
    <div class="ui-block-b">
        <mtango:img src="local/webcam/0/image"
                    width="640"
                    height="480"
                    poll="3000"
                >
        </mtango:img>
    </div>
</div>


<mtango:attr src="local/webcam/0/supportedFormats"
                     view="fld_list_ro"
                     read>
</mtango:attr>

Now you can open your browser and navigate it to {MTANGO_ROOT}/apps/web_cam/index.html you should see a similar output: follow the link

Do not mind the red rectangle on the right hand side for now -- this is due to no image was captured so far.

Lets quickly look through the code we have just created. For more in-depth knowledge please refer to mTangoUI page.

WebCam Status:
<mtango:attr src="local/webcam/0/Status"
             view="fld_text_ro"
             poll="3000">
</mtango:attr>

This tag places a predefined read only scalar attribute on the page. src attribute defines the attribute; view defines UI of the attribute. There are several predefined views, this one is a read only text field; poll="3000" -- defines acquisition method. So basically this tag says "poll test/webcam/0/Status at every 3000 ms rate and display it as a predefined read only text field".

WebCam commands and image block:
<div class="ui-grid-a">
    <div class="ui-block-a">
        <mtango:cmd src="local/webcam/0/start">
        </mtango:cmd>
        <mtango:cmd src="local/webcam/0/capture">
        </mtango:cmd>
        <mtango:cmd src="local/webcam/0/stop">
        </mtango:cmd>
    </div>
    <div class="ui-block-b">
        <mtango:img src="local/webcam/0/image"
                    width="640"
                    height="480"
                    poll="3000"
                >
        </mtango:img>
    </div>
</div>

Here is a number of controls grouped into a single control group using jQuery mobile's Grid Widget

On the left hand side we have three commands:

<mtango:cmd src="local/webcam/0/start">
</mtango:cmd>
<mtango:cmd src="local/webcam/0/capture">
</mtango:cmd>
<mtango:cmd src="local/webcam/0/stop">
</mtango:cmd>

and on the right -- an image attribute:

<mtango:img src="local/webcam/0/image"
                    width="640"
                    height="480"
                    poll="3000"
                >
</mtango:img>

Here we say "poll test/webcam/0/image every 3000 ms and display it as an 640x480 px image". If width and height are omitted framework will use image's dimensions.

Supported Formats:

Finally at the very bottom we have a spectrum attribute that shows all the formats supported by our webcam:

<mtango:attr src="local/webcam/0/supportedFormats"
                     view="fld_list_ro"
                     read>
</mtango:attr>

Here we use another predefined view for read only spectrum attributes (fld_list_ro) and we read this attribute only once when application starts.

Other predefined views:

  • fld_text_ro -- read only text field
  • fld_text_rw -- read write text field
  • fld_list_rw -- read write list field

mTangoUI has also mtango:plot tag which is not used in this application.

Please refer to mTangoUI page for more detailed tutorials.

So basically this is already a fully functional application. You can execute [start] command and then [capture], newly captured images will be displayed on the right hand side.

Adjust {MTANGO_ROOT}/pages/WebCam/main/content.ejs. Part 2

In this section we will add a "Live" button and a new page to our application. On the new page user will be able to change output format.

Adding a new page to the application

First let's deal with the new page. Open console and goto {MTANGO_ROOT} and execute js jmvc\mtango\page\add video_format web_cam:

D:\Projects\hzg.wpn\mTangoSDK\cordova\WebCam\www>js jmvc\mtango\page\add video_format web_cam
Generating ... models/web_cam/video_format_page.js
               pages/web_cam/video_format/header.ejs
               pages/web_cam/video_format/content.ejs
               pages/web_cam/main/footer.ejs
               pages/web_cam/video_format/footer.ejs
               apps/web_cam.js
               apps/web_cam/test.js
               apps/web_cam/web_cam.json

               apps/web_cam.js

               Done!

Now a new folder has appeared in pages/web_cam folder -- video_format. As for main it contains three files: header.ejs, content.ejs and footer.ejs. Again as for main page we will adjust only content.ejs.

This creates an empty page. Before filling it we need to add it into our application: edit WebCam's main_controller as follows:

//{MTANGO_ROOT/controllers/web_cam/main_controller.js}

//...
    load: function(params){
        gWebCamProxy = new WebCam("http://localhost:8080/mtango","local/webcam/0");

        var main = new MainPage();
        main.load();

        //the following is a new stuff
        var video_format = new VideoFormatPage();
        video_format.load();
//...

Now we can start to add content to our new page. Open pages/web_cam/video_format/content.ejs in your favorite editor and add the following:

<button id="btnChangeFormat">Change Format</button>

<div id="btnChangeFormat_result"></div>

We will use div#btnChangeFormat_result to notify user whether change format command succeed or not.

Then cut'n'paste supportedFormats spectrum attribute from the main page to the video_format page and add an id attribute to it:

<button id="btnChangeFormat">Change Format</button>

<div id="btnChangeFormat_result"></div>

<mtango:attr src="local/webcam/0/supportedFormats"
             id="supportedFormats"
             view="fld_list_ro"
             read>
</mtango:attr>

This is it with the content. And now we need to add a controller to our button. This controller will take a value of supportedFormats and write it to local/webcam/0/currentFormat.

Implementing btnChangeFormat handler in the video_format controller:

First we create an empty controller by executing js jmvc\generate\controller change_video_format web_cam:

D:\Projects\hzg.wpn.projects\mTango\cordova\WebCam\www>js jmvc\generate\controller change_video_format web_cam
Generating ... controllers/change_video_format_controller.js
               test/functional/change_video_format_controller_test.js

               Done!

This creates a new js file in the controllers/web_cam folder -- change_video_format_controller.js.

This also creates a functional test stub for the controller. Testing is out of the scope of this tutorial so just delete it or leave where it is.

First we need to bind our newly created controller to btnChangeFormat:

//{MTANGO_ROOT}/controllers/web_cam/video_format_controller.js

//ChangeVideoFormatController = MVC.Controller.extend('change_video_format',
ChangeVideoFormatController = MVC.Controller.extend('btnChangeFormat', //value in quotes specifies an HTML element's id
                                                                       // events on this element will be handled by this controller

NOTE: more information on how controllers can be bound to HTML elements can be found here

Now we need to add video_format_controller to our application:

//{MTANGO_ROOT}/controllers/web_cam/video_format_controller.js

//...
/* @Prototype */
{
    /**
     * This function responds to user's click on the button
     *
     * @param {Object} params -- passed in data
     */
    click:function(params){
        var supportedFormats = DeviceAttributeUI.find_one("supportedFormats");//notice passed value -- it is id attribute specified in content.ejs
        //check a new format has been chosen
        //spectrum's argin is always an index of the chosen item, for scalar attributes it is a value
        var argin = supportedFormats.argin;
        var result = document.getElementById("btnChangeFormat_result");
        if(argin == null){
            alert("Please choose a new format below first");
        } else {
            //global WebCam jsTango proxy created in main_controller
            gWebCamProxy.set_currentFormat(argin, {
                //notice how we pass request handlers - in a dedicated object.
                //Both are optional
                onSuccess:function(){
                    //NOTE: local/webcam/0/supportedFormats returns an array of strings, while local/webcam/0/currentFormat expects index
                    result.innerHTML = "VideoFormat is set to " + supportedFormats.wrapped.response.argout[argin];//notice how we access attribute's value
                                                                                                                  // here we get desired string (a format)
                                                                                                                  // from an array by index (argin is an index)
                },
                onFailure:function(response){
                    //this uses View object from JavascriptMVC. Refer to its documentation for more details.
                    //Here we use predefined fld_error.ejs template from mTangoUI to render a nice looking error message
                    result.innerHTML = new View({url:mtango.ui.ERROR_VIEW_URL}).render({message:"Set currentFormat failed!",data:response});
                }
            });
        }
    }
}
//...

Now open your browser and navigate it to {MTANGO_ROOT}/apps/web_cam/index.html. The application now must have two pages: Main and VideoFormat. Change video format button should change webcam's capture format (this can be observed in the window related to WebCam Server).

To reflect format change in our application remove width and height attributes from mtango:img tag on the main page:

<!-- {MTANGO_ROOT}/pages/web_cam/main/content.ejs -->

<!--
<mtango:img src="local/webcam/0/image"
            width="640"
            height="480"
            poll="3000">
<mtango:img>
-->
<mtango:img src="local/webcam/0/image"
            poll="3000">
</mtango:img>

To become even more prettier move mtango:img out of the grid and layout mtango:cmd horizontally:

<div class="ui-grid-b">
    <div class="ui-block-a">
        <mtango:cmd src="local/webcam/0/start">
        </mtango:cmd>
    </div>
    <div class="ui-block-b">
        <mtango:cmd src="local/webcam/0/capture">
        </mtango:cmd>
    </div>
    <div class="ui-block-c">
        <mtango:cmd src="local/webcam/0/stop">
        </mtango:cmd>
    </div>
</div>

<mtango:img src="local/webcam/0/image"
            poll="3000">
</mtango:img>

You may want to centralize mtango:img:

<div class="center-wrapper">
    <mtango:img src="local/webcam/0/image"
            poll="3000">
    </mtango:img>
</div>

Check out the result in your browser!

Implementing "Live" button

In this section we will replace three mtango:cmd tags with a single "Live" button.

The idea of the live button is that it aggregates functionality of the three buttons we added in the previous sections. When user clicks on the live button and WebCam is in ON state our application executes local/webcam/0/start, then continuously captures an image in the background. If the device is in RUNNING state click on the live button executes local/webcam/0/stop and stops capturing images.

First replace mtango:cmd tags with a button:

<!-- {MTANGO_ROOT}/pages/web_cam/main/content.ejs -->

<!--
<div class="ui-grid-b">
    <div class="ui-block-a">
        <mtango:cmd src="local/webcam/0/start">
        </mtango:cmd>
    </div>
    <div class="ui-block-b">
        <mtango:cmd src="local/webcam/0/capture">
        </mtango:cmd>
    </div>
    <div class="ui-block-c">
        <mtango:cmd src="local/webcam/0/stop">
        </mtango:cmd>
    </div>
</div>
-->
<button id="btnLive">Live</button>

<div id="btnLive_result"></div>

As for btnChangeVideoFormat div#btnLive_result is placeholder for an error message in case btnLive has failed.

Then add a hidden mtango:attr State tag with an id attribute:

<mtango:attr src="local/webcam/0/State"
             id="State"
             view="fld_empty"
             poll="3000">
</mtango:attr>

Now we add a new controller to our application that will handle btnLive:

D:\Projects\hzg.wpn.projects\mTango\cordova\WebCam\www>js jmvc\generate\controller live web_cam
Generating ...  controllers/web_cam/live_controller.js
                test/functional/web_cam/live_controller_test.js
Generating ... apps/web_cam.js
               apps/web_cam/test.js
               apps/web_cam/web_cam.json


               Done!

As for change_video_format_controller bind newly created controller to the button:

//{MTANGO_ROOT}/controllers/web_cam/live_controller.js

//LiveController = MVC.Controller.extend('live',
LiveController = MVC.Controller.extend('btnLive', //bind this controller to button#btnLive

We also need to change our controller to stateful as we will need to preserve background task id:

//LiveController = MVC.Controller.extend('btnLive',
LiveController = MVC.Controller.Stateful.extend('btnLive',

MVC.Controller.Stateful is not defined by default -- it is a plugin we need to add to our application:

//{MTANGO_ROOT}/apps/web_cam.js

//include.plugins(
//    "controller","view","model","cordova"
//);

include.plugins(
    "controller","controller/stateful","view","model","cordova"
);

Stateful controller is a special controller which must be created manually. We do so in main_controller.js:

//{MTANGO_ROOT}/controllers/web_cam/main_controller.js


//...
    load:function(){
        //...
        var video_format = new VideoFormatPage();
        video_format.load();

        //the following is a new code
        new LiveController();

//...

Now lets get back to live_controller.js

//{MTANGO_ROOT}/controllers/web_cam/live_controller.js

//...
/* @Prototype */
{
    proxy    : null,
    _task_id : null,
    _is_active: false,
    /**
     * @constructor
     * @init_description
     *
     *  Creates a new instance of this controller
     *
     */
    init:function(){ //this function is invoked when we call 'new LiveController'
        this._super(MVC.$E('btnLive')); //calls "super" constructor with an element#btnLive
        //store global WebCam jsTango proxy created in main_controller
        this.proxy = gWebCamProxy;
    },
    /**
     * #btnLive onclick handler
     */
    click:function(){
        //shortcut for this.proxy
        var proxy = this.proxy;

        //get the latest polled State value
        var stateUI = DeviceAttributeUI.find_one('State'); //find a js instance of mtango:attr#State
        var stateAttr = stateUI.wrapped; //wrapped is an instance of mtango.DeviceAttribute from jsTangORB
                                         // obviously it is wrapped by the UI instance
        var state = stateAttr.response.argout; //response is an instance of mtango.Response from jsTangORB
                                               // it is the latest response from the server
                                               // that corresponds to the DeviceAttribute
        if(state == 'ON'){
            proxy.start({
                onSuccess:MVC.Function.bind(this._success,this), //here we bind function's 'this' reference.
                                                                 // If we just pass this._success without binding
                                                                 // 'this' reference will point to a wrong object (we want this object not anything else)
                onFailure: MVC.Function.bind(this._failure,this)
            });
        } else if (state == 'RUNNING') {
            //stop capturing
            proxy.stop({
                onFailure: MVC.Function.bind(this._failure,this)
            });
            //stop background task
            clearInterval(this.task_id)
            this._is_active = false;
        } else {
            //see jsTangORB API reference for the details on mtango.Response
            var failedResponse = new mtango.Response({quality:'INVALID',timestamp:Date.now()})
            failedResponse.add_errors(["Can not execute Live:","Unknown state = " + state])
            this._failure(failedResponse);
        }
    },
    /**
     * This function uses javascript's setInterval/clearInterval paradigm to define a background task
     *
     * (see http://www.w3schools.com/jsref/met_win_setinterval.asp)
     *
     * @private
     */
    _success:function(response){
        //closure
        var proxy = this.proxy;
        var me    = this;
        //captures every 3s
        this.task_id = setInterval(
            function(){
                console.log("Capturing image");//this is used for debugging in the following sections
                proxy.capture({
                    //we do not need onSuccess here because image is already polled
                    // otherwise here we would read image from proxy and update img
                    // element on the page
                    onFailure:MVC.Function.bind(me._failure,me)
                });
            },3000);
        this._is_active = true;
        //publish an event through MVC.OpenAjax.hub, other controllers may subscribe to this event
        // specifically we will vibrate our device on this event in the following section
        this.publish('live.is_active');
    },
    /**
     * Shows error message in div#btnLive_result
     *
     * @private
     */
    _failure:function(response){
        this._is_active = false;
        //stop background task
        clearInterval(this.task_id)
        //this uses View object from JavascriptMVC. Refer to its documentation for more details.
        //Here we use predefined fld_error.ejs template from mTangoUI to render a nice looking error message
        document.getElementById('btnLive_result').innerHTML =
            new View({url:mtango.ui.ERROR_VIEW_URL}).render({message:"Live has failed!",data:response});
    }

Now open your browser and check the result!

Prepare for deploying onto a mobile device

Before deploying the application onto a mobile device we have to adjust several things:

create WebCam jsTango proxy with an IP of the computer where mtango is running (replace locahost:8080)

Replace localhost:8080 in the new WebCam with an IP where your mtango is running and it is accessible within the network your device is connected to:

//{MTANGO_ROOT}/controllers/web_cam/main_controller.js

//...
    load: function(params){
        //var webCam = new WebCam("http://localhost:8080/mtango","local/webcam/0");
        gWebCamProxy = new WebCam("http://131.169.65.104:8080/mtango","local/webcam/0");

//...
considering background tasks halted on mobile specific events

As mobile device is mobile several things have to be considered before deploying an application, like: device may go offline, pause etc

In our application we have a number of background tasks: Status, State and image polling - these are handled by mTangoUI; other we have created by ourown - background capture interval created by click on the Live button.

To take care about "Live" background task (which constantly executes local/webcam/0/capture) we need these two functions added to the live_controller:

//{MTANGO_ROOT}/controllers/web_cam/live_controller.js

//...
    },
    /**
     * Cancels background task
     */
    pause:function(){
        clearInterval(this._task_id);
    },
    /**
     * Reschedules background task
     */
    resume:function(){
        if(this._is_active)
            //simulate successful response from local/webcam/0/start
            this._success();//we may call _success without argument because it does not really used
    }
});
//end of file

Now we can gently pause/resume our Live task in response to device's specific events. For this add the following to cordova_controller:

//{MTANGO_ROOT}/controllers/web_cam/corodva_controller.js

//...
     pause      : function () {
         console.log("onPause");
         DeviceAttribute.store.find().forEach(function (el) {
             el.pause_polling();
         });

         //the following is the new code:
         MVC.Controller.controllers.btnLive[0].pause();//MVC.Controller.controllers
                                                       // is an object where property names are controller names (the quoted value)
                                                       // each such property is an array of all controller instances with such name
                                                       // we created only one btnLive controller in main_controller, so we access it by '0'
     },
     /**
      * onResume
      */
     resume     : function () {
         console.log("onResume");
         //...
         //the following is the new code:
         MVC.Controller.controllers.btnLive[0].resume();
//...

To add online/offline events fired by cordova we need to add a corresponding plugin to cordova first. Open console, goto {CORDOVA_PRJ_ROOT} and execute:

D:\Projects\hzg.wpn.projects\mTango\cordova\WebCam>cordova plugin add org.apache.cordova.network-information
Fetching plugin "org.apache.cordova.network-information" via plugin registry
Installing "org.apache.cordova.network-information" for android

Adjust online/offline methods of cordova_controller in the same way as pause/resume.

Now our application handles correctly the most important state transitions of the device. This can be observed if you deploy onto an android mobile device and execute adb logcat | grep "Capturing image" you should notice that task stops when device sleeps or the application is in the background.

improving user experience

User experience with a mobile application can be significantly increased by adding some feedback features to the application, like vibro on button click.

To add a vibration when button is clicked first we need to install a corresponding plugin to cordova:

D:\Projects\hzg.wpn.projects\mTango\cordova\WebCam>cordova plugin add org.apache.cordova.vibration
Fetching plugin "org.apache.cordova.vibration" via plugin registry
Installing "org.apache.cordova.vibration" for android

Now we can capture button clicks and vibrate the device:

//{MTANGO_ROOT}/controllers/web_cam/cordova_controller.js

//...
    },
    /**
     * Vibrates the device when this application goes "Live"
     */
    "live.is_active subscribe":function(){
        navigator.vibrate(300);//vibrate for 300ms
    }
});
//end of file

More information on different cordova's plugins can be found here

Deploy onto device and check the result!

Deploy to a mobile device

Please follow Cordova's platforms guide for android to setup cordova's android platform if you have not done it so far.

Here we will add an android platform to our project (of course user may add any cordova supported platform, but for this tutorial we assume android).

NOTE: this section does not cover production deployment as it is out of the scope and vary a lot from case to case. Please refer to cordova's documentation.

For this open console and goto {CORDOVA_PRJ_ROOT} *) and execute cordova platform add android. The following output indicates that command succeed:

D:\Projects\hzg.wpn\mTangoSDK\cordova\WebCam>cordova platform add android
Creating android project...
Creating Cordova project for the Android platform:
        Path: platforms\android
        Package: my.tango.webcam
        Name: WebCam
        Android target: android-19
Copying template files...
Project successfully created.

You can change android target in {CORDOVA_PRJ_ROOT}/platforms/andoird/project.properties

Now to deploy our application onto mobile device connect it **) and execute cordova run... Enjoy!

*) CORDOVA_PRJ_ROOT points to the cordova project created in "Setting up cordova project" section.
**) make sure that android SDK is actually sees the device: execute adb devices, you should see the following output:

> D:\Projects\hzg.wpn\mTangoSDK\cordova\WebCam>adb devices
> * daemon not running. starting it now on port 5037 *
> * daemon started successfully *
> List of devices attached
> C8OKAS001100    device

The last line indicates your device.

Debugging

Since mTangoUI applications first of all are just web pages with a bunch of javascript files attached to it use firefox firebug plugin or IntelliJ IDEA built-in js debugger.

Logging

To log your actions within application use javascript's console object. This object is supported in firefox and android + console.log - is a standard function and must be supported in all browsers.

By default mTangoUI produces a lot of logging output. Developer may use it to find out and investigate problems:

In firefox use firebug or built-in developer tools.

In android use adb logcat to catch console output.

mTangoTest

If you want to skip the process of developing WebCam android application described above and just test something on the device you can install mTangoTest application:

From the folder where mTangoUI is unzipped *) execute js jmvc\mtango\mTangoTest on Windows or ./js jmvc/mtango/mTangoTest on Linux/Mac.

mTangoTest uses TangoTest server to test attributes read/write operations and commands execution. Plus it has a sample application with a plot. Plus -- file system interaction and 3D graphics. Feel free to explore the code of this application.

To deploy it onto a mobile device first alter cordova's config.xml, specifically src attribute of the content tag:

{CORDOVA_PRJ_ROOT} points to a location where cordova project was created (see the Setting up Cordova project section)

<!-- {CORDOVA_PRJ_ROOT}/config.xml -->

<!-- <content src="index.html" /> -->
<content src="apps/mTangoTest/index.html"/>

then follow the Deploy onto a mobile device section.

*) go through the Setup section of the Getting Started section but instead of WebCam jTango server start TangoTest

Have fun!

Benchmark tests

Test case:

read sys/tg_test/1/double_scalar for 10K times and measure total time.

All tests are performed on ASUS TF700T with Android 4.2.2 (API 17)

Tango host: i7-3740QM 2,7GHz; 32GB RAM Corsair PC3-12800; 54Mb/s WiFi

REST based tests use Apache TomCat 8.0.17 running on Java 1.8.0_25

TangORB for android

RESULT: ~8,5 ms for a request. NOTE: in this case device connects directly to the remote Tango device.

mTangoREST [this one]

RESULT: ~35 ms

RESTfulTango

RESULT: ~47 ms

Useful links

[1] mtango.server user guide

[2] mtangoREST Java client guide

[3] mtangoREST JavaScript client guide

[4] mtangoREST Python client guide

[5] jsTangORB API reference

[6] mTangoUI API reference

[7] JavaScriptMVC-1.5.x home page

[8] Cordova platforms guide

[9] Cordova plugins API

[10] Implement responsive design with jQuery Mobile and CSS3

[11] Optimizing jQuery mobile performance

[12] RESTful API documentation webinar

Updated