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).