Dashkiosk’s documentation

Dashkiosk logo

Dashkiosk is a solution to manage dashboards on multiple screens. It comes in three parts:

  1. A server will manage the screens by sending them which URL they should display in realtime. A web interface enables the administrator to configure groups of dashboards as well as their associations with available displays.
  2. A receiver runs in a browser attached to each screen. On start, it contacts the server and waits for it to tell which URL to display.
  3. An Android application provides a simple fullscreen webview to display the receiver.

The Android application is an optional component. Any device able to display a fullscreen web page should work.

To contribute, use GitHub.

Installation

The server is a Node.js application providing a rendez-vous point for all displays to subscribe using a Websocket protocol as well as an administration page to manage all displays, group them and tell them which URL to display.

Server and receiver

To install it, you need to execute the following step:

  1. Grab the latest tarball for Dashkiosk from GitHub.

  2. Install Node.js and optionally npm. Currently, Dashkiosk only works with Node.js 0.10.x which is the current stable version. If the version available in your distribution is not up-to-date, have a look at how to install Node.js via the package manager before trying to build from the sources.

  3. Install bower and grunt, two package managers for Javascript with the following command:

    $ npm install -g bower grunt-cli
    
  4. Unpack Dashkiosk in the directory of your choice and go into that directory.

  5. Install the appropriate dependencies with the following commands:

    $ npm install
    $ bower install
    
  6. Build the final version of Dashkiosk with the following command:

    $ grunt
    
  7. Upon success, you will get a dist directory that you can put on some server. It includes both the receiver and the server part. If you want to use the Android application, you still need to build it and install it. See Android application.

Branding

As is, Dashkiosk is branded for Deezer. If you do not like that, there are two images that you should modify before building the final version with grunt.

  • The spinning vinyl is located in app/images/loading.svg. You should be able to replace it by anything that will give a cool effect while spinning. In this case, please submit it back.
  • The Deezer logo appearing both in the administration interface and in the default dashboard is located in app/images/stamp.svg. Put your favorite logo instead.

Database

Dashkiosk stores its data inside some database. By default, it uses SQLite. If you prefer to use another database, this is quite easy. We will use PostgreSQL but this should be easy to transpose to another database supported by Sequelize.js, the ORM used in Dashkiosk. The databases currently supported are:

  • MySQL,
  • MariaDB,
  • SQLite, and
  • PostgreSQL.

Here are the steps:

  1. Create a dedicated user inside your RDBMS. For PostgreSQL, this is done as the postgres user with the following command:

    $ createuser -P dashkiosk
    Enter password for new role:
    Enter it again:
    Shall the new role be a superuser? (y/n) n
    Shall the new role be allowed to create databases? (y/n) n
    Shall the new role be allowed to create more new roles? (y/n) n
    
  2. Create an empty database. For PostgreSQL, this is also done as the postgres user:

    $ createuser -O dashkiosk dashkiosk
    

The database will be populated automatically when running Dashkiosk for the first time.

Configuration

Before running the server, there are some options you may want to tune. Those options can be specified either on the command-line or in a configuration file (that should be specified on the command-line).

Available options

Here are the three more important options:

configuration
This option allows to specify a configuration file in JSON format.
environment
This option sets the environment to use. By default, the development environment is used. Unless you want to debug Dashkiosk, this is not what you want. You can use any other keyword. Use production if you don’t know.
port
The port to listen to. Quite important.

The remaining options can usually be left untouched unless you decided to not use the integrated SQLite database.

path.static
Path where the static files to be served for the receiver and the integrated dashboards are located. Unless you moved them to some other location, there is no need to change this.
db.database
Database name. This is not needed if you kept the default SQLite database.
db.username
Username to access the database. This is not needed if you kept the default SQLite database.
db.password
Password to authenticate with the above username. This is not needed if you kept the default SQLite database.
db.options.dialect
Dialect to use for the database. This can be sqlite, mysql, mariadb or postgres.
db.options.storage
Location of the SQLite database. Not used for other databases.
db.options.hostname
Hostname (or IP) where the database is located. This is not needed for SQLite.
log.level
Log level to use for logging messages. Use either info or debug.
log.file
Location of a log file where to write logs in JSON format. By default, no such file is generated.

