public async Task WaitForAVFlowConnectedShouldReturnWhenFlowConnected() { // Given TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_AudioVideoFlowAdded.json"); Task flowConnectedTask = m_audioVideoCall.WaitForAVFlowConnected(); await Task.Delay(300).ConfigureAwait(false); Assert.IsFalse(flowConnectedTask.IsCompleted); // When TestHelper.RaiseEventsFromFile(m_mockEventChannel, "Event_AudioVideoFlowConnected.json"); // Then Assert.IsTrue(flowConnectedTask.IsCompleted); }
private async Task StartAudioVideoIVRFlowAsync(IncomingInviteEventArgs <IAudioVideoInvitation> e) { Logger.Instance.Information(string.Format("[StartAudioVideoIVRFlowAsync]: LoggingContext: {0}", m_loggingContext)); m_pstnCallConversation = null; // Step1: accept incoming call Logger.Instance.Information(string.Format("[StartAudioVideoIVRFlowAsync] Step 1: Accept incoming av call: LoggingContext: {0}", m_loggingContext)); await e.NewInvite.AcceptAsync(m_loggingContext).ConfigureAwait(false); await e.NewInvite.WaitForInviteCompleteAsync().ConfigureAwait(false); // if everything is fine, you will be able to get the related conversation m_pstnCallConversation = e.NewInvite.RelatedConversation; m_pstnCallConversation.HandleResourceRemoved += HandlePSTNCallConversationRemoved; // Step 2 : wait AV flow connected and play Promt IAudioVideoCall pstnAv = m_pstnCallConversation.AudioVideoCall; IAudioVideoFlow pstnFlow = await pstnAv.WaitForAVFlowConnected().ConfigureAwait(false); pstnFlow.ToneReceivedEvent += ToneReceivedEvent; // Step 3 : play prompt await PlayPromptAsync(pstnFlow, AudioVideoIVRAction.PlayMainPrompt).ConfigureAwait(false); }
private async Task StartHuntGroupFlowAsync(IncomingInviteEventArgs <IAudioVideoInvitation> e) { Logger.Instance.Information(string.Format("[StartHuntGroupFlow] StartHuntGroupFlow: LoggingContext: {0}", LoggingContext)); m_pstnCallConversation = null; m_outboundAVConversations = new List <IConversation>(); // Step1: accept incoming call Logger.Instance.Information(string.Format("[StartHuntGroupFlow] Step 1: Accept incoming av call: LoggingContext: {0}", LoggingContext)); await e.NewInvite.AcceptAsync(LoggingContext).ConfigureAwait(false); await e.NewInvite.WaitForInviteCompleteAsync().ConfigureAwait(false); // if everything is fine, you will be able to get the related conversation m_pstnCallConversation = e.NewInvite.RelatedConversation; m_pstnCallConversation.HandleResourceRemoved += HandlePSTNCallConversationRemoved; // Step 2 : wait AV flow connected and play Promt IAudioVideoCall pstnAv = m_pstnCallConversation.AudioVideoCall; IAudioVideoFlow pstnFlow = await pstnAv.WaitForAVFlowConnected().ConfigureAwait(false); pstnFlow.ToneReceivedEvent += HandleToneReceived; // Step 3 : play prompt // We support two modes in this job. // A : InviteTargetUris are provided in the configuration; we will send invites to all of them and transfer the incoming call // to whoever accepts it. // B : InviteTargetUris not provided in the configuration; we will provide the user with a list of agents and let the user // pick the target transfer using DTMF tones. bool skipDTMF = m_jobInput.InviteTargetUris != null && m_jobInput.InviteTargetUris.Length > 0; string wavFile = skipDTMF ? "HuntGroupA.wav" : "HuntGroupB.wav"; var resourceUri = new Uri(string.Format(this.AzureApplication.ResourceUriFormat, wavFile)); try { await pstnFlow.PlayPromptAsync(resourceUri, LoggingContext).ConfigureAwait(false); } catch (CapabilityNotAvailableException ex) { Logger.Instance.Error("[HuntGroupJob] PlayPrompt api is not available!", ex); } catch (RemotePlatformServiceException ex) { ErrorInformation error = ex.ErrorInformation; if (error != null && error.Code == ErrorCode.Informational && error.Subcode == ErrorSubcode.CallTerminated) { Logger.Instance.Information("[HuntGroupJob] Call terminated while playing prompt."); } else { throw; } } string callContext = pstnAv.CallContext; if (string.IsNullOrEmpty(callContext)) { throw new PlatformserviceApplicationException("No valid callcontext in audioVideo resource "); } //Step 4 : Make out bound call to agents and do transfer ICommunication communication = m_pstnCallConversation.Parent as ICommunication; bool transferFlowSuccess = false; if (skipDTMF) { List <Task> TasksWithAgent = new List <Task>(); foreach (string to in m_jobInput.InviteTargetUris) { Task a = this.StartAgentCallAndTransferFlowAsync(communication, to, callContext).ContinueWith ( pTask => { if (pTask.IsFaulted) { Logger.Instance.Warning("[HuntGroupJob] Transfer flow failed." + pTask.Exception); } else { Logger.Instance.Information("[HuntGroupJob] Transfer flow complete."); transferFlowSuccess = true; } } ); TasksWithAgent.Add(a); } await Task.WhenAll(TasksWithAgent.ToArray()).ConfigureAwait(false); } else //Upgraded version, with DTMF recognize { //wait tone string target = await m_toneReceived.Task.ConfigureAwait(false); try { await this.StartAgentCallAndTransferFlowAsync(communication, target, callContext).ConfigureAwait(false); transferFlowSuccess = true; } catch (CapabilityNotAvailableException ex) { Logger.Instance.Warning("[HuntGroupJob] Transfer flow failed.", ex); } catch (RemotePlatformServiceException ex) { Logger.Instance.Warning("[HuntGroupJob] Transfer flow failed.", ex); } } m_outboundCallTransferLock = 0; if (transferFlowSuccess) { Logger.Instance.Information("TransferFlow success"); } else { Logger.Instance.Error("TransferFlow Failed, see above trace for error info"); } }
private async Task StartCallCenterFlowAsync(IncomingInviteEventArgs <IAudioVideoInvitation> e) { Logger.Instance.Information(string.Format("[StartCallCenterFlowAsync] StartCallCenterFlowAsync: LoggingContext: {0}", m_loggingContext)); m_pstnCallConversation = null; m_outboundAVConversations = new List <IConversation>(); // Step1: accept incoming call Logger.Instance.Information(string.Format("[StartCallCenterFlowAsync] Step 1: Accept incoming av call: LoggingContext: {0}", m_loggingContext)); await e.NewInvite.AcceptAsync(m_loggingContext).ConfigureAwait(false); await e.NewInvite.WaitForInviteCompleteAsync().ConfigureAwait(false); // if everything is fine, you will be able to get the related conversation m_pstnCallConversation = e.NewInvite.RelatedConversation; m_pstnCallConversation.HandleResourceRemoved += HandlePSTNCallConversationRemoved; // Step 2 : wait AV flow connected and play Promt IAudioVideoCall pstnAv = m_pstnCallConversation.AudioVideoCall; IAudioVideoFlow pstnFlow = await pstnAv.WaitForAVFlowConnected().ConfigureAwait(false); // Step 3 : play prompt // InviteTargetUris are provided in the configuration; we will send invites to all of them and transfer the incoming call // to whoever accepts it. string wavFile = "CallTransferSample.wav"; var resourceUri = new Uri(string.Format("{0}://{1}/resources/{2}", m_callbackUri.Scheme, m_callbackUri.Host, wavFile)); try { await pstnFlow.PlayPromptAsync(resourceUri, m_loggingContext).ConfigureAwait(false); } catch (CapabilityNotAvailableException ex) { Logger.Instance.Error("[CallCenterJob] PlayPrompt api is not available!", ex); } catch (RemotePlatformServiceException ex) { ErrorInformation error = ex.ErrorInformation; if (error != null && error.Code == ErrorCode.Informational && error.Subcode == ErrorSubcode.CallTerminated) { Logger.Instance.Information("[CallCenterJob] Call terminated while playing prompt."); } else { throw; } } string callContext = pstnAv.CallContext; if (string.IsNullOrEmpty(callContext)) { throw new Exception("No valid callcontext in audioVideo resource "); } //Step 4 : Make out bound call to agents and do transfer ICommunication communication = m_pstnCallConversation.Parent as ICommunication; bool transferFlowSuccess = false; List <Task> TasksWithAgent = new List <Task>(); foreach (string to in m_inviteTargetUris) { Task a = this.StartAgentCallAndTransferFlowAsync(communication, to, callContext).ContinueWith ( pTask => { if (pTask.IsFaulted) { Logger.Instance.Warning("[CallCenterJob] Transfer flow failed." + pTask.Exception); } else { Logger.Instance.Information("[CallCenterJob] Transfer flow complete."); transferFlowSuccess = true; } } ); TasksWithAgent.Add(a); } await Task.WhenAll(TasksWithAgent.ToArray()).ConfigureAwait(false); m_outboundCallTransferLock = 0; if (transferFlowSuccess) { Logger.Instance.Information("TransferFlow success"); } else { Logger.Instance.Error("TransferFlow Failed, see above trace for error info"); } }
public async Task RunAsync() { var skypeId = ConfigurationManager.AppSettings["Trouter_SkypeId"]; var password = ConfigurationManager.AppSettings["Trouter_Password"]; var applicationName = ConfigurationManager.AppSettings["Trouter_ApplicationName"]; var userAgent = ConfigurationManager.AppSettings["Trouter_UserAgent"]; var token = SkypeTokenClient.ConstructSkypeToken( skypeId: skypeId, password: password, useTestEnvironment: false, scope: string.Empty, applicationName: applicationName).Result; m_logger = new SampleAppLogger(); // Uncomment for debugging m_logger.HttpRequestResponseNeedsToBeLogged = true; EventChannel = new TrouterBasedEventChannel(m_logger, token, userAgent); // Prepare platform var platformSettings = new ClientPlatformSettings(QuickSamplesConfig.AAD_ClientSecret, new Guid(QuickSamplesConfig.AAD_ClientId)); var platform = new ClientPlatform(platformSettings, m_logger); // Prepare endpoint var endpointSettings = new ApplicationEndpointSettings(new SipUri(QuickSamplesConfig.ApplicationEndpointId)); var applicationEndpoint = new ApplicationEndpoint(platform, endpointSettings, EventChannel); var loggingContext = new LoggingContext(Guid.NewGuid()); await applicationEndpoint.InitializeAsync(loggingContext).ConfigureAwait(false); await applicationEndpoint.InitializeApplicationAsync(loggingContext).ConfigureAwait(false); // Meeting configuration var meetingConfiguration = new AdhocMeetingCreationInput(Guid.NewGuid().ToString("N") + " test meeting"); // Schedule meeting var adhocMeeting = await applicationEndpoint.Application.CreateAdhocMeetingAsync(loggingContext, meetingConfiguration).ConfigureAwait(false); WriteToConsoleInColor("ad hoc meeting uri : " + adhocMeeting.OnlineMeetingUri); WriteToConsoleInColor("ad hoc meeting join url : " + adhocMeeting.JoinUrl); // Get all the events related to join meeting through Trouter's uri platformSettings.SetCustomizedCallbackurl(new Uri(EventChannel.CallbackUri)); // Start joining the meeting var invitation = await adhocMeeting.JoinAdhocMeeting(loggingContext, null).ConfigureAwait(false); var conversation = invitation.RelatedConversation; // Wait for the join to complete await invitation.WaitForInviteCompleteAsync().ConfigureAwait(false); conversation.HandleParticipantChange += Conversation_HandleParticipantChange; IAudioVideoCall audioVideoCall = conversation.AudioVideoCall; await audioVideoCall.EstablishAsync(loggingContext).ConfigureAwait(false); // Wait for the audiovideo call to complete await audioVideoCall.WaitForAVFlowConnected().ConfigureAwait(false); WriteToConsoleInColor("Showing roaster udpates for 1 minute for meeting : " + adhocMeeting.JoinUrl); // Wait for 1 minutes before playing prompt. During this time, we can connect from other skype client and listen prompt. // Since we have registered Conversation_HandleParticipantChange, we will also continue to show participant changes in the // meeting for this duration. await Task.Delay(TimeSpan.FromMinutes(1)).ConfigureAwait(false); Uri promptUri = new Uri(mediaUrl); // Wait for prompt play to complete await audioVideoCall.AudioVideoFlow.PlayPromptAsync(promptUri, loggingContext).ConfigureAwait(false); // exit after play prompt. wait for 5 seconds to see all responses. await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false); }