Tutorial: Digital Signage and Game

In this tutorial you’ll integrate Gumband into an existing Electron app. This Electron app has two modes: a digital signage and a simple video game:

The Digital Signage screen of the SDK Tutorial

 

The Button Clicker game screen of the SDK Tutorial.

 

At the beginning of the tutorial, the app will only be able to serve preset static content for the digital signage screen, but by the end it will be able to:

  • Dynamically set all text copy for the digital signage

  • Dynamically change the image shown for the digital signage

  • Toggle the screen between rendering the digital signage and the Button Clicker game

  • Set some configurations for the Button Clicker game

  • Capture usage data for the Button Clicker game

Table of Contents

Setup

Clone the tutorial repo. Navigate into the gumband-sdk-tutorial directory and run npm install to install dependencies for the project. Run npm run start to start the electron app and serve the static digital signage content. You should see the following:

Installing and Initializing the Gumband SDK

Install the Gumband SDK as a new dependency: npm i @deeplocal/gumband-node-sdk.

Create a new exhibit in the Gumband UI and copy the exhibit ID and Authentication Token into a new .env file. You will use these two values to authenticate your exhibit with the Gumband Cloud.

// .env EXHIBIT_TOKEN=abc1...23 EXHIBIT_ID=1

Create a new manifest file at ./gumband/manifest.js, and add an empty manifest object inside:

// gumband/manifest.js const manifest = { manifest: {} } module.exports = { manifest };

Later, this manifest will tell Gumband what configurations your exhibit has, but right now it’s empty.

Now we need to initialize the Gumband SDK class, and pass it our exhibit id, token, and manifest so it can connect to Gumband. Create a new directory and file named ./gumband/gumband-service.js, and initialize a Gumband SDK inside that new file:

// gumband/gumband-service.js const { Gumband } = require("@deeplocal/gumband-node-sdk"); const { manifest } = require("./manifest"); /** * A class that wraps the Gumband SDK and handles websocket messages * that come from the Gumband Cloud. */ class GumbandService { /** * A reference to the Gumband SDK instance. */ gumbandSDK; constructor() { this.gumbandSDK = new Gumband( process.env.EXHIBIT_TOKEN, process.env.EXHIBIT_ID, manifest, ); } } module.exports = { GumbandService };

Initialize the GumbandService class in the electron app:

Now, when you run the electron app again (npm run start), your exhibit instance in the Gumband UI should come online:

Make the Digital Signage Copy Text Configurable

To start, let’s make the Digital Signage copy configurable through Gumband. We’ll need to add settings to the manifest that will represent the different copy text we’d like to be able to configure. Let’s put the header, subheader, and body settings in a SettingsGroup to differentiate them from the Game Mode settings that we’ll be adding later (SettingsGroups simply change how the settings are organized in the Gumband UI):

If you restart the app again, this new manifest will be submitted to Gumband you’ll see them settings in the Gumband UI:

When these settings are changed in the UI, our app will receive a Sockets.SETTING_RECEIVED websocket event. Let’s listen for that event and create a function to update the Electron app with text changes:

If you noticed, we also needed to pass a new window object into the constructor, so the GumbandService can communicate with the Electron app. Let’s pass that window object into the GumbandService instantiation:

Now we listen for content events coming from the GumbandService to the Electron App:

Also, delete the addStaticCopy function in the ./electron-app/main.js file, and all calls to it, since we don’t need to set static copy anymore.

Now, when you re-run the app, it should show a blank screen. This is because it is pulling the text from the Gumband settings, and those settings are blank. If you fill them in and click “Save”, you will see the Electron app populate in real time.

Add Setting for Updating the Signage Image

Now let’s get the image for digital signage back and configurable. First, let’s upload a few images to Gumband. In the Gumband UI, navigate to the Files tab for your exhibit instance and upload the three images in the seed-images directory:

We’ll also want to tell the Gumband SDK to download any images that were uploaded here and to save them in a place accessible to the Electron app. To do this, we’ll just need to add some configuration to our Gumband SDK initialization:

If you restart the app, you’ll notice a new directory at ./electron-app/content will all of the images. We also want these files to update whenever new files are uploaded to the Gumband UI. Let’s implement that by listening for the Sockets.FILE_UPLOADED event, which is fired whenever a new file is uploaded to your exhibit instance in Gumband:

Next, similar to how we added the signage copy settings, we’ll need to: update the manifest with the new setting, listen for the setting change from the Gumband Cloud (we’re already doing this), and communicate the new image name to the Electron app.

After restarting the app, you can now select any of the images you uploaded with your new setting in the Exhibit Settings tab of the Gumband UI. The selected image will show in the Electron app.

Toggle Between the Digital Signage and the Game

All the logic to build out the Button Clicker game in the frontend is already defined in the ./electron-app/main.js file, so all we need to do is call those functions based on a setting in Gumband. Let’s make this a Toggle setting called “Game Mode”; when it is true (toggled on) we’ll show the Button Clicker game, and when it is false we’ll show the Digital Signage. Once again, the changes required are in the manifest.js, the gumband-service.js, and the main.js. For the manifest, we’ll put the new setting outside the digital signage group of settings, since it is applicable to both the Digital Signage settings and the Button Clicker settings (to be added in a later step):

Now when you toggle the new “Game Mode” setting on, you will see the app change to the Button Clicker game.

Configuring Button Clicker

Each Button Clicker game is 5 seconds long by default, and the length of time that the game summary screen shows is also 5 seconds (set by gameDuration and gameSummaryScreenDuration variables in the main.js file). But what if we want to configure these times without changing the source code? Let’s implement that:

Measuring Interaction Time

When measuring the engagement of your exhibit we use have two basic concepts to understand: “events” and “interactions”.

Events are singular moments in time when something happens on the exhibit, typically due to a user action like a button push. An interaction is simply a collection of events that occurred within a specific window of time.

Getting started with Gumband interaction metrics is as simple as using the metrics module to create events.

Lets emit a new type of event from the electron app anytime a target is hit by adding a single line to createNewTarget.js.

Next we handle this new data type event within the gumband-service.js by calling the metrics.create(...) method

Once you begin emitting events in this manner the Gumband backend internally begins an interaction and will continue to group any incoming events into that particular interaction. If no events have been emitted within 60 seconds then the interaction will timeout and be considered ended.

For our game scenario, if we play a singular game (and hit at least 1 target) we can expect that interaction to last about 1 minute. However if we play several games one after another (hitting at least 1 target each time to trigger the metrics.create call) then we can expect that interaction to last longer than 1 minute because events continued to come in, preventing the Gumband backend from reaching it’s timeout period.

If you want to calibrate the timeout duration you can check out: How To Configure the Interaction Timeout

Make Exhibit Management Easier With Controls

Controls are custom, one-time events that can be triggered through the Gumband UI, which must be configured through the manifest. Let’s add two controls: one for reloading the frontend in case it somehow gets into a weird state, and one for toggling the Game Mode just to make that a faster process.

First, we need to configure the controls by adding them to the manifest:

When controls are triggered, the Gumband SDK will receive it as a Sockets.CONTROL_RECEIVED websocket event, so let’s listen for that:

You should now be able to toggle the Game Mode with a single button click, and you can reload the frontend if needed. Test out the new controls in the Controls tab of the Gumband UI.

Add Health Statuses

Statuses are often used as a way to display the health state of your exhibit, but they can be used to show any value that can be represented as a string and that you’d like to have easily viewable. All statuses are displayed on the Status tab of the Gumband UI to provide a quick glance at the state of your exhibit at any given time.

We’re going to add one status that shows what screen is currently being displayed: the digital signage, or the game. Statuses are configured through the manifest, so we’ll start there:

Now we need to use the setStatus SDK function to update the “screen-status” any time the frontend can change modes.

If you restart the app, you will see your statuses update in real time.

Add Logging

There are 4 log levels you can log to in Gumband: info, debug, warning, and error. You can filter by these logs in the Gumband UI. For our app, let’s just add some info logs so we’ll have a record of when settings were changed or when controls were triggered.

Logging messages to Gumband is as easy as that. You can view the logs in the Logs tab in the Gumband UI:

System Diagram

Here is a system diagram of what we’ve implemented so far:

It shows the communication protocols used and the areas in which we’ve been implementing code.

Bonus

That concludes the main part of this tutorial. If you’re interested in implementing a few additional features (including a simple Gumband Hardware integration) press onward.

Upload Seed Images on Startup

It would be nice if we didn’t need to upload the seed images manually before we started our app the first time. What if this was just the development version, but for production there were 20 images to choose from? Let’s add a function that automatically uploads the seed images to Gumband with the uploadFile SDK function.