Command-line or configuration file

On the command-line, the options are specified using the classic GNU long option style by prepending them with --. For example:

--port 8087 --environment production

JSON configuration file

Alternatively, you can specify a JSON configuration file with --configuration. In this case, the options with a dot should be understood as being a sub-object. For example, to configure a PostgreSQL database:

{
    "environment": "production",
    "db": {
        "username": "dashkiosk",
        "password": "dashkiosk",
        "database": "dashkiosk",
        "options": {
            "host": "172.17.42.1",
            "dialect": "postgres"
        }
    },
    "log": {
        "file": "/var/log/dashkiosk.log"
    }
}

Reverse proxy

You may want to put a reverse proxy in front of Dashkiosk. You should know that it uses Socket.IO whose preferred backend is WebSocket. Some reverse proxy may not like it.

Here is a configuration for nginx:

upstream dashkiosk {
        server localhost:9450;
        server localhost:9451;
}

server {
   listen 80;
   listen [::]:80;
   server_name dashkiosk.example.com;

   location / {
     proxy_pass http://dashkiosk;
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "upgrade";
     proxy_set_header X-Forwarded-For $remote_addr;
   }
}

Setting X-Forwarded-For header allows Dashkiosk to display the IP address of each display in case you want to log on it to debug it.

Usage

Running the server

Once installed and configured, running Dashkiosk should be straightforward. While in the build directory:

$ node server.js --environment production

Don’t forget to specify the environment! See Configuration for available options. They can also be specified in a configuration file.

Testing

The server has three browser endpoints:

  • /unassigned which is the default dashboard for unassigned displays,
  • /admin which is the administration interface,
  • /receiver which is the receiver part that a display should load.

