Initialization and Getting Started

Install the library

The first thing that you need to do is install our NPM package in your solution. The main package is hosted on npm (node package manager). If you are making an app for NodeJS - eg. an Electron desktop app - then this package is the only thing you need in order to get going.

You can install the NPM package from a terminal, opening the folder of your application, and running the NPM install command.

npm i @gnaudio/jabra-js --save

For other pre-requisites that may be needed for using the library, see the JavaScript Integration Component page.

See our guide on Module Import Strategies to learn more about different import formats.

Getting started in the browser

There are several ways of including the package in your application. A common approach is to use a module bundler like Webpack and import via the node_modules id, as shown in the example below.

import { init } from '@gnaudio/jabra-js';

init().then((api) => {
  // Library initialized...
});

If you are using the package directly on your website, point to the "browser-umd" build instead:

<html>
  <head>
    <script src="./node_modules/@gnaudio/jabra-js/browser-umd/index.js"></script>

    <script>
      // The module will be loaded into global scope as `jabra`
      jabra.init().then((api) => {
        // Library initialized...
      });
    </script>
  </head>
</html>

Getting started in Node

We support both CommonJS (require) and EcmaScript (import) syntax. In the example below, the module is imported using CommonJS.

const jabra = require('@gnaudio/jabra-js/node-cjs');

jabra.init().then((api) => {
  // Library initialized...
});

Summary

If you have completed the above steps for your target platform then that's it! You can start integrating the Jabra library into your solution.

Initialize the library

The integration library must be initialized before it can be used. This will allocate and activate the necessary system resources required by the library to function.

import { init } from '@gnaudio/jabra-js';

init().then((jabralib) => {
  // Library initialized...
});

Configure the library

The Jabra library can optionally be configured at initialization by using an IConfig object.

The configuration object allows you to set different app related keys, control the level of tracking, define a logger function and set a transport mechanism for device communication.

This section will elaborate on the configuration keys and tracking. To know more about the logger function please see the following section. Information on transport options can be found in the WebHID guide.

const config = {
  partnerKey: "get-from-developer-zone",
  appId: "self-chosen-app-identifier",
  appName: "The Name of My App",
  tracking: "track-all",
};

await init(config);

See Code Sample

partnerKey and appId

The motivation for adding the partnerKey and appId is:

  • Keys are used to register your application with Jabra Direct. Here, it will be added to the "Preferred softphone" selector. This will mitigate co-existence issues with other softphone applications; like preventing device signals from being used by multiple applications at the same time.
  • The Jabra support team can provide faster and more precise help if keys are provided while also setting tracking to track-errors.
  • Similarly, if tracking is set to track-usage you will be able to monitor how users interact with Jabra devices.

The partnerKey can be obtained from the Jabra Developer Zone. As the name suggest, you would need one per partner organization. The key can be reused across apps if needed.

The appId is a self-chosen identifier specific for the app. Furthermore, if you build your app to different targets, e.g. Electron and the browser, the appId should be unique between targets. Reusing the appId may lead to undesirable co-existence issues if two apps run in parallel on the same computer, so we strongly advise against that. Can be any string of minimum three characters consisting of letters, numbers, underscores or dashes. For example: my-unique-app-identifier.

appName

Provide a human-readable app name. This is used whenever a reference to your app needs to be shown to end-users. For instance, the preferred softphone selector in Jabra Direct. Can be any string of minimum three characters consisting of letters, numbers, dashes, spaces or ampersand. For example: My App Name.

If appName is not provided, the library will fallback to display the appId instead. We strongly advise to provide a human-readable name for this property.

tracking

You can set the level of tracking that the library is allowed to perform. The default is that there is no tracking.

All available: TrackingOptions.

When tracking is allowed, the library occasionally sends data to Jabra servers if connected to the internet.

Note: the feature is awaiting finalization on the server side, so for the time being, no tracking will be performed despite being allowed. However, we advise setting the key now in readiness as this will automatically enable the feature once it is ready.

Controlling logging

When initializing the library you have the option to pass in a custom logger. The custom logger should have a defined write(logEvent) method, where the received logEvent parameter holds information about the incident.

   const config = {
    logger: {
      write(logEvent) {
        if (logEvent.level === 'error') {
          console.log(logEvent.message, logEvent.layer);
        }
      }
    }
  };

  const jabra = await init(config);

See Code Sample

Each log event has a log level property denoting the severity. The log level can be used to filter what gets logged. Read about each member in the API reference on LogLevel. In addition, the log event will show in which layer of the stack the error occurred. Explanation of the different layers and enum member values are available in the documentation on StackLayer.

