wazo-platform / wazo-js-sdk

Wazo's JavaScript Software Development Kit.
https://www.npmjs.com/package/@wazo/sdk
MIT License
36 stars 18 forks source link
conference-talk sdk telephony

Wazo's JavaScript Software Development Kit

npm version Greenkeeper badge

Wazo JavaScript SDK makes it easy for you to build Programmable Conversation applications. Use this dev kit in any JS application to leverage communication possibilities.

Supported Features

Wazo's Javascript SDK allows you to use these features :

Install

Install / Add

Voice Video Chat Fax Status Config Misc

You may install the Wazo JavaScript Software Development Kit to your project one of the following ways:

Content Delivery Networks

Voice Video Chat Fax Status Config Misc

Alternatively, you may load the Wazo SDK from a CDN. Use one of the following Content Delivery Networks:

UNPKG

<script src="https://unpkg.com/@wazo/sdk/dist/wazo-sdk.js"></script>

jsDelivr

<script src="https://cdn.jsdelivr.net/npm/@wazo/sdk"></script>

Simple API

Importing the Simple API

// For Node / packaged app
import Wazo from '@wazo/sdk';

// Browser
// You can access the `Wazo` object directly on the browser, simply include it in the html :
<script src="https://unpkg.com/@wazo/sdk/dist/wazo-sdk.js"></script>
or 
<script src="https://cdn.jsdelivr.net/npm/@wazo/sdk"></script>

Authentication with the simple API

Initializing

Wazo.Auth.init(clientId, tokenExpiration, minSubscriptionType, authorizationName);

Setting the engine host

Wazo.Auth.setHost(host);

Customizing all the fetch options

Wazo.Auth.fetchOptions({
  referrer: '',
});

Authenticating a user

const session = await Wazo.Auth.logIn(username, password, backend, tenantId);

Returns as Wazo.domain.Session. This object contains, among other information, the user's token.

Note: you need to set clientId in your WazoAPIClient in order to get a refresh token in the returned Session.

Authenticating a user with SAML

const response = await Wazo.Auth.initiateIdpAuthentication(domain, redirectUrl);

Returns an object that contains a location and a saml_session_id

location is the URL to open for the user to log in through an identity provider.

saml_session_id needs to be used to create a wazo-auth token once the SAML authentication has been completed successfully.

const session = await Wazo.Auth.samlLogIn(samlSessionId);

Returns as Wazo.domain.Session. This object contains, among other information, the user's token.

const logoutResponse = await Wazo.Auth.samlLogOut();

Returns an object that contains a location

location is the URL to open for the user to log out from their identity provider.

Validating a token

const session = await Wazo.Auth.validateToken(token, refreshToken);

Returns as Wazo.domain.Session.

Setting a callback when a new token is refreshed

When the user's token is about to expire, Wazo's SDK triggers a callback so you can update it in your application. Like updating the new token in your localstorage / cookies.

Note: you need to set clientId in your WazoAPIClient in order to refresh tokens.

Wazo.Auth.setOnRefreshToken(token => { /* Do something with the new token */ });

Logging out

Destroys user's token and refreshToken.

await Wazo.Auth.logout();

Conference

Joining a room

Wazo.Room.connect(options);

Returns a Wazo.Room instance.

Sending a chat message in the room

room.sendChat(content);

Sending a custom message to all participants

room.sendSignal(content);

Sharing the user screen

room.startScreenSharing(constraints);

Stopping the screen share

room.stopScreenSharing();

Disabling the camera

room.turnCameraOff();

Enabling the camera

room.turnCameraOn();

Disabling the microphone

room.mute();

Enabling the microphone

room.unmute();

Accessing room participants

room.participants;

participants: An array of Wazo.LocalParticipant and Wazo.RemoteParticipant.

Disconnect from the room

Wazo.room.disconnect();

Conference events

room.on(room.ON_CHAT, (message) => {});

Triggered when receiving a chat message.

room.on(room.ON_MESSAGE, (message) => {});

Triggered when receiving a custom message.

room.on(room.ON_JOINED, (participant) => {});

Triggered when joining the room.