To test that everything is setup correctly, point your browser to /unassigned (for example http://localhost:9400/unassigned if you kept the default parameters and installed Dashkiosk on your PC).

You should see the default dashboard displayed for unknown device. These are just a few photos cycling around.

Then, you should go to the administration interface located in /admin. While in the administration interface, open another tab and go to /receiver which is the URL displaying the receiver. In the /admin tab, you should see yourself as a new display in the “Unassigned” group and in the /receiver tab, you should see the default dashboard that you got by going in /unassigned.

Troubleshooting

If something goes wrong, be sure to look at the log. Either you run the server through something like supervisord and you can have a look at the log in some file or you can use --log.file to get a log file.

Administration

The administration interface allows to create new dashboards, see active displays and associate them to a group of dashboards. When pointing a browser to the /admin URL, you should see an interface like this:

Administration interface

The administration interface with a few groups. At the top, the special “Unassigned” group.

On the figure above, you can see the three main entities in Dashkiosk:

  1. The monitors with a 5-digit serial numbers are the displays. For each of them, the serial number is attributed on their first connection and stored locally in the display [2]. They come with a green light when they are actually alive.
  2. Each display is affected to a group of displays. In the above figure, we have three groups. It is possible to move a display from one group to another. Each group can have a name and a description. It is possible to create or rename any group. The group named “Unassigned” is special and new displays will be attached to it on first connection. Other than that, this is a regular group.
  3. Each group of displays contains an ordered list of dashboards. A dashboard is just an URL to be displayed with a bunch of parameters. You can reorder the dashboards in a group and choose how much time they should be displayed.

The first time, you will only have the special “Unassigned” group [3].

Displays

Clicking on a display will show a dialog box with various information about the display.

Display details

The dialog box of the APFI0S display.

First, you get the IP address of the display. This could be useful if you need to connect to it for some other purpose (like debugging a problem related to this display). If the display is offline, the IP displayed is the last known IP.

Then, on the top right corner, there are contextual icons relevant to the current display. On a display, you can execute two actions:

  • force a reload of the receiver (after an update, for example),
  • toggle the OSD on the receiver.

The receiver OSD is a neat feature to check if the display you are inspecting is really the one you are interested in. It will display an overlay with the display name as well as some technical information that may be useful when displaying dashboards.

Not shown on the above figure, you can destroy a display by clicking on the Delete button in the lower left corner.

You can assign a description to the display, like “In the kitchen”. You can also change the group the display is currently attached to by choosing another group in the dropdown menu. The display should immediatly display the current dashboard of the group.

The viewport will be explained in a dedicated section. See Viewport.

On a desktop browser, it is also possible to move the display to another group by dragging it to the appropriate group.

Groups

By default, you only get the “Unassigned” group. But you can create any number of groups you need by clicking on the “Add a new group” button.

The name and the description of a group can be changed by clicking on them. If you change the name of the “Unassigned” group, a new “Unassigned” group will be created the next time a new display comes to live.

As for displays, you can execute contextual actions on a group. There are three of them:

  • for a reload of all the displays in the group,
  • toggle the OSD of all the displays in the group,
  • destroy the group.

The group can only be destroyed if no display is attached to it.

Each group has a list of dashboards. You can reorder them by using the up and down arrow icons on the right of each dashboard. You can add a new dashboard by using the “Add a new dashboard” button.

Dashboards

When creating a dashboard or modifying an existing one (by clicking on the little pen icon), you will get the following dialog box:

Dashboard details

The dialog box to modify some random dashboard.

Currently, a dashboard has:

  • an URL
  • an optional description
  • a timer to tell how much time the dashboard should be displayed
  • a viewport size (see Viewport).

The timer is optional but it doesn’t make sense to omit it if you have several dashboards in a group. Without it, once the dashboard is displayed, the next one will never be displayed unless you remove or modify the current one.

You can also modify the timer and the viewport by clicking on them directly in the list of dashboards in each group.

About the dashboards

The dashboards to be displayed can be any URL accessible by the displays. When a new dashboard has to be displayed for a group, the server will broadcast the URL of the dashboard to each member of the group. They will load the dashboard and display it. This may seem easy but there are several limitations to the system.

Network access

So, the first important thing about those dashboards is that they are fetched by the displays, not by the server. You must therefore ensure that the dashboards are accessible by the displays and not protected by a password or something like that.

Processing power

Some dashboards may be pretty dynamic and use special effects that look cool on the average PC. However, when using a US$ 30 low-end Android stick to display it, it may become a bit laggy. Also, please note that the Android application uses a modern webview but some functionalities may be missing, like WebGL.

Viewport

By default, a dashboard is displayed using the native resolution of the display. If the display is a 720p screen and your dashboard can only be rendered correctly on a 1080p screen, you have a problem. There are several solutions to this problem.

  1. Use a responsive dashboard that can adapt itself to any resolution.

  2. Change the viewport of the display. By clicking on the display, you can specify a viewport. When empty, it means that you use the viewport matching the native resolution of the screen. By specifying another resolution, the display will render the dashboards at the given resolution and zoom in or out to fit it into its native resolution.

    The support of this option depends on the ability of the browser running the receiver to exploit this information. Android devices are able to make use of it but other devices may not. If you don’t see any effect when changing the viewport, use the next option.

  3. Change the viewport of the dashboard. This is quite similar to the previous option but it is a per-dashboard option and it will work on any device. It works in the same way: the rendering will be done at the given resolution and then resized to fit in the screen. Both options can be used at the same time, there is no conflict.

IFrames

Technically, the receiver is a simple app rendering the requested URL inside an IFrame which is like a browser inside a browser. There are some limitations to an IFrame:

  • The receiver has almost no way to communicate with the IFrame [1]. It can know when an IFrame is ready but not if there is an error. The IFrame can therefore be displayed while it is not fully rendered and on the other hand, we cannot detect any error and try to reload the IFrame.
  • The IFrame can refuse to be display its content if there is a special X-Frame-Options in the headers forbidding the use of an IFrame.

The second limitation can be quite annoying. Here are some workarounds:

  1. Find an embeddable version of the content. Youtube, Google Maps and many other sites propose a version specifically designed to be embedded into an iframe.
  2. Use a web proxy that will strip out the offending header. A good base for such a proxy is Node Unblocker. It should be easy to modify it to remove the X-Frame-Options header.
  3. Use a screenshot service. Instead of displaying the real website, just display a screenshot. There are many solutions to implement such a service with headless browsers like Phantom.JS. For example this one.
[1]If the iframe is in the same domain, it can communicate with the iframe. However, most of the time, this is not the case. The receiver can also communicate with a cooperating iframe by sending messages. This is currently not implemented.
[2]The serial number is stored either in the local storage of the browser or in a cookie. If a display comes without this serial number or with an invalid one, it will be granted a new one.
[3]If you don’t have this group, this may be because no display has ever been registered. In this case, point your browser to the /receiver URL to register one.

API

There are three API available in Dashkiosk:

  • a REST API to manipulate groups, dashboards and displays,
  • the change API which is a Socket.IO based API which broadcasts changes to subscriber,
  • the display API which is a Socket.IO based API which tells displays which URL they should display.

There is also an internal bus API.

REST API

The REST API is available on the /api endpoint. Only JSON is currently supported. On error, the HTTP error code is important and the error message is also encapsulated into a JSON object:

{
    "error": {
        "httpCode": 404,
        "message": "No display named \"CNDS0KD\".",
        "name": "NotFoundError",
        "stack": [
            "NotFoundError: No display named \"CNDS0KD\".",
            "    at dashkiosk/lib/models/display.js:154:15",
            "    at process._tickDomainCallback (node.js:459:13)",
            "    at process._tickFromSpinner (node.js:390:15)",
            "From previous event:",
            "    at new Promise (dashkiosk/node_modules/sequelize/node_modules/bluebird/js/main/promise.js:88:37)",
            "    at module.exports.CustomEventEmitter.then (dashkiosk/node_modules/sequelize/lib/emitters/custom-event-emitter.js:144:12)",
            "    at Function.Display.get (dashkiosk/lib/models/display.js:152:6)",
            "    at dashkiosk/lib/api/rest/displays.js:21:20",
            "    at callbacks (dashkiosk/node_modules/express/lib/router/index.js:164:37)",
            "    at param (dashkiosk/node_modules/express/lib/router/index.js:138:11)"
        ]
    },
    "message": "No display named \"CNDS0KD\".",
    "token": "1397254337651-5YHK0SFJRC"
}

The error attribute is only present in development mode. It can also be found in the logs thanks to the token attribute.

Displays

GET /api/display

The list of all known displays.

Example request:

GET /api/display HTTP/1.1
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "3VZG6Y": {
      "connected": false,
      "description": null,
      "group": 1,
      "id": 2,
      "ip": null,
      "name": "3VZG6Y",
      "viewport": null
  },
  "51VRJ7": {
      "connected": false,
      "description": "Chromium",
      "group": 2,
      "id": 7,
      "ip": "127.0.0.1",
      "name": "51VRJ7",
      "viewport": null
  }
}
Status Codes:
  • 200 – no error
