@deeplocal/gumband-node-sdk
v2.0.15
Published
The Gumband SDK; made with ❤️ at Deeplocal
Downloads
427
Readme
Gumband Node.js SDK
The Gumband SDK takes care of all communication between an Exhibit and Gumband servers in the Cloud. It handles authentication, establishes a websocket connection for live updates, and also optionally spawns an MQTT broker to handle communcation with Gumband-compatible hardware.
Check out our public documentation here.
How to Prepare your exhibit to use the Gumband SDK
Step 0: Install the SDK
Install the Gumband SDK to your Node.js project using the npm registry with the command $ npm install @deeplocal/gumband-node-sdk
.
Step 1: Create an exhibit
Log into the Gumband dashboard in a web browser and then select an organization and site. Create a new exhibit or select an existing exhibit. Select the "Auth" tab for that exhibit and note the ID and token, you'll need this when initializing the Gumband SDK. Some users may not have permission to create exhibits in the Gumband dashboard.
Step 2: Create a manifest
The exhibit manifest is a way to describe the real time signals (statuses, settings, and controls) available for an exhibit. The manifest is a local JSON file that is included in the Gumband SDK constructor. It has a main key manifest
that contains three required keys - statuses
, controls
, and settings
- that each contain the necessary Gumband schema.
Here is an example of a manifest file:
{
"manifest": {
"statuses": [
{
"id": "ip_address",
"type": "String",
"display": "IP Address",
"default": "127.0.0.1", // Optional
"order": 0 // Optional
},
{
"id": "count",
"type": "Integer",
"display": "Count",
"default": 0, // Optional
"order": 1 // Optional
},
{
"id": "last_interaction",
"type": "Date",
"display": "Last Interaction",
"order": 2 // Optional
},
{
"id": "primary_color",
"type": "Color",
"display": "Color",
"default": "#abc123" // Optional
}
],
"controls": [
{
"id": "reload",
"type": "Single",
"display": "Reload",
"order": 0 // Optional
},
{
"id": "skip",
"type": "Single",
"display": "Skip Interaction",
"enabledOpMode": "On" // Optional
},
{
"id": "restart_cameras",
"type": "Group",
"display": "Restart Cameras",
"items": [
{
"id": "camera_1",
"display": "Camera 1"
},
{
"id": "camera_2",
"display": "Camera 2"
}
]
}
],
"settings": [
{
"id": "kiosk_name",
"type": "TextInput",
"display": "Kiosk Name",
"default": "(not set)" // Optional
},
{
"id": "idle_timeout_secs",
"type": "IntegerInput",
"display": "Idle Timeout (secs)",
"default": 60 // Optional
},
{
"id": "prod_api",
"type": "Toggle",
"display": "Production API",
"default": false // Optional
},
{
"id": "audio_file",
"type": "Dropdown",
"display": "Audio File",
"default": "a_type_1", // Optional
"items": [
{
"id": "a_type_1",
"display": "Audio 1"
},
{
"id": "a_type_2",
"display": "Audio 2"
},
{
"id": "a_type_3",
"display": "Audio 3"
}
]
},
{
"id": "ux_mode",
"type": "SingleButtonGroup",
"display": "UX Mode",
"default": "ux_mode_ambient", // Optional
"items": [
{
"id": "ux_mode_silent",
"display": "Silent"
},
{
"id": "ux_mode_ambient",
"display": "Ambient"
},
{
"id": "ux_mode_offline",
"display": "Offline"
}
]
},
{
"id": "date",
"type": "Date",
"display": "Date"
},
{
"id": "named_images",
"type": "SettingsList",
"display": "Named Images",
"schema": [
{
"type": "TextInput",
"id": "image_group_title",
"display": "Image Group Title"
},
{
"type": "SettingsList",
"id": "images_list",
"display": "Images",
"schema": [
{
"type": "FileSelection",
"id": "image_file",
"display": "Image"
}
]
}
]
},
{
"id": "operator_info",
"type": "SettingsGroup",
"display": "Operator Info",
"schema": [
{
"type": "TextInput",
"id": "operator_name",
"display": "Operator Name",
"order": 0
},
{
"type": "TextInput",
"id": "operator_location",
"display": "Operator Location",
"order": 1
}
]
}
]
}
}
Real Time Signal Types
Statuses: Integer
, String
, Date
, Color
Controls: Single
, Group
Settings: TextInput
, IntegerInput
, Toggle
, Dropdown
, SingleButtonGroup
, FileSelection
, Date
, SettingsList
, SettingsGroup
Step 3: Configuring the Gumband SDK via the constructor
After the previous steps, you can start using Gumband in your Node.js application. The Gumband constructor requires the exhibit ID, exhibit Token, and the path to the manifest file that you previously created.
Upon creation, the Gumband class will attempt to authenicate itself with the Gumband API and establish a Websocket connection to listen to Real-Time signals relevant to the exhibit. Here's an example:
const { Gumband, Sockets } = require("@deeplocal/gumband-node-sdk");
const gb = new Gumband(
"a986dc223cc137xxxxxxxxxxxxxxx", // exhibit token
"6", // exhibit ID
"/path/to/manifest.json" // manifest path
);
// Register callback for when Gumband is ready to be used
// No Gumband SDK functions should be called before this event fires
gb.on(Sockets.READY, async () => {
console.log("Gumband Exhibit Initialization Successful!");
});
Optional Constructor Parameters
You can initialize the Gumband SDK with a few parameters:
version
(string): What API version to use. Value should bev1
.endpoint
(string): What Gumband environment to operate with. Value can belocal
,dev
,stag
,app
, orcustom
.customServerIp
(string): Ifendpoint=custom
, what DNS name or IP address is the Gumband environment at. Value should be similar totest.gumband.com
or192.168.1.1
.contentLocation
(string || null): Assets uploaded to Gumband will be synced to the specified folder. Active user must have write permission for this directory. It is advised use an absolute instead of relative path. This value can be set tonull
to explicitly not sync any files.skipOrganizationFileSync
(boolean): Set tofalse
to sync organization level files. Defaults totrue
.
// optional contructor parameters example
const gb = new Gumband(
"a986dc223cc137xxxxxxxxxxxxxxx", // exhibit token
"6", // exhibit ID
"/path/to/manifest.json", // manifest path
{
endpoint: "custom", // local, dev, stag, app, or custom (set to 'app' by default)
customServerIP: "test.gumband.com", // or an IP address such as '192.168.1.1' (ignored unless endpoint=custom)
version: "v1", // api version
contentLocation: "/path/to/content", // a directory to sync files in or null to not sync content
skipOrganizationFileSync: false, // whether or not to skip the org level file syncing
}
);
Using the SDK
The Gumband
class provides you with methods to make requests to our API and Surfaces Websocket and Hardware events as an EventEmitter
. Combining our example manifest.json
and our example exhibit code above, here is an example of how to interact with Gumband with a properly configured instance of the Gumband
class.
The js example below and manifest.json example above have been included in the npm package as files example.js
and manifest.json
as a place to start.
For a more in depth example of interacting with these methods, events, and a walkthrough of building something out from scratch, check out our Quick Start Guide.
const { Gumband, Sockets } = require("@deeplocal/gumband-node-sdk");
const gb = new Gumband(
"a986dc223cc137xxxxxxxxxxxxxxx", // exhibit token
"6", // exhibit ID
"/path/to/manifest.json" // manifest path
{
localLogging: {
level: "info" // Must be one npm log levels supported by winston: https://github.com/winstonjs/winston?tab=readme-ov-file#logging-levels
}
}
);
// Register callback for when Gumband is ready to be used
// No Gumband SDK functions should be called before this event fires
gb.on(Sockets.READY, async () => {
// Get and set statuses
await gb.setStatus("ip_address", "0.0.0.0");
const status = await gb.getStatus("ip_address");
console.log(status);
// Get and set settings
await gb.setSetting("kiosk_name", "a new value");
const setting = await gb.getSetting("kiosk_name");
console.log(setting);
// Get and set operating mode
await gb.setOperatingMode(true);
const opMode = await gb.getOperatingMode();
console.log(opMode);
// Send logs
await gb.logger.info("Log info text.");
await gb.logger.debug("Log debug text.");
await gb.logger.warn("Log warn text.");
await gb.logger.error("Log error text.");
// Report an analytics event (second param can be key-value pairs)
await gb.event.create("HardwareFailure", {
data: "The hardware has failed",
value: 1,
});
// Send an event to hardware
await gb.hardware.set("17/switch1/switch", 1);
});
// You can listen for events and importantly register multiple listeners!
// It is OK to do this prior to the Sockets.READY event
// Do something when the exhibit is turned on or off in the dashboard
gb.on(Sockets.OP_MODE_RECEIVED, (payload) => {
console.log(payload);
});
// Do something when a setting is updated
gb.on(Sockets.SETTING_RECEIVED, (payload) => {
console.log(payload);
});
// Do something when a control is triggered
gb.on(Sockets.CONTROL_RECEIVED, (payload) => {
console.log(payload);
});
// Sync files when a file is uploaded
// Assumes a contentLocation directory is specified in the constructor
gb.on(Sockets.FILE_UPLOADED, async (data) => {
console.log(`User uploaded ${data.fileName} to exhibit`);
await gb.content.sync();
console.log("Downloaded new files!");
});
// Notify when a file is deleted
// Assumes a contentLocation directory is specified in the constructor
gb.on(Sockets.FILE_DELETED, (data) => {
console.log(`User deleted ${data.fileName} from exhibit`);
// The SDK does not automatically delete files so potentially delete the file here
});
// Do something when receiving data from hardware
// Assumes a Gumband Hardware is connected to this exhibit.
gb.on(Sockets.HARDWARE_PROPERTY_RECEIVED, (payload) => {
console.log(payload);
});
Optional Environment Variables
You can set a few environment variables to control functionality of the Gumband SDK:
GB_LOCAL_LOG_LEVEL
(string): what level of logs to be displayed, options {debug
,info
,warn
,error
}, defaults towarn
GB_MUTE_HEARTBEAT
(boolean): whether or not to mute the heartbeat logs, defaults tofalse
Settings Groups Usage
As shown in the above example, you can define a setting of type SettingsGroup
. This is different from other settings, in that it allows you to define a schema for a group unit of settings. Settings created within a group follow the naming schema settingsGroupId/settingID
. You are also able to nest settings groups within other settings groups, and the nested groups also follow the above naming schema (ie. settingsGroupId/nestedGroupId/settingID
). When the settings within a group are updated, they follow the same communication pipelines as normal settings.
Setting Lists Usage
As shown in the above example, you can define a setting of type SettingsList
. This is different from other settings, in that it allows you to define a schema for a group unit of settings. Once you define this group unit of settings, you can add (and remove) an arbitrary number of these setting units through the gumband web interface. Settings created within a group follow the naming schema settingsListId/groupName/settingID
. You are also able to nest settings lists within other settings lists, and the nested groups also follow the above naming schema (ie. settingsListId/groupName/nestedListId/nestedGroupName/settingID
). When the settings nested within a group are updated, they follow the same communication pipelines as normal settings.
A note for parsing Settings Lists:
When fetching settings lists and their values, via the
getAllSettingLists
call, your return will be formatted with all top level settings groups in an array (ie. [ImageGroups, Employees, ...]) where each item is a group Object. This object contains information about the group, and contains all the groups sub-settings under thesettinglistitems
field. If the settings list contains a nested settings list, that nested list will appear in thesettinglistitems
field as well.
Locally stored values
Another feature of the Gumband class is that it locally stores setting and status values from the Websocket events and 'set' methods in the SDK.
This improves the responsiveness of the 'get' methods because your exhibit won't have to wait for an http request while the websocket connection is active.
In our testing, we've found our websocket connection to be reliable. However, if the websocket ever fails to catch and surface an event, the locally stored values may be outdated.
To force the locally stored values to update with the Gumband web services' values, you can restart your exhibit or run syncManifest()
.
Connecting to hardware (optional)
- Go to the Gumband Dashboard and make sure Hardware is created. If not, assuming you have the necessary permissions, create a Hardware device. Make sure the Hardware is in the same Organization and Site as your Exhibit.
- Under the "Overview" tab in the Hardware page, select "Connect to Exhibit" and select the desired Exhibit to connect to.
- Next time you run the Exhibit SDK, it will automatically pull in the Hardware information and wait for an incomming Hardware registration through GBTT.
- Verify that the Hardware device points to the Exhibit's GBTT endpoint (default port: 8883) and that it is sending the correct Hardware ID and Hardware Authentication Token.
Optional Constructor Parameters for hardware
gbttEnabled
(boolean): Set totrue
to run the MQTT broker for hardware communication, defaults tofalse
.gbttPort
(number): What port to run the MQTT broker, defaults to1883
.noInternetConnection
(boolean): Whether the exhibit will run in offline mode. Default isfalse
. This is mostly useful for when an exhibit is going to run without an internet connection but still wants to communicate with Gumband hardware through MQTT.noInternetHardwareIds
(string[]): Specify an array of Gumband hardware IDs to allow to connect to this exhibit. Used in conjunction withnoInternetConnection=true
. Warning: this will allow any hardware with the specified IDs to send and receive data from the exhibit without authentication.
// optional construct parameters for hardware example
const gb = new Gumband(
"a986dc223cc137xxxxxxxxxxxxxxx", // exhibit token
"6", // exhibit ID
"/path/to/manifest.json", // manifest path
{
gbttEnabled: false, // or true to enable the hardware MQTT broker (set to false by default)
gbttPort: 8884, // port for the MQTT broker, defaults to 1883
noInternetConnection: false, // true if the SDK needs to run in offline mode (set to false by default)
noInternetHardwareIds: [], // array of offline hardware IDs to accept messages from (without auth)
}
);
Developing the SDK
- To initialize the SDK for local development, run the command
git submodule update --recursive --remote
to pull in all necessary submodules. - To develop the SDK, create a copy of the
template-test-scripts/
folder and name itlocal-test/
(the naming is important because it is git-ignored). - Modify the Exhibit token and Exhibit ID to point to an exhibit in your local environment.
- Test exhibit while editing the SDK source folder in
lib/
.