Set up Toggle Agent availability in Twilio
To make the agent available or unavailable, we need to use the Device object in the
Twilio SDK. The Device
object represents a softphone that communicates with
Twilio to help inbound and outbound audio connections.
Overview
Here's an overview of the sequence of operations performed once an agent marks themselves as available by clicking the Toggle Agent Availability button in the media toolbar application:
- The agent clicks the Toggle Agent Availability button on the media toolbar.
- The media toolbar application fires a REST API call to fetch the ID and toked required for authentication.
- The Twilio service authenticates the request and returns the ID and token.
- The media toolbar application uses this token to initialize the Device object provided by Twilio SDK.
- Once the device object is registered in Twilio, it fires a
registered
event. - When the registered event is received in your media toolbar application, the
invoke agentStateEvent
UEF operation to make the agent state available. - After the fusion application identifies this action, the agent state is made as Available in the Fusion application also.
Update makeAgentAvailable method in VendorHandler to call the supplier API to make the agent available
- Create a method in the
vendorHandler
class (src/ts/cti/vendor/vendorHandler.ts
) with the following code:private async getIdAndToken(): Promise<any> { const headers: Headers = (new Headers()) as Headers; const url: string = 'https://twilio-node-voice-stream.com/token'; // Replace this url with the url of the deployed node app headers.set('Accept', 'application/json'); const request: Request = new Request(url, { method: 'GET', headers: headers }) as Request; const idAndToken: Response = await fetch(request); this.idAndToken = await idAndToken.json(); return this.idAndToken; }
- Add the following import
statement:
import { Call, Device } from '@twilio/voice-sdk'; import { ICtiVendorHandler } from './ICtiVendorHandler'; import { IntegrationEventsHandler } from '../integrationEventsHandler';
- Create two class properties in Twilio,
device
andidAndToken
as shown:export class VendorHandler implements ICtiVendorHandler { private twilio: any; private device: Device | null; private integrationEventsHandler: IntegrationEventsHandler; public idAndToken: any; constructor(integrationEventsHandler: IntegrationEventsHandler) { this.twilio = (window as any).Twilio; this.device = null; this.idAndToken = null; this.integrationEventsHandler = integrationEventsHandler; } // ... }
- Instantiate a device with
DeviceOptions
:const idAndToken = await this.getIdAndToken(); // get the id token this.device = new this.twilio.Device(idAndToken.token, { logLevel: 1, codecPreferences: ["opus", "pcmu"], enableRingingState: true });
- To make the agent available call the register on the device instance as
shown:
this.device.register();
- Use the
registered
event anderror
event to get the result for registration event as shown:this.device.on("registered", () => { // Do your logic when registration is completed. }); this.device.on("error", (deviceError) => { // Do your logic when the registration fails });
- Update the
makeAgentAvailable
method invendorHandler
as shown:public async makeAgentAvailable(): Promise<void> { await this.getIdAndToken(); this.device = this.twilio.Device(this.idAndToken.token, { logLevel: 1, codecPreferences: ["opus", "pcmu"], enableRingingState: true }); let resolve: Function; let reject: Function; if (this.device) { this.device.on("registered", () => { console.log("Registration completed ...") resolve(); }); this.device.on("error", (deviceError) => { console.error("Registration Failed ...", deviceError); reject(); }); this.device.register(); } return new Promise((res: Function, rej: Function) => { resolve = res; reject = rej; }); }
- Update the
makeAgentUnavailable
method inVendorHandler
as shown:public async makeAgentUnavailable(): Promise<void> { let resolve: Function; let reject: Function; if (this.device) { this.device.on("unregistered", () => { console.log("Successfully UnRegistered ..."); resolve(); }); this.device.on("error", (deviceError) => { console.error("Failed to unregister ...", deviceError); reject(); }); this.device.unregister(); } return new Promise((res: Function, rej: Function) => { resolve = res; reject = rej; }); }
- View the complete code:
import { Call, Device } from '@twilio/voice-sdk'; import { ICtiVendorHandler } from './ICtiVendorHandler'; import { IntegrationEventsHandler } from '../integrationEventsHandler'; export class VendorHandler implements ICtiVendorHandler { private twilio: any; private device: Device | null; private integrationEventsHandler: IntegrationEventsHandler; public idAndToken: any; constructor() { this.twilio = (window as any).Twilio; this.device = null; this.idAndToken = null; this.integrationEventsHandler = integrationEventsHandler; } public async makeAgentAvailable(): Promise<void> { const idAndToken = await this.getIdAndToken(); this.device = new Device(idAndToken.token, { logLevel: 1, codecPreferences: [Call.Codec.Opus, Call.Codec.PCMU], //enableRingingState: true }); let resolve: Function; let reject: Function; if (this.device) { this.device.on("registered", () => { console.log("Registration completed ...") resolve(); }); this.device.on("error", (deviceError) => { console.error("Registration Failed ...", deviceError); reject(); }); this.device.register(); } return new Promise((res: Function, rej: Function) => { resolve = res; reject = rej; }); } public async makeAgentUnavailable(): Promise<void> { let resolve: Function; let reject: Function; if (this.device) { this.device.on("unregister", () => { console.log("Successfully UnRegistered ...") resolve(); }); this.device.on("error", (deviceError) => { console.error("Failed to unregister ...", deviceError); reject(); }); this.device.unregister(); } return new Promise((res: Function, rej: Function) => { resolve = res; reject = rej; }); } public async makeOutboundCall(phoneNumber: string, eventId: string): Promise<void> { throw new Error('Method not implemented.'); } public async acceptCall(): Promise<void> { throw new Error('Method not implemented.'); } public async rejectCall(): Promise<void> { throw new Error('Method not implemented.'); } public async hangupCall(): Promise<void> { throw new Error('Method not implemented.'); } private async getIdAndToken(): Promise<any> { const headers: Headers = (new Headers()) as Headers; headers.set('Accept', 'application/json'); const request: Request = new Request('https://twilio-node-voice-stream.com/token', { method: 'GET', headers: headers }) as Request; const idAndToken: Response = await fetch(request); this.idAndToken = await idAndToken.json(); return this.idAndToken; } }
Verify your progress
Sign in to your Fusion application and open the media toolbar. Click the Agent Availability button from your media toolbar application. You'll see that the button color changes to and the phone icon status in the Fusion application is changed to Available.