PUT /api/display/(name)

Modify the attributes of the display name.

Example request:

PUT /api/display/CNDS0K HTTP/1.1
Accept: application/json

{ "viewport": "1920x1080" }

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "connected": true,
  "description": "Nexus 5 (localhost:9400)",
  "group": 2,
  "id": 5,
  "ip": null,
  "name": "CNDS0K",
  "viewport": "1920x1080"
}
Parameters:
  • name – name of the display
JSON Parameters:
 
  • description – new description for the display
  • viewport – new viewport for the display
Status Codes:
  • 200 – no error
  • 404 – display not found
PUT /api/display/(name)/group/(int: id)

Attach the display name to the group id.

Example request:

PUT /api/display/CNDS0K/group/10 HTTP/1.1
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "connected": false,
  "description": "Nexus 5 (localhost:9400)",
  "group": 10,
  "id": 5,
  "ip": null,
  "name": "CNDS0K",
  "viewport": "1920x1080"
}
Parameters:
  • name – name of the display
  • id – ID of the group
Status Codes:
  • 200 – no error
  • 404 – display or group not found
POST /api/display/(name)/action

Request an action on a display. Only if connected.

Example request:

POST /api/display/CNDS0K/action HTTP/1.1
Accept: application/json

{ "action": "reload" }

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "connected": true,
  "description": "Nexus 5 (localhost:9400)",
  "group": 10,
  "id": 5,
  "ip": null,
  "name": "CNDS0K",
  "viewport": "1920x1080"
}
Parameters:
  • name – name of the display