room.on(room.CONFERENCE_USER_PARTICIPANT_JOINED, (participant) => {});

Triggered when a participant joins the room.

room.on(room.CONFERENCE_USER_PARTICIPANT_LEFT, (participant) => {});

Triggered when a participant leaves the room.

room.on(room.ON_SCREEN_SHARE_ENDED, () => {});

Triggered when screensharing is stopped.

room.on(room.ON_TALKING, (channel, participant) => {});

Triggered when a participant is talking or stops talking.

Ad hoc Conference features

Voice Video

Merging sessions in one conference

Use this method to merge multiple calls in a new ad hoc conference.

const adHocConference = Wazo.Phone.startConference(host: CallSession, otherCalls: CallSession[]): Promise<AdHocAPIConference>;

Add a call to a conference

Use this method to add a single call to an existing conference room.

adHocConference.addParticipant(participant: CallSession);

Remove a call from a conference

Use this method to remove a participant from a conference.

adHocConference.removeParticipant(callSession: CallSession);
// shouldHold indicate if the session should be held after removed from session

Terminating a conference

Use this method to terminate a conference.

adHocConference.hangup();

Accessing the current WebRtc phone

You can access the current webRtcPhone instance via Wazo.Phone.phone.

Domains

You can access all Wazo's domain objects in Wazo.domain.*, like Wazo.domain.Session;

Participant

Wazo.LocalParticipant and Wazo.RemoteParticipant shares the same properties :

Participant events

participant.on(participant.ON_UPDATED, () => {});

Triggered when the participant is updated.

participant.on(participant.ON_START_TALKING, () => {});

Triggered when the participant is talking.

participant.on(participant.ON_STOP_TALKING, () => {});

Triggered when the participant stops talking.

participant.on(participant.ON_DISCONNECT, () => {});

Triggered when the participant leaves the room.

participant.on(participant.ON_STREAM_SUBSCRIBED, (stream) => {});

Triggered when the participant sends a stream.

participant.on(participant.ON_STREAM_UNSUBSCRIBED, (stream) => {});

Triggered when the participant stops sending a stream.

participant.on(participant.ON_AUDIO_MUTED, () => {});

Triggered when the participant has disabled his microphone.

participant.on(participant.ON_AUDIO_UNMUTED, () => {});

Triggered when the participant has enabled his microphone.

participant.on(participant.ON_VIDEO_MUTED, () => {});

Triggered when the participant has disabled his camera.

participant.on(participant.ON_VIDEO_UNMUTED, () => {});

Triggered when the participant has enabled his camera.

participant.on(participant.ON_SCREENSHARING, () => {});

Triggered when the participant is sharing his screen.

participant.on(participant.ON_STOP_SCREENSHARING, () => {});

Triggered when the participant stops sharing his screen.

Stream

Wazo.Stream helps attach or detach streams to HTML elements:

stream.attach(htmlEmelent)

Attaches a stream to an existing htmlElement or creates and returns a new one.

Returns a htmlElement (audio or video) attached to the stream.

stream.detach(htmlEmelent)

Detaches a stream from an existing htmlElement.

Advanced API

Libraries

Require / Import

Voice Video Chat Fax Status Config Misc

Depending on your preference, you may require or add the Wazo SDK to your own client application one of the following ways using:

API Client Library

Depending on your environment you can import:

WebRTC Library
import { WebRTCClient } from '@wazo/sdk';
WebSocket Library
import { WazoWebSocketClient } from '@wazo/sdk';

Authentication

Initialization

Voice Video Chat Fax Status Config Misc

When using API Client
const client = new WazoApiClient({
  server: 'stack.example.com', // required string
  agent: null, // http(s).Agent instance, allows custom proxy, unsecured https, certificate etc.
  clientId: null, // Set an identifier for your app when using refreshToken
  isMobile: false,
});
When using WebRTC
const session = await client.auth.logIn({ ... });

Log In

Voice Video Chat Fax Status Config Misc