To test that this is working correctly, delete the electron-app/content directory. If you recall from the Add Setting for Updating the Signage Image section, this is the directory that we configured the Gumband SDK to place all of the files uploaded to the Gumband UI. You’ll also need to delete the images in the Gumband UI, so the Files tab shows no files:

Now, when you next run the app, the gumband-service.js should upload all of the files in the seed-images directory to the Gumband Cloud and the electron-app/content directory should get recreated with those files.

Custom Email Notifications

Let’s say our exhibit has a screen that should be serviced every few months, and we want to have an email notification sent out whenever it needs attention. We can accomplish this with custom email notifications:

Going forward, any user subscribed to the “Custom Exhibit” email notification in the Gumband UI will receive a maintenance reminder every 6 months.

Hardware Integration

For this step, you’ll need a Gumband Hardware. We’ll be implementing two integrations with the Gumband Hardware:

  1. When one of the built-in buttons on the Gumband Hardware is pressed, the Game Mode setting will be toggled through the Gumband SDK.

  2. When a user is playing the “Button Clicker” game, and they click on a button target, the LED on the Gumband Hardware will pulse on/off.

Connecting Your Hardware to the SDK

If you haven’t already, follow the Hardware Getting Started Guide to set up the Gumband Hardware and your development environment.

In the Arduino IDE, open the RemoteLEDandButton firmware example by navigating to File → Examples → Gumband SDK Examples → RemoteLEDandButton, and flash it onto your Gumband Hardware. This firmware causes an event to be sent whenever the built-in button on the Gumband Hardware (next to the Ethernet port) is pressed.

Before we go any further, take a look at this updated system diagram. Note that this diagram also includes the “Pulse LED” event that is part of a later step:

Notice that the Gumband Hardware is communicating with our Gumband Service through an MQTT broker that the SDK owns (it is also an option to use your own third party MQTT broker). So to establish this communication we need to:

  1. Enable the built-in SDK MQTT broker and configure it with a port.

  2. Tell the hardware what the MQTT broker IP and Port are.

Starting the built-in MQTT broker is as simple as adding one configuration to our Gumband SDK initialization.

Now when you start the app, the Gumband SDK will start up the MQTT message broker at the default port, 1883. See the API Reference documentation for more information on configuring the MQTT broker.

Next, run ifconfig in a terminal to find your local IP address and configure the Gumband Hardware with this address and the MQTT port. You can do this with the Arduino IDE Serial Monitor with the write app address and write app port commands:

Let’s test that we have it all set up correctly and that the Gumband Hardware can connect to our exhibit MQTT broker (the GBTT service). Connect the Gumband Hardware to power and to the same local network as your exhibit. If the LED on the hardware pulses green, that means it successfully authenticated with the Gumband Cloud, received the IP and port of your MQTT broker, and connected to it. For more details on the Gumband Hardware authentication and registration flow, check out the Gumband MQTT Reference Guide.

Receiving a Hardware Event

Now, let’s make the Game Mode setting toggle whenever the built-in button on the Gumband Hardware is pressed. All we need to do is listen for the Sockets.HARDWARE_PROPERTY_RECEIVED event and then toggle the Game Mode setting:

Test it out by clicking the button next to the ethernet port on the Gumband Hardware. It should toggle the Game Mode setting.

Writing a Property Value to the Hardware

Let’s simulate a user interaction that causes a physical change in our exhibit by making the built-in LED on the Gumband Hardware blink when the user clicks a button target in the Button Clicker game. To do this, we’ll need to:

  1. Listen for the Sockets.HARDWARE_FULLY_REGISTERED event in the gumband-service.js so that we can get the ID of the hardware. We will need this for the next step.

  2. Listen for the Electron “target-hit” event in the gumband-service.js and dispatch MQTT messages that will toggle the hardware LED on and off.

One thing to keep in mind is that the property path hardcoded in lines 31 and 34 above (“LED/Toggle”) will change based on the firmware you’ve flashed onto the Gumband Hardware. You can see all of the properties and peripherals on the hardware by logging out the payload of the Sockets.HARDWARE_FULLY_REGISTERED event.

Test this out by playing the Button Clicker game. An LED on the Gumband Hardware should flash every time you click on one of the button targets.

 

Congratulations on making it the whole way through this Tutorial! Now that you have a general understanding of Gumband, check out the Quick Start guide for any reminders about the syntax usage of the SDK, and see the API Reference doc to look through the entire SDK API.