JSON Parameters:
 
  • action – requested action, either reload or osd
  • text – for OSD only, text to display or null to remove the OSD
Status Codes:
  • 200 – no error
  • 400 – unknown action
  • 404 – display not found or offline
DELETE /api/display/(name)

Delete the display name. Only possible if the display is not connected anymore.

Example request:

DELETE /api/display/CNDS0K HTTP/1.1
Accept: application/json

Example response:

HTTP/1.1 204 OK
Content-Type: application/json
Parameters:
  • name – name of the display
Status Codes:
  • 204 – no error
  • 404 – display not found
  • 409 – display still connected

Groups

GET /api/group

The list of all known groups.

Example request:

GET /api/group HTTP/1.1
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "1": {
      "description": "Default group for unassigned displays",
      "id": 1,
      "name": "Unassigned"
  },
  "2": {
      "description": "Dashboards with Game of Thrones stuff",
      "id": 2,
      "name": "Game of Thrones"
  }
}
Status Codes:
  • 200 – no error
POST /api/group

Create a new group

Example request:

POST /api/group HTTP/1.1
Accept: application/json

{
  "name": "New group"
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 9,
  "name": "New group"
}
JSON Parameters:
 
  • name – name of the group
  • description – description of the group
Status Codes:
  • 200 – no error
  • 400 – a group should have a name
  • 409 – a group with the same name already exists
PUT /api/group/(int: id)

Modify a group attributes.

Example request:

PUT /api/group/15 HTTP/1.1
Accept: application/json

{
  "name": "Another name",
  "description": "Fancy"
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 9,
  "name": "Another name",
  "description": "Fancy"
}
JSON Parameters:
 
  • name – name of the group
  • description – description of the group
Status Codes:
  • 200 – no error
  • 409 – a group with the same name already exists
DELETE /api/group/(int: id)

Delete the group. Only possible if no display are attached.

Example request:

DELETE /api/group/15 HTTP/1.1
Accept: application/json

Example response:

HTTP/1.1 204 OK
Content-Type: application/json
Parameters:
  • id – ID of the group
Status Codes:
  • 204 – no error
  • 404 – group not found
  • 409 – group with displays

Dashboards

GET /api/group/(int: id)/dashboard

The list of all dashboards in a group

Example request:

GET /api/group/15/dashboard HTTP/1.1
Accept: application/json

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
      "active": false,
      "description": "House Stark",
      "group": 15,
      "id": 2,
      "timeout": 30,
      "url": "http://www.gameofthronescountdown.com/#stark",
      "viewport": null
  },
  {
      "active": true,
      "description": "House Tully",
      "group": 15,
      "id": 3,
      "timeout": 30,
      "url": "http://www.gameofthronescountdown.com/#tully",
      "viewport": null
  }
]
Parameters:
  • id – group ID
Status Codes:
  • 200 – no error
  • 404 – the group doesn’t exist
POST /api/group/(int: id)/dashboard

Create a new dashboard

Example request:

POST /api/group/15/dashboard HTTP/1.1
Accept: application/json

{
  "url": "http://www.example.com",
  "timeout": 30
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
      "active": false,
      "group": 15,
      "id": 6,
      "timeout": 30,
      "url": "http://www.example.com"
}
Parameters:
  • id – group ID