client.auth.logIn({
  expiration, // optional integer. Session life in number of seconds. If omitted, defaults to 3600 (an hour).
  username, // required string
  password, // required string
  backend, // optional string. If omitted, defaults to wazo_user
  mobile, // optional boolean. If omitted, defaults to false: tells if the current user uses a mobile application
  tenantId, // optional string. The tenant identifier (uuid or slug). Needed when backend is external (not wazo_user)
}).then(/* undefined if login failed, or : */{
  metadata: {
    username,
    uuid_tenant_uuid,
    xivo_user_uuid,
    groups,
    xivo_uuid,
    tenants: [{ uuid }],
    auth_id
  },
  // should be used for other request
  acl,
  utc_expires_at,
  xivo_uuid,
  issued_at,
  utc_issued_at,
  auth_id,
  expires_at,
  xivo_user_uuid
});
// or
const { refreshToken, ...result } = await client.auth.logIn(/* ... */);

Note: you need to set clientId in your WazoAPIClient in order to get a refresh token.

Set token (and refresh token)

Voice Video Chat Fax Status Config Misc

client.setToken(token);
client.setRefreshToken(refreshToken);
client.setRefreshTokenExpiration(tokenExpirationInSeconds);

Note: you need to set clientId in your WazoAPIClient in order to get a refresh token.

Add an event when the token is refreshed

Voice Video Chat Fax Status Config Misc

client.setOnRefreshToken((newToken, newSession) => {
  // Do something with the new token and the new session (like storing them in the localstorage...).
});

Note: you need to set clientId in your WazoAPIClient to refresh a token.

Log Out

Voice Video Chat Fax Status Config Misc

client.auth.logOut(token).then(/* ... */);
// or
await client.auth.logOut(token);

Check token

Voice Video Chat Fax Status Config Misc

client.auth.checkToken(token).then(valid);
// or
const valid = await client.auth.checkToken(token);

Other auth methods

Config

client.auth.listTenants();
client.auth.createTenant(name);
client.auth.deleteTenant(uuid);
client.auth.createUser(username, password, firstname, lastname);
client.auth.addUserEmail(userUuid, email, main);
client.auth.addUserPolicy(userUuid, policyUuid);
client.auth.deleteUser();
client.auth.listUsers();
client.auth.listGroups();
client.auth.createPolicy(name, description, acl);
client.auth.listPolicies();

Sending logs to fluentd via a HTTP endpoint

Logger

Log

import Wazo from '@wazo/sdk';

Wazo.IssueReporter.enable();
Wazo.IssueReporter.configureRemoteClient({
    host: 'localhost', // fluentd http host
    port: 9880, // fluentd http port
    tag: 'name of your application,
    level: 'trace', // Min log level to be sent
    extra: {
      // Extra info sent for every logs
      user_uuid: '...',
    },
});

Using the logger :

// Log with for category, this will send a `category` attribute in every logs for this logger.
const logger = Wazo.IssueReporter.loggerFor('my_category');
logger(logger.TRACE, 'my log');

// or simply
Wazo.IssueReporter.log(Wazo.IssueReporter.INFO, 'my log');

Interact with the engine

Applicationd

Voice Video Chat Fax Status Config

Use Applicationd to construct your own communication features.

client.application.calls(applicationUuid); // list calls
client.application.hangupCall(applicationUuid, callId); // hangup a call
client.application.answerCall(applicationUuid, callId, context, exten, autoanswer);  // answer a call
client.application.listNodes(applicationUuid); // list nodes
client.application.listCallsNodes(applicationUuid, nodeUuid); // list calls in a node
client.application.removeCallNodes(applicationUuid, nodeUuid, callId); // remove call from node (no hangup)
client.application.addCallNodes(applicationUuid, nodeUuid, callId); // add call in a node
client.application.playCall(applicationUuid, callId, language, uri); // play a sound into a call

Calld

Voice Video Chat Fax Status

Use Calld to directly control interactions. (Please note, ctidNg endpoint is deprecated but continues to work with old versions. Please update your code.)

