Skip to content

Commit 1be7f4c

Browse files
authored
Merge pull request #217335 from ashwinder/eventgrid
how-to guide for signaling actions
2 parents d2409ac + 3f4b52f commit 1be7f4c

File tree

7 files changed

+287
-0
lines changed

7 files changed

+287
-0
lines changed

articles/communication-services/concepts/voice-video-calling/call-automation.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ These actions can be performed on the calls that are answered or placed using Ca
101101

102102
**Terminate** – Whether your application has answered a one-to-one or group call, or placed an outbound call with one or more participants, this action will remove all participants and end the call. This operation is triggered by setting `forEveryOne` property to true in Hang-Up call action.
103103

104+
104105
## Events
105106

106107
The following table outlines the current events emitted by Azure Communication Services. The two tables below show events emitted by Event Grid and from the Call Automation as webhook events.
@@ -117,6 +118,8 @@ Most of the events sent by Event Grid are platform agnostic meaning they're emit
117118
| ParticipantAdded | A participant has been added to a call |
118119
| ParticipantRemoved| A participant has been removed from a call |
119120

121+
Read more about these events and payload schema [here](../../../event-grid/communication-services-voice-video-events.md)
122+
120123
### Call Automation webhook events
121124

122125
The Call Automation events are sent to the web hook callback URI specified when you answer or place a new outbound call.
@@ -136,6 +139,8 @@ The Call Automation events are sent to the web hook callback URI specified when
136139
| RecognizeFailed | Recognition of user input was unsuccessful <br/>*to learn more about recognize action events view our [quickstart](../../quickstarts/voice-video-calling/Recognize-Action.md)*|
137140

138141

142+
To understand which events are published for different actions, refer to [this guide](../../how-tos/call-automation-sdk/actions-for-call-control.md) that provides code samples as well as sequence diagrams for various call control flows.
143+
139144
## Known Issues
140145

141146
1. Using the incorrect IdentifierType for endpoints for `Transfer` requests (like using CommunicationUserIdentifier to specify a phone number) returns a 500 error instead of a 400 error code. Solution: Use the correct type, CommunicationUserIdentifier for Communication Users and PhoneNumberIdentifier for phone numbers.
@@ -145,3 +150,8 @@ The Call Automation events are sent to the web hook callback URI specified when
145150

