npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@deeplocal/gumband-node-sdk

v2.0.13

Published

The Gumband SDK; made with ❤️ at Deeplocal

Downloads

298

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 be v1.
  • endpoint (string): What Gumband environment to operate with. Value can be local, dev,stag, app, or custom.
  • customServerIp (string): If endpoint=custom, what DNS name or IP address is the Gumband environment at. Value should be similar to test.gumband.com or 192.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 to null to explicitly not sync any files.
  • skipOrganizationFileSync (boolean): Set to false to sync organization level files. Defaults to true.
// 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 to warn
  • GB_MUTE_HEARTBEAT (boolean): whether or not to mute the heartbeat logs, defaults to false

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 the settinglistitems field. If the settings list contains a nested settings list, that nested list will appear in the settinglistitems 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)

  1. 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.
  2. Under the "Overview" tab in the Hardware page, select "Connect to Exhibit" and select the desired Exhibit to connect to.
  3. Next time you run the Exhibit SDK, it will automatically pull in the Hardware information and wait for an incomming Hardware registration through GBTT.
  4. 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 to true to run the MQTT broker for hardware communication, defaults to false.
  • gbttPort (number): What port to run the MQTT broker, defaults to 1883.
  • noInternetConnection (boolean): Whether the exhibit will run in offline mode. Default is false. 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 with noInternetConnection=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

  1. To initialize the SDK for local development, run the command git submodule update --recursive --remote to pull in all necessary submodules.
  2. To develop the SDK, create a copy of the template-test-scripts/ folder and name it local-test/ (the naming is important because it is git-ignored).
  3. Modify the Exhibit token and Exhibit ID to point to an exhibit in your local environment.
  4. Test exhibit while editing the SDK source folder in lib/.