client.calld.getConferenceParticipantsAsUser(conferenceId); // List participants of a conference the user is part of
client.calld.answerSwitchboardQueuedCall(switchboardUuid, callId);
client.calld.answerSwitchboardHeldCall(switchboardUuid, callId);
client.calld.cancelCall(callId);
client.calld.deleteVoicemail(voicemailId);
client.calld.fetchSwitchboardHeldCalls(switchboardUuid);
client.calld.fetchSwitchboardQueuedCalls(switchboardUuid);
client.calld.getConferenceParticipantsAsUser(conferenceId);
client.calld.getPresence(contactUuid); //deprecated use chatd in ctidNg, don't work with calld
client.calld.getStatus(lineUuid); //deprecated use chatd in ctidNg, don't work with calld
client.calld.holdSwitchboardCall(switchboardUuid, callId);
client.calld.listCalls();
client.calld.listMessages(participantUuid, limit);
client.calld.listVoicemails();
client.calld.makeCall(extension, fromMobile, lineId, allLines);
client.calld.sendFax(extension, fax, callerId);
client.calld.sendMessage(alias, msg, toUserId);
client.calld.relocateCall(callId, destination, lineId);
client.calld.updatePresence(presence);

Confd

Config

Use Confd to interact with configurations.

client.confd.listUsers();
client.confd.getUser(userUuid);
client.confd.getUserLineSip(userUuid, lineId);
client.confd.listApplications();

Dird

Misc

Use Dird to interact with directories.

client.dird.search(context: string, term: string, offset: number, limit: number);
client.dird.listPersonalContacts();
client.dird.addContact(newContact: NewContact);
client.dird.editContact(contact: Contact);
client.dird.deleteContact(contactUuid: UUID);
client.dird.listFavorites(context: string);
client.dird.markAsFavorite(source: string, sourceId: string);
client.dird.removeFavorite(source: string, sourceId: string);

Agentd

Misc

Use Agentd to handle agent states

Legacy (all versions)

client.agentd.getAgent(agentNumber);
client.agentd.login(agentNumber, context, extension);
client.agentd.logout(agentNumber);
client.agentd.pause(agentNumber);
client.agentd.resume(agentNumber);

Log in with line ID only (engine version > 20.11 -- recommended)

client.agentd.loginWithLineId(lineId);

No-args methods (engine version >= 20.17 -- recommended)

client.agentd.getStatus();
client.agentd.staticLogout();
client.agentd.staticPause();
client.agentd.staticResume();

callLogd

Voice Misc

Use callLogd to interact with call logs.

client.callLogd.search(search, limit);
client.callLogd.listCallLogs(offset, limit);
client.callLogd.listCallLogsFromDate(from, number);

Chatd

Chat Status

Use chatd to send and retrieve chat messages and user statuses.

client.chatd.getContactStatusInfo(contactUuid: UUID);
client.chatd.getState(contactUuid: UUID);
client.chatd.getLineState(contactUuid: UUID);
client.chatd.getMultipleLineState(contactUuids: ?Array<UUID>);
client.chatd.getUserRooms();
client.chatd.updateState(contactUuid: UUID, state: string);
client.chatd.updateStatus(contactUuid: UUID, state: string, status: string);
client.chatd.createRoom(name: string, users: Array<ChatUser>);
client.chatd.getRoomMessages(roomUuid: string);
client.chatd.sendRoomMessage(roomUuid: string, message: ChatMessage);
client.chatd.getMessages(options: GetMessagesOptions);

Calling an API endpoint without WazoApiClient

Voice Video Chat Fax Status Config Misc

Use this generic method to request endpoints directly.

const requester = new ApiRequester({ 
  server: 'stack.example.com', // Engine server
  refreshTokenCallback: () => {}, // Called when the token is refreshed
  clientId: 'my-id', // ClientId used for refreshToken
  agent: null, // http(s).Agent instance, allows custom proxy, unsecured https, certificate etc.
  token: null, // User token (can be defined later with requester.setToken()
});

// Retrieve personal contacts
const results = await requester.call('dird/0.1/personal');

WebRTCClient

This sample describes the very first steps to place a call using WebRTC.

import { WebRTCClient } from '@wazo/sdk'; // import the library

const session = await client.auth.logIn({ ... }); // log in

