Using the ServiceHandler

ServiceHandler is the helper global object for connecting to the Captivate API server.

init method

Initializes the connection to the Captivate API server.

// when you want the ServiceHandler to automatically determine the best connection method, use this call.
ServiceHandler.init();

// when you want to use a specific websocket url, initialize with a call like this.
ServiceHandler.init(serverUrl);

// when you want to use a pre-existing websocket or any other socket connection (useful when calling from nodejs), you may pass the socket as the second argument
// The socket must implement the same interface as the native browser JavaScript WebSocket for sending and receiving messages and for closing connections.
ServiceHandler.init(null, socket);

Arguments

  • serverUrl - (optional) URL of the web socket server to use for communication with Captivate. When the script is hosted by the built-in Captivate HTTP server, this argument isn’t needed because Captivate will put its own connection information into a cookie served with the main page. However, if you are hosting your HTML page on another server, you might need to specify this value manually. The url should look like this ws://Captivate_COMPUTER_IP:Captivate_PORT.

    • Captivate_COMPUTER_IP: The hostname or local IP address of the computer running Captivate.

    • PORT: The port Captivate exposes for API communication. Captivate defaults to using port 9023 for the WebSocket API.

      • Changing the webSocket port is possible by editing the NewBlue settings in the Windows Registry or the Mac Preferences.

      • Mac: defaults write com.newblue.captivate 'Generic HTML.webSocketPort' 10002 (from ~/Library/Preferences/com.newblue.captivate.plist)

      • Windows RegEdit: \HKEY_CURRENT_USER\SOFTWARE\NewBlue\Captivate\Generic HTML.httpPort

      • The main HTTP server port can also be read/set using the Generic HTML.httpPort key.

    • To avoid hardcoding this value in your scripts, you can also specify the host and port using a query string in your browser’s url like this: ?ip=127.0.0.1&port=9023. The ServiceHandler object will automatically look for those values if a serverUrl is not provided.

  • socket - When you are running in nodejs or in some other context, you might have a previously negotiated socket compatible with the JavaScript WebSocket interface. You can pass that socket directly to the ServiceHandler as the second argument, specifying the first one as null.

About the automatic connection method

When init is called with no arguments and the ServiceHandler is running in a browser context, the library will attempt to connect with Captivate using a number of different connection methods:

  1. It will gather some default values from the query parameters:

  • It will use ip or hostName to construct a websocket domain (defaults to the domain of the browser url).

  • It will use port as the websocket port (defaults to 9023).

  • It will use wsTunnel as the unique identifier for a remote websocket tunnel (see below).

  • Captivate will automatically add these query parameters to any data controller it hosts.

  1. It will attempt to make the following connections:

  • First, it will try to connect to ws://[ipOrHostName]:[port]

  • Second, it will try to connect to ws://127.0.0.1:[port]

  • Third, it will try to tunnel its websocket connection through NewBlue’s secure server: wss://controllers.newbluefx.com/tunnel/[wsTunnel]/client

  • Fourth, if the SimplePeer library has been loaded into the global scope, ServiceHandler will use the websocket tunnel to negotiate a direct peer-to-peer connection to Captivate through WebRTC. If a WebRTC connection can be established, it will replace the websocket tunnel connection resulting in a direct connection that doesn’t pass through any NewBlue servers.

Example:

<!-- we host a version of simple peer for automatic WebRTC connections -->
<script src="https://newbluefx.com/api/v3/common/js/simplepeer.min.js"></script>
<script src="https://newbluefx.com/api/v3/common/js/qwebchannel.js"></script>
<script src="https://newbluefx.com/api/v3/common/js/servicehandler.js"></script>

<script>
  // Will attempt to auto-connect.
  ServiceHandler.init();

  ServiceHandler.onready = () => {
    // The `ServiceHandler.scheduler` object is ready now.
  };

  ServiceHandler.onerror = () => {
    // handle connection failure messages
  };

  ServiceHandler.onclose = () => {
    // handle connection close here
  };
</script>

scheduler property

Scheduler API object. Will be undefined until the ServiceHandler.onready callback fires.

Usage:

// For safety, check if the scheduler is null or use the `?.` operator since `scheduler` could be undefined.
ServiceHandler.scheduler?.scheduleAction(...);

Using promises instead of callbacks...

The scheduler object exposes all of its functions in a way that allows callbacks or promises.

To provide a callback to any scheduler function, simply include it as the last argument of the function.

If a callback function is not provided, the scheduler will automatically switch to the Promise method and you can use await or .then() / .catch() functions to access the return value.

Finally, if a function is not exported by the current Captivate API, it will not throw an exception, but will instead respond with a failure message.

console.log(await ServiceHandler.scheduler.hello());
/*
{
    "success": false,
    "error": "Method not found. Either we have lost connection to Captivate, or the installed version doesn't support this API method."
}
*/

serverUrl property

Websocket server URL currently used to communicate with Captivate (i.e. ws://localhost:9023).

Usage:

ServiceHandler.onready = () => {
  console.info('ServiceHandler connected to', ServiceHandler.serverUrl);
};

onready callback

Executes when connection to server is established.

Usage:

ServiceHandler.onready = () => {
  console.info('ServiceHandler connected');
};

onclose callback

User callback to execute when connection to server is terminated.

Usage:

ServiceHandler.onclose = () => {
  console.info('ServiceHandler disconnected');
};

onerror callback

User callback to execute when an error is encountered trying to communicate with the server.

Usage:

ServiceHandler.onerror = (e) => {
  console.error('ServiceHandler error', e);
};

Using the ServiceHandler.scheduler Object

All API actions happen with methods defined on the scheduler object. The scheduler object directly exposes these functions from the C++ environment to the JavaScript environment; however, only a few methods are relevant for data controller developers and those are documented here.

In each case, whenever a ‘return’ value is described, it will be passed as the sole argument to a callback function or will be the value of the resolved promise if no callback function is supplied. Additional functions for using the scheduler object can be found on the subsequent pages.

Last updated