JSON Parameters:
 
  • url – URL of the dashboard
  • description – description of the dashboard
  • timeout – timer for this dashboard
  • viewport – viewport for this dashboard
Status Codes:
  • 200 – no error
  • 404 – group not found
  • 409 – the URL is mandatory
PUT /api/group/(int: id)/dashboard/(int: dashid)

Modify an existing dashboard. The special attribute rank can be used to modify the position of the dashboard in the group. The dashboards are numbered from 0 and the rank is the target position we want.

Example request:

POST /api/group/15/dashboard/6 HTTP/1.1
Accept: application/json

{
  "timeout": 40
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/json

{
      "active": false,
      "group": 15,
      "id": 6,
      "timeout": 40,
      "url": "http://www.example.com"
}
Parameters:
  • id – group ID
  • dashid – dashboard ID
JSON Parameters:
 
  • url – URL of the dashboard
  • description – description of the dashboard
  • timeout – timer for this dashboard
  • viewport – viewport for this dashboard
  • rank – New position for the dashboard
Status Codes:
  • 200 – no error
  • 404 – dashboard or group not found
DELETE /api/group/(int: id)/dashboard(int: dashid)

Delete the dashboard.

Example request:

DELETE /api/group/15/dashboard/6 HTTP/1.1
Accept: application/json

Example response:

HTTP/1.1 204 OK
Content-Type: application/json
Parameters:
  • id – ID of the group
  • dashid – ID of the dashboard
Status Codes:
  • 204 – no error
  • 404 – group or dashboard not found

Changes API

The socket.IO endpoint for this API is changes. Upon connection, a client will get all the current groups. Each group has a collection of displays in the displays attribute and an array of dashboards in the dashboards attribute. Here is an example:

{
  "1": {
      "description": "Default group for unassigned displays",
      "id": 1,
      "name": "Unassigned",
      "displays": {},
      "dashboards": []
  },
  "2": {
      "description": "Dashboards with Game of Thrones stuff",
      "id": 2,
      "name": "Game of Thrones"
      "displays": {
         "CNDS0K": {
            "connected": true,
            "description": "Nexus 5 (localhost:9400)",
            "group": 10,
            "id": 5,
            "ip": null,
            "name": "CNDS0K",
            "viewport": "1920x1080"
         }
       }
      "dashboards": [
            {
              "active": false,
              "description": "House Stark",
              "group": 2,
              "id": 2,
              "timeout": 30,
              "url": "http://www.gameofthronescountdown.com/#stark",
              "viewport": null
            },
            {
              "active": true,
              "description": "House Tully",
              "group": 2,
              "id": 3,
              "timeout": 30,
              "url": "http://www.gameofthronescountdown.com/#tully",
              "viewport": null
            }
      ]
  }
}

This message will be labeled snapshot.

On changes, only the group or the display affected by the change will be sent. The label of the message will be one of:

  • group.deleted
  • group.updated
  • group.created

And for displays:

  • display.deleted
  • display.updated (also for new displays)

If a change affects a dashboard, the whole group will be sent nonetheless.

Display API

This API is used by the display to know what they should do. The socket.IO endpoint to use for it is displays.

The server attributes to each new display a serial number. The display is expected to remember it and transmit it back on the next connection. It is encrypted by the server to avoid the display to steal another display identity.

Upon connection, a display is expected to send a register message with an object containing the blob attribute with the encrypted identity it previously received (if any).

If the server accepts the identity as is, it answers to this message with the same blob that should be stored by the client. If not, it will generate a new blob and sends it back to the client. In both cases, the client just has to store the received blob.

After this handshake, the display can receive the following messages:

dashboard
The dashboard that should be displayed right now. It is an object containing the same attributes as we would have got when requesting this particular dashboard with the REST API. See Dashboards.
reload
The display should reload itself.
osd
The OSD should be shown or hidden. If the message comes with a text, the OSD is displayed with the provided text. Otherwise, it is hidden.
osd
Modify the current viewport of the display with the provided value.

Internal bus message

To avoid strong coupling between components, Dashkiosk uses postal.js as an internal bus message. The messages that are emitted are listed below:

  • display.NAME.connected when a new display is connected
  • display.NAME.disconnected when a new display is disconnected
  • display.NAME.group when a display should change to a new group
  • display.NAME.deleted when a display is deleted
  • display.NAME.updated when another change happens on a display
  • display.NAME.dashboard when a new dashboard should be displayed by the given display.
  • display.NAME.reload when a display should reload itself
  • display.NAME.osd when we need to display something on the OSD
  • display.NAME.viewport when the display viewport should be updated
  • group.ID.created when a new group is created
  • group.ID.updated when a group is updated (but not something dashboard related)
  • group.ID.deleted when a group is deleted
  • group.ID.dashboard when a whole group should switch to a new dashboard
  • group.ID.dashboard.ID.added when a new dashboard has been added
  • group.ID.dashboard.ID.removed when a dashboard has been removed
  • group.ID.dashboard.ID.updated when a dashboard has been updated

Each message comes with the group, the dashboard and/or the display specified in the message (when this is relevant).

Android application

This is a simple Android application whose purpose is to display fullscreen non-interactive dashboards on Android devices. Its main use is to be run from an Android stick plug on some TV to run the web application to display dashboards.

Supported devices

Currently, the minimal version of Android is 4.2 (Jelly Bean). However, it works best with Android 4.4 (Kit Kat) or later since the webview component shipped in those versions come from the Chromium project and are pretty up-to-date. In the future, an external webview may be used[#]_.

[1]For example, the one from the Crosswalk project is a good candidate. It is currently not embeddable but it is planned. You could look at XWALK-957 for progress on this.

There are a lot of Android devices that you can choose to run Dashkiosk on. When choosing one, prefer the ones which can be upgraded to Android 4.4.

Features

  • It registers as a possible home screen. It is therefore to run the application on boot.
  • It provides a really fullscreen webview. Absolutely no space lost in bars.
  • No possible interactions. If run on a tablet, the user is mostly locked out. However, there are still some way to interact with the device while the application is running by invoking the settings and changing the home application from here.
  • Prevent the device going to sleep.

Compilation

You need to download the Android SDK. Once installed, you should manage to get the android command in your path. Execute the remaining steps:

  1. Grab the latest tarball for Dashkiosk from GitHub.

  2. Unpack it and go into the android directory.

  3. Execute the following commands to get an APK to be installed on an Android device:

    android update project -p .
    ant debug
    

At the end of the compilation, you get bin/DashKiosk-debug.apk that should be installed on the Android device.

Installation

Ensure you have adb available in your path. If not, it is available in the platform-tools directory. You can then install the APK on a device attached through USB on your computer with the following command:

adb install -r bin/DashKiosk-debug.apk

The next step is to run the configuration panel by clicking on the pen icon in the action bar.

Configuration

The orientation is configured to landscape by default. You can choose either auto or portrait.

The important part is to input the receiver URL. You can check that this is the correct URL with any browser. You should see a dashboard with some nice images cycling.

The timeout is not really important. Until the application is able to make contact with the receiver, it will try to reload the receiver if the timeout is reached.

Alternatively, the configuration can be done at compile-time by modifying res/xml/preferences.xml.

Usage

Once configured, just run the application as usual. You can also click on the home button and choose the application from here to make it starts on boot.

Troubleshooting

Still with adb, you can see the log generated by the application with the following command:

adb logcat -s DashKiosk AndroidRuntime

The log also includes Javascript errors that can be generated by the dashboards. Javascript errors from the receiver are prefixed with [Dashkiosk].

License

Dashkiosk is distributed under the ISC license. It basically means: do whatever you want with it as long as the copyright sticks around, the conditions are not modified and the disclaimer is present.

ISC License

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Indices and tables