const client = new WebRTCClient({
  displayName: 'From WEB',
  host: 'stack.example.com',
  websocketSip: 'other.url.com', // Allows to connect throught another URL than host (default to `host` is not set).
  media: {
    audio: boolean,
    video: boolean | document.getElementById('video'), // pointing to a `<video id="video" />` element
    localVideo: boolean | document.getElementById('video'), // pointing to a `<video id="video" />` element
  }
}, session);

// eventName can be on the of events : 
// - transport: `connected`, `disconnected`, `transportError`, `message`, `closed`, `keepAliveDebounceTimeout`
// - webrtc: `registered`, `unregistered`, `registrationFailed`, `invite`, `inviteSent`, `transportCreated`, `newTransaction`, `transactionDestroyed`, `notify`, `outOfDialogReferRequested`, `message`.
client.on('invite', (sipSession: SipSession, hasVideo: boolean, shouldAutoAnswer: boolean) => {
  this.currentSipSession = sipSession;
  // ...
});

// We have to wait to be registered to be able to make a call
await client.waitForRegister();

client.call('1234');

WebRTCClient Configuration

const config = {
  displayName: '', // Display name sent in SIP payload
  host: '', // Host where to connect
  port: '', // Port of the host (default to `443`)
  media: {
    audio: boolean, // If we want to send audio
    video: boolean | document.getElementById('video'), // pointing to a `<video id="video" />` element
    localVideo: boolean | document.getElementById('video'), // pointing to a `<video id="video" />` element
  },
  iceCheckingTimeout: 1000, // Time allowed to retrieve ice candidates
  log: {}, // @see https://sipjs.com/api/0.5.0/ua_configuration_parameters/#log
  audioOutputDeviceId: null, // The audio output device id (when we want to send audio in another destination).
  userAgentString: null, // Customize the User-Agent SIP header
  heartbeatDelay: 1000, // Duration in ms between 2 heartbeat (default to 2000)
  heartbeatTimeout: 5000, // Duration in ms when to consider that the Asterisk server is not responding (default to 5000)
  maxHeartbeats: 4, // Number of heatbeat send each time we want to check connection (default to 3)

  // When not passing session as second argument:
  authorizationUser: '', // The SIP username
  password: '', // The SIP user password
  uri: '', // The SIP user identity
}

const uaConfigOverrides = {
  peerConnectionOptions: {
    iceServers = [
      {urls: "stun:stun.example.com:443"},  // STUN server
      {urls: "turn:turn.example.com:443", username: "login", credential: "secret" },  // TURN server
      ...
    ]
  }
}

const client = new WebRTCClient(config, session, /* optional */ uaConfigOverrides);

Basic client features

Voice Video Chat

Calling a number

Use this method to dial a number.

client.call(number: string);
Be notified of a phone call

Use this method to be notified of an incoming call.

client.on('invite', (sipSession: SipSession) => {
  this.currentSipSession = sipSession;
});
Answering a call

Use this method to pick up an incoming call.

client.answer(sipSession: SipSession);
Hangup a call

Use this method to hangup a call (the call must have been already picked up)

client.hangup(sipSession: SipSession);
Rejecting a call

Use this method to deny an incoming call (Must not have been picked up already)

client.reject(sipSession: SipSession);
Muting a call

Use this method to mute yourself in a running call.

client.mute(sipSession: SipSession);
Unmuting a call

Use this method to unmute yourself in a running call.

client.unmute(sipSession: SipSession);
Holding a call

Use this method to put a running call on hold.

client.hold(sipSession: SipSession);
Unholding a call

Use this method to resume a running call.

client.unhold(sipSession: SipSession);
Make a blind transfer

Use this method to transfer a call to another target, without introduction

client.transfer(sipSession: SipSession, target: string);
Make an attended transfer

Use this method to transfer a call to another target, but first introduce the caller to the transfer target. The transfer may be cancelled (hangup the transfer target) or completed (hangup the transfer initiator).

transfer = client.atxfer(sipSession: SipSession);

// Start the transfer to a phone number, starts a new SIP session in the process
transfer.init(target: string)

// Get the new SIP session to the target of the transfer
targetSession = transfer.newSession

// Complete the transfer.
// transfer.init(...) must be called first.
transfer.complete()

