Exhibitera
  • Home
  • Download
  • Tutorials
  • Troubleshooting
  • API
  • Contact

Developing with Exhibitera

While Exhibitera Apps enables many kinds of interactives, you can also develop your own apps that integrate with Hub.

API
  • Browser-based apps
    • Overview

    • Definitions
    • Updates
    • Local data
  • Non-browser apps
    • Overview

    • Ping
    • Ping response

Building a browser-based app

The apps in Exhibitera Apps are built using JavaScript. This approach ensures maximum flexibility, while also offloading many performance and security concerns to the rendering engine. It also makes developing your own app surprisingly easy!

Exhibitera Apps provides a JavaScript module, exhibitera_app_common.js, that enables easy connection with Exhibitera. In just a few lines of code, you can have an app up and running! Here is the complete code to create a blank Exhibitera app (the JavaScript file, at least):

import * as exCommon from 'exhibitera_app_common.js'

function loadDefinition (definition) {
  // A function to configure your app's content
  // based on the provided configuration.
  ... 
}

function parseUpdate (update) {
  // A function to respond to commands from
  // Exhibitera Hub.
  ...
}

exCommon.configureApp({
  name: 'other',
  loadDefinition: loadDefinition,
  parseUpdate: parseUpdate
})

Note that exhibitera_app_common.js is a JavaScript module, so your file must also be a module.

Definitions

Definitions are user-provided configuraitons for your app. Users can use the Other App setup page in Exhibitera Apps to pass parameters to your app. Based on those parameters, you can configure the app as needed. These parameters are given in the parameters field of the defintion:

{
  ...
  parameters: {
    'parameter 1': 'value 1',
    'parameter 2': 'value 2'
  },
  ...
}

You can ignore the other fields in the definition, as they are for interal Exhibitera use.

Updates

If your user is using Hub, your app will check in with the server every five seconds. This updates the Hub web console and retrieves any updates from the server.

Interaction status

Your app can communicate whether it is in active use by setting the value of exCommon.config.currentInteraction. Set the value to true when interaction begins and false when it ends. One common way of defining "ends" is when the attractor is shown again. Properly setting this variable helps your user understand how the app is being used and enables them to collect analytics.

Responding to commands

Hub may send a command in response to a user action, an event in the schedule, or another app. Built-in commands, such as refreshing, restarting, and shutting down, are handled automatically by Exhibitera.

Using the parseUpdate() function, your app can respond to custom commands.

Reading and writing local data

You can read and write local data by using exCommon.makeHelperRequest(). For example, here is the code used to save votes from Voting Kiosk:

exCommon.makeHelperRequest(
  {
    method: 'POST',
    endpoint: '/data/write',
    params: {
      name: 'votingData',
      data: {
        option1: 5,
        option2: 8
      }
    }
  })

makeHelperRequest() returns a Promise that resolves with two fields, the boolean success and the string reason. If the write fails, reason will provide helpful details.

/data/write POST

Write a JavaScript object to disk. Each request will write one line of JSON to the file. The user can download the file as a CSV spreadsheet from the Exhibitera Apps configuration page.

{
  data: {
    key1: 'value1',
    'key 2': ['value 2', 'value 3']
  },
  name: 'myDataFile'
}

data Object

A JSON-serializable object.

name String

A string filename without an extension. The extension '.txt' will be appended.

/data/writeRawText POST

Write the given text to file for later retrieval. If you wish to write JSON, you must call JSON.stringify() yourself first.

{
  text: 'A string of text',
  mode: 'a',
  name: 'myDataFile'
}
text String

The text to be written to file.

mode String

Pass 'a' (default) to append to the file or 'w' to overwrite the file.

name String

A string filename without an extension. The extension '.txt' will be appended.

/data/getRawText POST

Retrieve a previously-written data file.

{
  name: 'myDataFile'
}
name String

A string filename without an extension. The extension '.txt' will be appended.

Building a non-broswer app

When building an app using Python, Java, .NET, etc., you must communicate with Hub manually.

Ping

Exhibitera uses a client-server model. To connect your app to Exhibitera Hub, you should send a JSON object to the server every five seconds. Exhibitera calls this a ping. The ping object should have the following format and be sent as a POST request to the endpoint /system/ping:

{
  currentInteraction: true,
  helperAddress: '192.168.1.27:8000',
  permissions: {
    audio: true,
    refresh: true,
    restart: true,
    shutdown: false,
    sleep: false
  },
  uuid: '9e325f88-2f21-4a64-b9ef-f39d549f140f'
}

currentInteraction Boolean

Boolean value that should be true if the user is currently interacting with the app or false if they are not (or this is not an interactive app).

helperAddress String

The helperAddress is the IP address and port of a webserver run by your application that can receive commands.

permissions Object

A dictionary defining how Hub may command the app.

audio Boolean

A boolean value giving whether Hub can mute/unmute the app.

refresh Boolean

A boolean value giving whether Hub can ask the app to refresh its state. The result should be equivilent to pressing refresh in a browser.

restart Boolean

A boolean value giving whether Hub may ask the app to restart the underlying computer.

shutdown Boolean

A boolean value giving whether Hub may ask the app to shut down the underlying computer.

sleep Boolean

A boolean value giving whether Hub may ask the app to put the display to sleep.

uuid String

String value representing a totally-unique identifier. Each installation of your app should use a different uuid, but the uuid must be consistent between app sessions. Exhibitera Hub interprets each uuid as an entirely different physical installation.

Ping response

When Hub receives a ping, it will respond with a JSON object. That object will have the following structure:

{
  app_id: 'other',
  app_name: '',
  commands: [],
  current_exhibit: 'An Exhibit',
  definition: '08a1ad7a-c40d-40c7-8b06-c0bd878a9921',
  description: 'Some user-provided text describing this interactive.',
  error: '{}',
  maintenance_status: 'On floor, working',
  permissions: {
    audio: true,
    refresh: true,
    restart: true,
    shutdown: false,
    sleep: false
  }
}

Most of these fields are for internal Exhibitera use. However, your app should respond to the follwoing fields:

commands Array

An array of string values representing commands from Hub.

'refresh_page'

Your app should respond by rebuilding its content or reloading its state to an initial default. This should behave similarly to how pressing reload on a webpage does.

'restart'

Your app should initiate a reboot of the underlying PC.

'shutdown' or 'power_off'

Your app should initiate a shut down of the underlying PC.

'sleepDisplay'

Your app should attempt to place the computer's display to sleep.

'wakeDisplay' or 'power_on'

Your app should wake the computer's display.

permissions Object

This dictionary represents the user's desired permissions. If reasonable, you should update your internal permissions to align with these.

audio Boolean

If audio is true, your app should allow audio (unmute); if false, it should mute the audio.