146151
> [!div class="nextstepaction"]
147152
> [Get started with Call Automation](./../../quickstarts/voice-video-calling/Callflows-for-customer-interactions.md)
153+
154+
Here are some articles of interest to you:
155+
1. Understand how your resource will be [charged for various calling use cases](../pricing.md) with examples.
156+
2. Learn about metrics and logs available for this service.
157+
1. Troubleshoot common issues.
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
---
2+
title: Azure Communication Services Call Automation how-to for managing calls with Call Automation
3+
titleSuffix: An Azure Communication Services how-to document
4+
description: Provides a how-to guide on using call actions to steer and manage a call with Call Automation.
5+
author: ashwinder
6+
7+
ms.topic: how-to
8+
ms.service: azure-communication-services
9+
ms.subservice: call-automation
10+
ms.date: 11/03/2022
11+
ms.author: askaur
12+
manager: visho
13+
ms.custom: private_preview
14+
services: azure-communication-services
15+
zone_pivot_groups: acs-csharp-java
16+
---
17+
18+
# How to control and steer calls with Call Automation
19+
> [!IMPORTANT]
20+
> Functionality described on this document is currently in private preview. Private preview includes access to SDKs and documentation for testing purposes that are not yet available publicly. Apply to become an early adopter by filling out the form for [preview access to Azure Communication Services](https://aka.ms/ACS-EarlyAdopter).
21+
22+
Call Automation uses a REST API interface to receive requests for actions and provide responses to notify whether the request was successfully submitted or not. Due to the asynchronous nature of calling, most actions have corresponding events that are triggered when the action completes successfully or fails. This guide covers the actions available for steering calls, like CreateCall, Transfer, Redirect, and managing participants. Actions are accompanied with sample code on how to invoke the said action and sequence diagrams describing the events expected after invoking an action. These diagrams will help you visualize how to program your service application with Call Automation.
23+
24+
Call Automation supports various other actions to manage call media and recording that aren't included in this guide.
25+
26+
> [!NOTE]
27+
> Call Automation currently doesn't interoperate with Microsoft Teams. Actions like making, redirecting a call to a Teams user or adding them to a call using Call Automation isn't supported.
28+
29+
As a pre-requisite, we recommend you to read the below articles to make the most of this guide:
30+
1. Call Automation [concepts guide](../../concepts/voice-video-calling/call-automation.md#call-actions) that describes the action-event programming model and event callbacks.
31+
2. Learn about [user identifiers](../../concepts/identifiers.md#the-communicationidentifier-type) like CommunicationUserIdentifier and PhoneNumberIdentifier used in this guide.
32+
33+
For all the code samples, `client` is CallAutomationClient object that can be created as shown and `callConnection` is the CallConnection object obtained from Answer or CreateCall response. You can also obtain it from callback events received by your application.
34+
## [csharp](#tab/csharp)
35+
```csharp
36+
var client = new CallAutomationClient("<resource_connection_string>");
37+
```
38+
## [Java](#tab/java)
39+
```java
40+
CallAutomationClient client = new CallAutomationClientBuilder().connectionString("<resource_connection_string>").buildClient();
41+
```
42+
-----
43+
44+
## Make an outbound call
45+
You can place a 1:1 or group call to a communication user or phone number (public or Communication Services owned number). Below sample makes an outbound call from your service application to a phone number.
46+
callerIdentifier is used by Call Automation as your application's identity when making an outbound a call. When calling a PSTN endpoint, you also need to provide a phone number that will be used as the source caller ID and shown in the call notification to the target PSTN endpoint.
47+
To place a call to a Communication Services user, you'll need to provide a CommunicationUserIdentifier object instead of PhoneNumberIdentifier.
48+
### [csharp](#tab/csharp)
49+
```csharp
50+
Uri callBackUri = new Uri("https://<myendpoint>/Events"); //the callback endpoint where you want to receive subsequent events
51+
var callerIdentifier = new CommunicationUserIdentifier("<user_id>");
52+
CallSource callSource = new CallSource(callerIdentifier);
53+
callSource.CallerId = new PhoneNumberIdentifier("+16044561234"); // This is the ACS provisioned phone number for the caller
54+
var callThisPerson = new PhoneNumberIdentifier("+16041234567");
55+
var listOfPersonToBeCalled = new List<CommunicationIdentifier>();
56+
listOfPersonToBeCalled.Add(callThisPerson);
57+
var createCallOptions = new CreateCallOptions(callSource, listOfPersonToBeCalled, callBackUri);
58+
CreateCallResult response = await client.CreateCallAsync(createCallOptions);
59+
```
60+
### [Java](#tab/java)
61+
```java
62+
String callbackUri = "https://<myendpoint>/Events"; //the callback endpoint where you want to receive subsequent events
63+
List<CommunicationIdentifier> targets = new ArrayList<>(Arrays.asList(new PhoneNumberIdentifier("+16471234567")));
64+
CommunicationUserIdentifier callerIdentifier = new CommunicationUserIdentifier("<user_id>");
65+
CreateCallOptions createCallOptions = new CreateCallOptions(callerIdentifier, targets, callbackUri)
66+
.setSourceCallerId("+18001234567"); // This is the ACS provisioned phone number for the caller
67+
Response<CreateCallResult> response = client.createCallWithResponse(createCallOptions).block();
68+
```
69+
-----
70+
The response provides you with CallConnection object that you can use to take further actions on this call once it's connected. Once the call is answered, two events will be published to the callback endpoint you provided earlier:
71+
1. `CallConnected` event notifying that the call has been established with the callee.
72+
2. `ParticipantsUpdated` event that contains the latest list of participants in the call.
73+
![Sequence diagram for placing an outbound call.](media/make-call-flow.png)
74+
75+
76+
## Answer an incoming call
77+
Once you've subscribed to receive [incoming call notifications](../../concepts/voice-video-calling/incoming-call-notification.md) to your resource, below is sample code on how to answer that call. When answering a call, it's necessary to provide a callback url. Communication Services will post all subsequent events about this call to that url.
78+
### [csharp](#tab/csharp)
79+
80+
```csharp
81+
string incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
82+
Uri callBackUri = new Uri("https://<myendpoint_where_I_want_to_receive_callback_events");
83+
84+
var answerCallOptions = new AnswerCallOptions(incomingCallContext, callBackUri);
85+
AnswerCallResult answerResponse = await client.AnswerCallAsync(answerCallOptions);
86+
CallConnection callConnection = answerResponse.CallConnection;
87+
```
88+
### [Java](#tab/java)
89+
90+
```java
91+
String incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
92+
String callbackUri = "https://<myendpoint>/Events";
93+
94+
AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri);
95+
Response<AnswerCallResult> response = client.answerCallWithResponse(answerCallOptions).block();
96+
```
97+
-----
98+
The response provides you with CallConnection object that you can use to take further actions on this call once it's connected. Once the call is answered, two events will be published to the callback endpoint you provided earlier:
99+
1. `CallConnected` event notifying that the call has been established with the caller.
100+
2. `ParticipantsUpdated` event that contains the latest list of participants in the call.
101+
102+
![Sequence diagram for answering an incoming call.](media/answer-flow.png)
103+
104+
## Reject a call
105+
You can choose to reject an incoming call as shown below. You can provide a reject reason: none, busy or forbidden. If nothing is provided, none is chosen by default.
106+
# [csharp](#tab/csharp)
107+
```csharp
108+
string incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
109+
var rejectOption = new RejectCallOptions(incomingCallContext);
110+
rejectOption.CallRejectReason = CallRejectReason.Forbidden;
111+
_ = await client.RejectCallAsync(rejectOption);
112+
```
113+
# [Java](#tab/java)
114+
115+
```java
116+
String incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
117+
RejectCallOptions rejectCallOptions = new RejectCallOptions(incomingCallContext)
118+
.setCallRejectReason(CallRejectReason.BUSY);
119+
Response<Void> response = client.rejectCallWithResponse(rejectCallOptions).block();
120+
```
121+
-----
122+
No events are published for reject action.
123+
124+
## Redirect a call
125+
You can choose to redirect an incoming call to one or more endpoints without answering it. Redirecting a call will remove your application's ability to control the call using Call Automation.
126+
# [csharp](#tab/csharp)
127+
```csharp
128+
string incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
129+
var target = new CommunicationUserIdentifier("<user_id_of_target>"); //user id looks like 8:a1b1c1-...
130+
var redirectOption = new RedirectCallOptions(incomingCallContext, target);
131+
_ = await client.RedirectCallAsync(redirectOption);
132+
```
133+
# [Java](#tab/java)
134+
```java
135+
String incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
136+
CommunicationIdentifier target = new CommunicationUserIdentifier("<user_id_of_target>"); //user id looks like 8:a1b1c1-...
137+
RedirectCallOptions redirectCallOptions = new RedirectCallOptions(incomingCallContext, target);
138+
Response<Void> response = client.redirectCallWithResponse(redirectCallOptions).block();
139+
```
140+
-----
141+
To redirect the call to a phone number, set the target to be PhoneNumberIdentifier.
142+
# [csharp](#tab/csharp)
143+
```csharp
144+
var target = new PhoneNumberIdentifier("+16041234567");
145+
```
146+
# [Java](#tab/java)
147+
```java
148+
CommunicationIdentifier target = new PhoneNumberIdentifier("+18001234567");
149+
```
150+
-----
151+
No events are published for redirect. If the target is a Communication Services user or a phone number owned by your resource, it will generate a new IncomingCall event with 'to' field set to the target you specified.
152+
153+
## Transfer a 1:1 call
154+
When your application answers a call or places an outbound call to an endpoint, that endpoint can be transferred to another destination endpoint. Transferring a 1:1 call will remove your application from the call and hence remove its ability to control the call using Call Automation.
155+
# [csharp](#tab/csharp)
156+
```csharp
157+
var transferDestination = new CommunicationUserIdentifier("<user_id>");
158+
var transferOption = new TransferToParticipantOptions(transferDestination);
159+
TransferCallToParticipantResult result = await callConnection.TransferCallToParticipantAsync(transferOption);
160+
```
161+
# [Java](#tab/java)
162+
```java
163+
CommunicationIdentifier transferDestination = new CommunicationUserIdentifier("<user_id>");
164+
TransferToParticipantCallOptions options = new TransferToParticipantCallOptions(transferDestination);
165+
Response<TransferCallResult> transferResponse = callConnectionAsync.transferToParticipantCallWithResponse(options).block();
166+
```
167+
-----
168+
When transferring to a phone number, it's mandatory to provide a source caller ID. This ID serves as the identity of your application(the source) for the destination endpoint.
169+
# [csharp](#tab/csharp)
170+
```csharp
171+
var transferDestination = new PhoneNumberIdentifier("+16041234567");
172+
var transferOption = new TransferToParticipantOptions(transferDestination);
173+
transferOption.SourceCallerId = new PhoneNumberIdentifier("+16044561234");
174+
TransferCallToParticipantResult result = await callConnection.TransferCallToParticipantAsync(transferOption);
175+
```
176+
# [Java](#tab/java)
177+
```java
178+
CommunicationIdentifier transferDestination = new PhoneNumberIdentifier("+16471234567");
179+
TransferToParticipantCallOptions options = new TransferToParticipantCallOptions(transferDestination)
180+
.setSourceCallerId(new PhoneNumberIdentifier("+18001234567"));
181+
Response<TransferCallResult> transferResponse = callConnectionAsync.transferToParticipantCallWithResponse(options).block();
182+
```
183+
-----
184+
The below sequence diagram shows the expected flow when your application places an outbound 1:1 call and then transfers it to another endpoint.
185+
![Sequence diagram for placing a 1:1 call and then transferring it.](media/transfer-flow.png)
186+
187+
## Add a participant to a call
188+
You can add one or more participants (Communication Services users or phone numbers) to an existing call. When adding a phone number, it's mandatory to provide source caller ID. This caller ID will be shown on call notification to the participant being added.
189+
# [csharp](#tab/csharp)
190+
```csharp
191+
var addThisPerson = new PhoneNumberIdentifier("+16041234567");
192+
var listOfPersonToBeAdded = new List<CommunicationIdentifier>();
193+
listOfPersonToBeAdded.Add(addThisPerson);
194+
var addParticipantsOption = new AddParticipantsOptions(listOfPersonToBeAdded);
195+
addParticipantsOption.SourceCallerId = new PhoneNumberIdentifier("+16044561234");
196+
AddParticipantsResult result = await callConnection.AddParticipantsAsync(addParticipantsOption);
197+
```
198+
# [Java](#tab/java)
199+
```java
200+
CommunicationIdentifier target = new PhoneNumberIdentifier("+16041234567");
201+
List<CommunicationIdentifier> targets = new ArrayList<>(Arrays.asList(target));
202+
AddParticipantsOptions addParticipantsOptions = new AddParticipantsOptions(targets)
203+
.setSourceCallerId(new PhoneNumberIdentifier("+18001234567"));
204+
Response<AddParticipantsResult> addParticipantsResultResponse = callConnectionAsync.addParticipantsWithResponse(addParticipantsOptions).block();
205+
```
206+
-----
207+
To add a Communication Services user, provide a CommunicationUserIdentifier instead of PhoneNumberIdentifier. Source caller ID isn't mandatory in this case.
208+
209+
AddParticipant will publish a `AddParticipantSucceeded` or `AddParticipantFailed` event, along with a `ParticipantUpdated` providing the latest list of participants in the call.
210+
211+
![Sequence diagram for adding a participant to the call.](media/add-participant-flow.png)
212+
213+
## Remove a participant from a call
214+
# [csharp](#tab/csharp)
215+
```csharp
216+
var removeThisUser = new CommunicationUserIdentifier("<user_id>");
217+
var listOfParticipantsToBeRemoved = new List<CommunicationIdentifier>();
218+
listOfParticipantsToBeRemoved.Add(removeThisUser);
219+
var removeOption = new RemoveParticipantsOptions(listOfParticipantsToBeRemoved);
220+
RemoveParticipantsResult result = await callConnection.RemoveParticipantsAsync(removeOption);
221+
```
222+
# [Java](#tab/java)
223+
```java
224+
CommunicationIdentifier removeThisUser = new CommunicationUserIdentifier("<user_id>");
225+
RemoveParticipantsOptions removeParticipantsOptions = new RemoveParticipantsOptions(new ArrayList<>(Arrays.asList(removeThisUser)));
226+
Response<RemoveParticipantsResult> removeParticipantsResultResponse = callConnectionAsync.removeParticipantsWithResponse(removeParticipantsOptions).block();
227+
```
228+
-----
229+
RemoveParticipant only generates `ParticipantUpdated` event describing the latest list of participants in the call. The removed participant is excluded if remove operation was successful.
230+
![Sequence diagram for removing a participant from the call.](media/remove-participant-flow.png)
231+
232+
## Hang up on a call
233+
Hang Up action can be used to remove your application from the call or to terminate a group call by setting forEveryone parameter to true. For a 1:1 call, hang up will terminate the call with the other participant by default.
234+
235+
# [csharp](#tab/csharp)
236+
```csharp
237+
_ = await callConnection.HangUpAsync(true);
238+
```
239+
# [Java](#tab/java)
240+
```java
241+
Response<Void> response1 = callConnectionAsync.hangUpWithResponse(new HangUpOptions(true)).block();
242+
```
243+
-----
244+
CallDisconnected event is published once the hangUp action has completed successfully.
245+
246+
## Get information about a call participant
247+
# [csharp](#tab/csharp)
248+
```csharp
249+
CallParticipant participantInfo = await callConnection.GetParticipantAsync("<user_id>")
250+
```
251+
# [Java](#tab/java)
252+
```java
253+
CallParticipant participantInfo = callConnection.getParticipant("<user_id>").block();
254+
```
255+
-----
256+
257+
## Get information about all call participants
258+
# [csharp](#tab/csharp)
259+
```csharp
260+
List<CallParticipant> participantList = (await callConnection.GetParticipantsAsync()).Value.ToList();
261+
```
262+
# [Java](#tab/java)
263+
```java
264+
List<CallParticipant> participantsInfo = Objects.requireNonNull(callConnection.listParticipants().block()).getValues();
265+
```
266+
-----
267+
268+
## Get latest info about a call
269+
# [csharp](#tab/csharp)
270+
```csharp
271+
CallConnectionProperties thisCallsProperties = callConnection.GetCallConnectionProperties();
272+
```
273+
# [Java](#tab/java)
274+
```java
275+
CallConnectionProperties thisCallsProperties = callConnection.getCallProperties().block();
276+
```
277+
-----
27.4 KB
Loading
42.9 KB
Loading
27.2 KB
Loading
21.6 KB
Loading
48.3 KB
Loading

0 commit comments

Comments
 (0)