// Cancel the transfer.
// transfer.init(...) must be called first.
transfer.cancel()
Sending a DTMF tone

Use this method to send the dual-tone multi-frequency from the phone keypad.

client.sendDTMF(sipSession: SipSession, tone: string);
Sending a message
client.message(destination: string, message: string);

Set the audio output volume

Stores a value between 0 and 1, which can be used to on your audio element

phone.changeAudioOutputVolume(volume: number);

Set the audio ring volume

Stores a value between 0 and 1, which can be used to on your audio element

phone.changeAudioRingVolume(volume: number);

Closing the RTC connection

Use this method to put an end to an RTC connection.

client.close();

WebRTCPhone

Higher level of abstraction to use the WebRtcClient.

import { WebRTCClient, WebRTCPhone } from '@wazo/sdk';

const webRtcClient = new WebRTCClient({/* See above for parameters */});

const phone = new WebRTCPhone(
  webRtcClient: WebRTCClient, // Instance of WebRTCClient
  audioDeviceOutput: string, // The output device used to play audio
  allowVideo: boolean, // Allow to send and receive video
  audioDeviceRing, // The output device used to play ringtones
);

Basic phone features

Voice Video Chat

Calling a number

Use this method to dial a number.

const callSession = await phone.makeCall(
  number: string, // The number to dial
  line: // Not used
  enableVideo: boolean // Optional (default to false) when we want to make a video call 
);
Hangup a call

Use this method to stop a call

phone.hangup(
  callSession: CallSession, // The callSession to stop
);
Accepting a call

Use this method to accept (answer) an incoming call

phone.accept(
  callSession: CallSession, // The callSession to accept
  cameraEnabled?: boolean // Should we accept the call with video
);
Rejecting a call

Use this method to reject an incoming call

phone.reject(
  callSession: CallSession // The callSession to reject
);
Holding a call

Use this method to put a running call on hold.

phone.hold(
  callSession: CallSession, // The call session to put on hold
  withEvent: boolean = true // Should the phone triggers event
);
Resuming a call

Use this method to resume a running call.

phone.resume(callSession: CallSession);

Please note that phone.resume() is the preferred method

phone.unhold(callSession: CallSession); // deprecated
Muting a call

Use this method to mute yourself in a running call.

phone.mute(
  callSession: CallSession, // The call session to mute
  withEvent: boolean = true // Should the phone triggers event
);
Unmuting a call

Use this method to unmute yourself in a running call.

phone.unmute(callSession: CallSession);
Muting camera in a call

Use this method to mute your camera in a running call.

phone.turnCameraOff(callSession: CallSession);
Unmuting camera in a call

Use this method to unmute your camera in a running call.

phone.turnCameraOn(callSession: CallSession);
Sending DTMF

Use this method to unmute yourself in a running call.

phone.sendKey(callSession: CallSession, tone: string);
Transferring a call
Blind transfer

Use this method to transfer a call directly to another extension, without introduction

phone.transfer(
  callSession: CallSession, // The call session to transfer
  target: string // The extension where to transfer to call
);
Attended transfer

Use this method to transfer a call to another extension by allowing to speak with the other participant first and validate the transfer after that. You have to run makeCall first on the target to be able to confirm the transfer with this method.

phone.indirectTransfer(
  callSession: CallSession, // The call session to transfer
  target: string // The extension where to transfer to call
);
Start screen sharing
const screenShareStream: MediaStream = await phone.startScreenSharing({ 
  audio: true, 
  video: true, 
  /* See webRtc media constraints */ 
});
Stop screen sharing
phone.stopScreenSharing();

Conference phone features

Voice Video Chat

Starting a conference

Use this method to start an ad-hoc conference.

phone.startConference(participants: CallSession[]);
Adding a participant to the conference
phone.addToConference(participant: CallSession);
Holding a conference
phone.holdConference(participants: CallSession[]);
Resuming a conference
phone.resumeConference(participants: CallSession[]);
Muting a conference
phone.muteConference(participants: CallSession[]);
Unmuting a conference
phone.unmuteConference(participants: CallSession[]);
Removing participants from a conference
phone.removeFromConference(participants: CallSession[]);
Stopping a conference
phone.hangupConference(participants: CallSession[]);

