Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .env

This file was deleted.

17 changes: 17 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Required: Your Bandwidth account ID
REACT_APP_ACCOUNT_ID=

# Required: Your OAuth / Identity token
REACT_APP_AUTH_TOKEN=

# Required: Source phone number (e.g. +15551234567)
REACT_APP_ACCOUNT_USERNAME=

# Optional: Override the WebRTC gateway WebSocket URL
# REACT_APP_GATEWAY_URL=wss://gateway.pv.prod.global.aws.bandwidth.com/prod/gateway-service/api/v1/endpoints

# Optional: Override the Bandwidth REST API base URL
# REACT_APP_HTTP_BASE_URL=https://api.bandwidth.com/v2

# Optional: Event callback URL for inbound call notifications
# REACT_APP_EVENT_CALLBACK_URL=
7 changes: 3 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
.env
.env.*
!.env.example

npm-debug.log*
yarn-debug.log*
Expand Down
189 changes: 98 additions & 91 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# In-App Calling Dialpad

# Table of Contents
# Table of Contents

* [Description](#description)
* [Pre-Requisites](#pre-requisites)
* [Initialization](#initialization)
* [Running the Application](#running-the-application)
- [Description](#description)
- [Pre-Requisites](#pre-requisites)
- [Initialization](#initialization)
- [Running the Application](#running-the-application)

# Description

Expand All @@ -17,58 +17,64 @@ In order to use this sample app, your account must have In-App Calling enabled.

For more information about API credentials see our [Account Credentials](https://dev.bandwidth.com/docs/account/credentials) page.

### Environmental Variables
### Environment Setup

The sample app uses the below environmental variables.
1. Copy the example environment file:

```sh
REACT_APP_IN_APP_CALLING_TOKEN # You Identity Token
REACT_APP_ACCOUNT_USERNAME # Put from number here
REACT_APP_ACCOUNT_DISPLAY_NAME # Put from number/display name here
REACT_APP_ACCOUNT_PASSWORD # use some password or leave it empty
cp .env.example .env
```

2. Fill in your values in `.env`:

```sh
REACT_APP_ACCOUNT_ID= # Your Bandwidth account ID
REACT_APP_AUTH_TOKEN= # Your OAuth / Identity token
REACT_APP_ACCOUNT_USERNAME= # Source phone number (e.g. +15551234567)
```

Optional overrides (uncomment in `.env` if needed):

```sh
# REACT_APP_GATEWAY_URL= # Override the WebRTC gateway WebSocket URL
# REACT_APP_HTTP_BASE_URL= # Override the Bandwidth REST API base URL
# REACT_APP_EVENT_CALLBACK_URL= # Event callback URL for inbound call notifications
```

# Initialization

- **BandwidthUA**: The instance is available from the outset, Initialization required before making the call, follow the below code snippet for initialization
```sh
const serverConfig = {
domain: 'gw.webrtc-app.bandwidth.com',
addresses: ['wss://gw.webrtc-app.bandwidth.com:10081'],
iceServers: [
'stun.l.google.com:19302',
'stun1.l.google.com:19302',
'stun2.l.google.com:19302',
],
};
const phone = new BandwidthUA();

phone.setServerConfig(
serverConfig.addresses,
serverConfig.domain,
serverConfig.iceServers
);
phone.setWebSocketKeepAlive(5, false, false);
- **BandwidthUA**: The instance is available from the outset. Initialization is required before making a call. Follow the below code snippet for initialization:

```js
import { BandwidthUA } from "@bandwidth/bw-webrtc-sdk";

const phone = new BandwidthUA({
accountId: accountId,
});

phone.checkAvailableDevices();
phone.setAccount(`${sourceNumber}`, 'In-App Calling Sample', '');
phone.setAccount(`${sourceNumber}`, "In-App Calling Sample", "");
phone.setOAuthToken(authToken);
phone.init();
await phone.init();
```

> **Note:** In v1.2.0, `setServerConfig()` is no longer required. The SDK connects directly to the Bandwidth WebRTC backend. The only new requirement is passing `accountId` in the constructor. See the [SDK README](https://github.com/Bandwidth/javascript-webrtc-sdk#migration-from-v11x) for migration details.

# Usage

### Making a Call

Making a call using the Bandwidth services involves a series of steps to ensure the call's proper initiation and management.

```sh
var activeCall = async phone.makeCall(`${destNumber}`, extraHeaders);
```js
const activeCall = await phone.makeCall(`${destNumber}`, extraHeaders);
```

Keep the `activeCall` instance global in persistant state in order to reuse this instance for call termination, hold & mute.
Keep the `activeCall` instance in persistent state in order to reuse this instance for call termination, hold & mute.

### Terminating a Call

```sh
```js
activeCall.terminate();
```

Expand All @@ -84,79 +90,80 @@ In the provided code, the `BandwidthUA.setListeners` is used. This listener has

To use the listener, you implement it as an anonymous class and provide logic inside each method:

```sh
```js
phone.setListeners({
loginStateChanged: function (isLogin, cause) {
console.log(cause);
switch (cause) {
case 'connected':
console.log('phone>>> loginStateChanged: connected');
break;
case 'disconnected':
console.log('phone>>> loginStateChanged: disconnected');
break;
case 'login failed':
console.log('phone>>> loginStateChanged: login failed');
break;
case 'login':
console.log('phone>>> loginStateChanged: login');
break;
case 'logout':
console.log('phone>>> loginStateChanged: logout');
break;
}
},

outgoingCallProgress: function (call, response) {
updateFBStatus("Call-Initiate");
console.log('phone>>> outgoing call progress');
},

callTerminated: function (call, message, cause) {
console.log(`phone>>> call terminated callback, cause=${cause}`);
},

callConfirmed: function (call, message, cause) {
console.log('phone>>> callConfirmed');
},

callShowStreams: function (call, localStream, remoteStream) {
console.log('phone>>> callShowStreams');
let remoteVideo = document.getElementById('remote-video-container');
if (remoteVideo != undefined) {
remoteVideo.srcObject = remoteStream;
}
},

incomingCall: function (call, invite) {
console.log('phone>>> incomingCall');
},

callHoldStateChanged: function (call, isHold, isRemote) {
console.log(`phone>>> callHoldStateChanged to ${isHold ? 'hold' : 'unhold'} `);
}
loginStateChanged: function (isLogin, cause) {
console.log(cause);
switch (cause) {
case "connected":
console.log("phone>>> loginStateChanged: connected");
break;
case "disconnected":
console.log("phone>>> loginStateChanged: disconnected");
break;
case "login failed":
console.log("phone>>> loginStateChanged: login failed");
break;
case "login":
console.log("phone>>> loginStateChanged: login");
break;
case "logout":
console.log("phone>>> loginStateChanged: logout");
break;
}
},

outgoingCallProgress: function (call, response) {
console.log("phone>>> outgoing call progress");
},

callTerminated: function (call, message, cause) {
console.log(`phone>>> call terminated callback, cause=${cause}`);
},

callConfirmed: function (call, message, cause) {
console.log("phone>>> callConfirmed");
},

callShowStreams: function (call, localStream, remoteStream) {
console.log("phone>>> callShowStreams");
let remoteVideo = document.getElementById("remote-video-container");
if (remoteVideo != undefined) {
remoteVideo.srcObject = remoteStream;
}
},

incomingCall: function (call, invite) {
console.log("phone>>> incomingCall");
},

callHoldStateChanged: function (call, isHold, isRemote) {
console.log(
`phone>>> callHoldStateChanged to ${isHold ? "hold" : "unhold"}`
);
},
});
```

### Configuring Inbound Calls

- **Overview:** We have used two major capabilities to make the inbound call

- Caller to Callee & Callback from Callee to Caller
- Bridging the both calls to connect caller and callee in a single call
- Caller to Callee & Callback from Callee to Caller
- Bridging the both calls to connect caller and callee in a single call

- **Sequence Diagram:** Follow sequence diagram to implement the in call using the SDK
![InboundFLow](bandwidth-inbound-react.drawio.svg)
![InboundFLow](bandwidth-inbound-react.drawio.svg)

- **Notification Handler Service Sample:**
https://github.com/Bandwidth-Samples/in-app-calling-inbound-demo

# Running the Application

Use the following command/s to run the application:
Use the following command to run the application:

```sh
yarn start
npm start
```

# Error Handling
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@babel/plugin-proposal-private-property-in-object": "^7.16.7"
},
"dependencies": {
"@bandwidth/bw-webrtc-sdk": "^1.1.4",
"@bandwidth/bw-webrtc-sdk": "file:../javascript-webrtc-sdk",
"@emotion/react": "^11.8.1",
"@emotion/styled": "^11.8.1",
"@mui/icons-material": "^5.14.0",
Expand Down
30 changes: 13 additions & 17 deletions src/components/DialPad.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Button } from '@mui/material';
export default function DialPad() {
const userId = process.env.REACT_APP_ACCOUNT_USERNAME;
const authToken = process.env.REACT_APP_AUTH_TOKEN;
const accountId = process.env.REACT_APP_ACCOUNT_ID;
const sourceNumber = userId;

const { totalSeconds, seconds, minutes, hours, start, pause, reset } = useStopwatch({ autoStart: false });
Expand Down Expand Up @@ -71,23 +72,18 @@ export default function DialPad() {
}, [])

useEffect(() => {
const serverConfig = {
domain: 'gw.webrtc-app.bandwidth.com',
addresses: ['wss://gw.webrtc-app.bandwidth.com:10081'],
iceServers: [
'stun.l.google.com:19302',
'stun1.l.google.com:19302',
'stun2.l.google.com:19302',
],
};
const newPhone = new BandwidthUA();
const newPhone = new BandwidthUA({
accountId: accountId,
// Optional overrides:
// gatewayUrl: process.env.REACT_APP_GATEWAY_URL,
// httpBaseUrl: process.env.REACT_APP_HTTP_BASE_URL,
// eventCallbackUrl: process.env.REACT_APP_EVENT_CALLBACK_URL,
});
console.log(`version: `, newPhone.version());

// These are still accepted for backwards compatibility but are no longer
// required — the new SDK connects directly to the WebRTC gateway.
newPhone.setWebSocketKeepAlive(5, false, false, 5, true);
newPhone.setServerConfig(
serverConfig.addresses,
serverConfig.domain,
serverConfig.iceServers,
);

//overriding the SDK logs
newPhone.setBWLogger((...e) => {
Expand All @@ -111,8 +107,8 @@ export default function DialPad() {
case 'disconnected':
console.log('phone>>> loginStateChanged: disconnected');
if (phone.isInitialized()) {
// after deinit() phone will disconnect SBC.
console.log('Cannot connect to SBC server');
// after deinit() phone will disconnect from gateway.
console.log('Cannot connect to WebRTC gateway server');
}
break;
case 'login failed':
Expand Down