The Native Console Application and the Chrome Extension will forward error messages to the custom logger, so you can collect all logs from this method - and optionally extend it with your own app-specific logging.

The Jabra library does not provide a way of saving log files - this implementation detail is up to you. We strongly recommend saving logs, either to a file on the filesystem or using a cloud logging service.

Using Jabra library modules

Overview

The Jabra library is a modular library. It comes with a "core" interface, which enables developers to discover Jabra USB devices and communicate with these devices via HID. Several modules are then available, which build on top of the core interface, in order to provide common functionality, for example call control or telemetry.

These modules are optional and are meant to be initialized depending on your use case.

The functionality they offer can be almost completely replicated by using the basic core module.

This section will guide you through initializing and using these optional modules.

Initializing a module

Initializing the core library

The prerequisite in using any of the optional modules is initializing the core library.

import { init } from './node_modules/@gnaudio/jabra-js/browser-esm/index.js';

const coreApi = await init();

[Note] For the rest of this section, we will assume you have initialized the core API and assigned it to a variable called coreApi.

Initializing an optional module

Once you have initialized and have a reference to the core API, you can initialize any optional module.

For every module, a "factory" class exists that helps you initialize the module and make use of the attached Jabra devices.

To initialize a module, you have to create a new instance of the aforementioned "factory" helper class. Creating that instance requires you to pass a reference to the core API. Depending on the module, additional parameters might be required. For example, the Call Control module comes with a CallControlFactory class, and has an additional mandatory parameter, which specifies the unique name and ID of your software product.

Below is an example of initializing the Call Control module:

const coreApi; // We assume the core has been initialized

// Creating a CallControlFactory initializes the module
const callControlFactory = new CallControlFactory(coreApi);

[Note] The modules do not interfere with each other. You can also initialize the same module multiple times if you so decide, although we do not recommend it.

Using the core API to enable module functionality

Once the module is initialized, you can take any IDevice instance and feed it to the factory object you used to initialize the optional module.

Using the Call Control module as an example, you can use any IDevice to create a ICallControl object, which you can then use for any call control functionality (for that device):

const callControlFactory = new CallControlFactory(coreApi);

// Whenever the core module detects new devices...
coreApi.deviceAdded.subscribe((newCoreDevice: IDevice) => {
  // Convert the IDevice to a ICallControl
  callControlFactory
    .createCallControl(newCoreDevice)
    .then((deviceCallControl: ICallControl) => {
      // Do call control-related functionality, for example
      deviceCallControl.takeCallLock();
      deviceCallControl.offHook(true);
      deviceCallControl.mute(true);
    });
});

Error handling

This section will help you catch and react to errors coming from the Jabra library.

We divide errors into categories such as usage errors, unsupported features, device errors, and initialization errors.

Depending on the context, some of these errors should be communicated to the end-users and others are only relevant for you - the developer. The API Reference has a full list of error types, corresponding enum member values, and descriptions - see ErrorType.

See Code Sample

Catching errors

All calls to Jabra APIs should be wrapped in try-catch blocks. Either as general try-catches or per call for better control.

The error object returned from the catch will be an instance of custom IJabraError object, which will provide an extra type property denoting what kind of error it is.

Example:

  try {
    device.offHook(true);
  } catch (err) {
      if (err instanceof JabraError) { // err can be any type so make sure it's actually a JabraError
        console.log(err.message); // Calls can only be started and stopped when the call lock is held.
        console.log(err.type);    // 'sdk-usage-error'
      }
  }

In this example, device.offHook(true) is called without first obtaining the callLock. This is an implementation error and something you should fix before releasing to end-users.

Typescript users can import the ErrorType enum from the main package. IntelliSense comments further explain the purpose of each error type, and when to expect it.

import { ErrorType } from '@gnaudio/jabra-js';

if (err.type === ErrorType.FEATURE_NOT_SUPPORTED) {
  alert("Your device does not support this feature!");
}

Not using TypeScript? Please refer to ErrorType in the API Reference to get the different type strings.

Communicating errors to users

Certain errors need to acted upon, especially errors related to unsupported features and initialization, hence these must be communicated to the end-user.

A scenario could be a user trying to perform an action not supported by the device such as trying to mute a device that does not have a microphone.

Initialization errors could mean that the user hasn't installed the Chrome Extension and the Native Console App. In that case, prompting the user to install these necessary components would be a good idea. Alternatively, if you're developing an app for a call center with central IT-administration, you might need to warn the administrator instead.

Next Steps