Advanced phone features

Voice Video Chat

Registering the phone

Sends a SIP REGISTER payload

phone.register();
Check if the phone is registered
phone.isRegistered();
Un-registering the phone

Sends a SIP UNREGISTER payload

phone.unregister();
Updating audio output device
phone.changeAudioDevice(someDevice: string);
Updating audio ring device
phone.changeRingDevice(someDevice: string);
Updating audio input device
phone.changeAudioInputDevice(someDevice: string, session: ?Inviter, force: ?boolean);
Updating video input device
phone.changeVideoInputDevice(someDevice: string);
Checking if it has an active call
phone.hasAnActiveCall(): boolean;
Retrieve the number of active calls
phone.callCount(): number;
Sending a SIP message

Sends a SIP MESSAGE in a session. Use phone.currentSipSession to retrieve the current sipSession.

phone.sendMessage(
  sipSession: SipSession = null, The sip session where to send to message
  body: string, // The message to SEND
);
Closing the phone

Disconnect the SIP webSocket transport.

phone.stop();
Starting heartbeat

Sends a SIP OPTIONS every X seconds, Y times and timeout after Z seconds. See webrtcClient's heartbeatDelay, heartbeatTimeout, maxHeartbeats, configuration.

phone.startHeartbeat();
Stopping heartbeat
phone.stopHeartbeat();

Wazo WebSocket

You can use the Wazo WebSocket to listen for real-time events (eg: receiving a chat message, a presential update...)

Web Socket features

Voice Video Chat Fax Status

Opening the socket
import { WebSocketClient } from '@wazo/sdk';

const ws = new WebSocketClient({
  host: '', // wazo websocket host
  token: '', // valid Wazo token
  events: [''], // List of events you want to receive (use `['*']` as wildcard).
  version: 2, // Use version 2 of the Wazo WebSocket protocol to be informed when the token will expire.
}, {
  // see https://github.com/pladaria/reconnecting-websocket#available-options
});

ws.connect();
Listening for event
import { USERS_SERVICES_DND_UPDATED, AUTH_SESSION_EXPIRE_SOON } from '@wazo/sdk/lib/websocket-client';

// eventName can be on the of events here: http://documentation.wazo.community/en/stable/api_sdk/websocket.html
ws.on('eventName', (data: mixed) => {
});

ws.on(USERS_SERVICES_DND_UPDATED, ({ enabled }) => {
  // Do something with the new do not disturb value.
});

ws.on(AUTH_SESSION_EXPIRE_SOON, (data) => {
  // Called when the user's token will expire soon.
  // You should refresh it at this point (eg: by using a refreshToken).
});
Updating the user token

You can update a new token to avoid being disconnected when the old one will expire.

ws.updateToken(newToken: string);

Closing the socket

ws.close();

Usage with Webpack 5

As Webpack 5 dropped some polyfills, you have to add them manually:

yarn add -D assert buffer https-browserify url stream-http stream-browserify browserify-zlib process

If you have used create-react-app to create your app, you can customize the Webpack configuration with react-app-rewired :

yarn add -D react-app-rewired

Create a config-overrides.js file :

const webpack = require('webpack');
module.exports = function override(config, env) {
  config.resolve.fallback = {
    ...config.resolve.fallback,
    assert: require.resolve("assert"),
    buffer: require.resolve('buffer'),
    https: require.resolve('https-browserify'),
    url: require.resolve('url'),
    http: require.resolve('stream-http'),
    stream: require.resolve('stream-browserify'),
    zlib: require.resolve('browserify-zlib'),
  };

  config.plugins.push(
    new webpack.ProvidePlugin({
      process: 'process/browser',
      Buffer: ['buffer', 'Buffer'],
    }),
  );

  config.module.rules.push({
    test: /\.m?js/,
    resolve: {
      fullySpecified: false
    }
  })

  return config;
}

Then edit in package.json :

"scripts": {
  // ...
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-app-rewired eject"
  // ...
},

Please refer to https://github.com/facebook/create-react-app/issues/11756 for more details.