right  Talk To Us!

Cloud UAS Sample Outbound Connect

UAS API - Outbound Connect Sample Application

  • Filename:

    samples/outbound_connect.py

    Description:

    An outbound application that makes calls to two destination addresses and connects them together. The destination addresses are supplied in the outbound_parameters variable, using the semi-colon (;) as a delimiter. This application also requires one extra channel.

    First the two call destination addresses are extracted from outbound_parameters using Python's split() function. Then the extra channel is retrieved from the channel.ExtraChannel list. Extra channels are set on the Inbound and Outbound Services pages.

    The application places two calls and the calling code has been put in a function called _place_call, which takes a channel, destination address and call_from as parameters. The call_from variable identifies the calling party and its value is taken from application_parameters which is configured on the Outbound Services page.

    The first outbound call is placed and, if successful, TTS is used to ask the user to speak a message after the beep. To create a beep, a DTMF tone is played using the channel.DTMFPlayer.play() function. The message is recorded and then the caller is asked to hold while the system calls the second destination..

    The extra channel is used to call the second destination and the recorded message from the first call is played using the channel.FilePlayer.start() function which does not block. This allows the application to use TTS to tell the first caller that his message is being played.

    Once the message has been played, the application joins the two calls together using the channel.connect() function, this allows the two calls to communicate with each other. The application then waits for either party to hang up, using the channel.state() function on each channel.

    Code:

    """
        An outbound application that makes calls to two destination addresses 
        (passed in through outbound_parameters using the semi-colon as a 
        delimiter). 
    
        It prompts the first call to record a message and plays this to the 
        second call before connecting the two calls together. It then waits for 
        the calls to be hung up. 
    
        This application requires that call_from is supplied in 
        application_parameters and it requires one extra channel (this is 
        configured on the outbound service page of the CWP). 
    
        For information on placing outbound calls please read the online 
        web services documentation.
        
        For additional information regarding outbound PSTN calls, please see the 
        online documentation.
        
        Also have a look at the invoke_outbound_service sample code in the 
        samples_ws directory.
    
        Actions:
            - place an outbound call
            - record a message
            - place another outbound call
            - play the message to the outbound call
            - connect the two calls together
            - wait for someone to hang up
    
    """
    
    from prosody.uas import Hangup, Error, ICanRun
    import time
    
    __uas_version__  = "0.0.1"
    __uas_identify__ = "application"
    
    
    def _place_call(channel, destination, call_from):
            # Place an outbound call. If the destination is BUSY,
            # wait ten seconds and try again; try for one minute.
            endTime = time.time() + 60
    
            while channel.call(destination, call_from=call_from) != channel.State.ANSWERED:
                cause = channel.cause()
                if cause != channel.Cause.BUSY:
                    raise Error("Call destination returned cause {0}".format(cause))
                if time.time() > endTime:
                    raise Hangup("Call destination is busy.")
                time.sleep(10)
                continue
    
            
    def main(channel, application_instance_id, file_man, my_log, application_parameters, outbound_parameters):
        try:
            return_code = 0
            out_channel_2 = None
            # read the outbound args, we're expecting two destination_address with a ; as delimiter
            my_log.info("Out Args: {0}".format(outbound_parameters))
            
            out_arg_splits = outbound_parameters.split(';')
            try:
                outbound_destination_1 = out_arg_splits[0]
                outbound_destination_2 = out_arg_splits[1]
                # we expect the call_from details to be in application_parameters
                # this is used in CLI validation for PSTN calls
                call_from = application_parameters
            except:
                raise Error("Could not get outbound call destinations.")
            
            # get the extra channel
            try:
                out_channel_2 = channel.ExtraChannel[0]
            except:
                raise Error("You need to register an extra channel for this application")
    
            #place the first call
            _place_call(channel, outbound_destination_1, call_from)
            
            my_log.info("Placed first outbound call")
    
            # prompt the party to record a message, the prompt is played using TTS
            cause = channel.FilePlayer.say("<acu-engine name='Polly'><voice name='Brian'>Hello, please record a message after the beep.</voice></acu-engine>")
            if cause != channel.FilePlayer.Cause.NORMAL:
                raise Error("Say hello failed: cause is {0}".format(cause)) # log at error level
    
            # play a DTMF digit for the tone
            cause = channel.DTMFPlayer.play('#')
            if cause != channel.DTMFPlayer.Cause.NORMAL:
                raise Error("Play # failed: cause is {0}".format(cause))
            
            # record the message, record until we've had three seconds of silence
            cause = channel.FileRecorder.record('recorded_message_{0}.wav'.format(application_instance_id), milliseconds_max_silence=3000)
            if cause != channel.FileRecorder.Cause.SILENCE:
                raise Error("Record message failed: cause is {0}".format(cause)) # log at error level        
    
            # thanks for the recording
            cause = channel.FilePlayer.say("Thank you, please wait while I phone a friend.")
            if cause != channel.FilePlayer.Cause.NORMAL:
                raise Error("Say thank you failed: cause is {0}".format(cause)) # log at error level
            
            # place next call
            _place_call(out_channel_2, outbound_destination_2, call_from)
                
            # We have an outbound call, start playing the recording to the outbound call
            if out_channel_2.FilePlayer.start('recorded_message_{0}.wav'.format(application_instance_id)) is False:
                raise Error("Failed to start playing recording to outbound channel")
            
            # tell the inbound channel what we're doing
            cause = channel.FilePlayer.say("I am playing your message to your friend.")
            if cause != channel.FilePlayer.Cause.NORMAL:
                raise Error("Say playing to friend failed: cause is {0}".format(cause))
            
            # wait for message play to complete
            cause = out_channel_2.FilePlayer.wait_until_finished()
            if cause != out_channel_2.FilePlayer.Cause.NORMAL:
                raise Error("Wait for finished failed: cause is {0}".format(cause))
    
            # indicate to the far end that the message has finished playing
            cause = out_channel_2.DTMFPlayer.play('#')
            if cause != out_channel_2.DTMFPlayer.Cause.NORMAL:
                raise Error("DTMF play returned {0}: expected {1}".format(cause, out_channel_2.DTMFPlayer.Cause.NORMAL))
                
            # let the parties talk to each other
            if channel.connect(out_channel_2) is True:
                # wait until either call hangs up
                # wait on i_can_run to prevent an accidental infinite loop
                i_can_run = ICanRun(channel)
                while i_can_run:
                    # throw hangup exception on IDLE
                    channel.state(check_for_hangup=True)
                    out_channel_2.state(check_for_hangup=True)
                    time.sleep(1)
            else:
                raise Error('Connect channels failed')
                
        except Hangup as exc:
            my_log.info("Hangup exception reports: {0}".format(exc))
             # in this app a hangup is not an error, return a positive value
            return_code = 100
            
        except Error as exc:
            # for error conditions return a negative value
            my_log.error("Error exception reports: {0}".format(exc))
            return_code = -101
            
        except Exception as exc:
            # an unexpected exception, return a negative value
            my_log.exception("Unexpected exception reports: {0}".format(exc))
            return_code = -102
            
        finally:
            if channel is not None:
                if channel.state() != channel.State.IDLE:
                    channel.hang_up()
            if out_channel_2 is not None:
                if out_channel_2.state() != out_channel_2.State.IDLE:
                    out_channel_2.hang_up()
        return return_code
    
  • Filename:

    Samples\C#\OutboundConnect\OutboundConnect.cs

    Description:

    In this application we extract two call destination addresses from the outboundParameters argument using the String.Split() method and then ensure we have at least one extra channel available. This will allow us to make one outbound call on the primary channel (the channel argument) and one outbound call on an extra channel.

    If either of the destination addresses are PSTN numbers then the source address (caller Id) that is passed into the application via the applicationParameters argument must be set to a PSTN number that has been validated from the Caller Id page on cloud.aculab.com.

    We call the first destination address on the primary channel using the channel.Call() method and when answered, we use TTS to ask the callee to record a message that will ultimately be played to the second callee. We can record a message using the channel.FileRecorder.Start() method. This requires a filename as a parameter to identify where to store the recorded data. To play a message prompt, we use the channel.DTmfPlayer.Play() method. We wait for silence from the other end for a couple of seconds before ending the recording.

    We then call the second destination address on one of the extra channels and when answered, we play the previously recorded message to the second callee. Then we use TTS to notify both callees that they are being connected and use the Connect() method to connect both calls together bidirectionally. To wait for either caller to hangup, we use the channel.WaitForIdle() method.

    Code:

    using System;
    using System.Threading;
    using AMSClassLibrary;
    using UASAppAPI;
    
    // An outbound application that makes calls to two destination addresses (passed in).
    // It prompts the first call to record a message and plays this to the second call 
    // before tromboning the two calls together. It then waits for the calls to be hung up.
    //
    // The Caller Id (callFrom) that is to be used when calling out should be supplied in
    // the applicationsParameters field. For outgoing SIP calls this can be empty, but for
    // outgoing PSTN calls see the Outbound Calls documentation for your platform.
    //
    // Requires:
    // [outboundParameters = two destination addresses for the two outgoing calls, semicolon delimited]
    // [applicationParameters = an optional validated Caller Id]
    // [1 extra channels]
    //
    // e.g.
    // outboundParameters = "sip:bob@bobscompany.com;sip:brian@brianscompany.com"
    // applicationParameters = ""
    // or
    // outboundParameters = "441908081876;441908678180"
    // applicationParameters = "441908876543"
    //
    namespace OutboundConnect
    {
        // The application class.
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        public class OutboundConnect : UASOutboundApplication
        {
            // Possible return codes
            enum ReturnCode
            {
                // Success Codes:
                Success = 0,
                // ... any positive integer
    
                // Fail Codes:
                // -1 to -99 reserved
                ExceptionThrown = -100,
                ArgumentError = -101,
                NoCallerIdError = -102,
                NotSufficientExtraChannels = -103
            }
    
            // This is the entry point for the application
            public override int Run(UASCallChannel channel,
                                    string applicationParameters, // Caller Id (may be required for outgoing PSTN, optional for outgoing SIP)
                                    string outboundParameters)    // 2 x destinationAddresses, semicolon delimited...
            {
                this.Trace.TraceInfo("Start - appParms [{0}] outParms [{1}]",
                                   applicationParameters,
                                   outboundParameters);
                ReturnCode reply = ReturnCode.Success;
    
                UASCallChannel otherChannel = null;
                string recFileName = "recordings/introMessage";
    
                try
                {
                    // Typically the outboundParameters field is simply the destination address.
                    // However, in this case we require 2 destination addresses to be specified.
                    string[] destinationAddress = outboundParameters.Split(';');
                    if (destinationAddress.Length < 2)
                    {
                        reply = ReturnCode.ArgumentError;
                        this.Trace.TraceError("This app requires 2 destination addresses in the outboundParameters field");
                    }
    
                    // Check we've got an extra Channel
                    if (reply == ReturnCode.Success)
                    {
                        if (channel.ExtraChannels.Length < 1)
                        {
                            this.Trace.TraceError("This app requires at least 1 extra channel to be configured");
                            reply = ReturnCode.NotSufficientExtraChannels;
                        }
                    }
    
                    // Make the first call on the primary channel
                    if (reply == ReturnCode.Success)
                    {
                        string callFrom = applicationParameters;
                        CallState state = channel.Call(destinationAddress[0], callFrom);
                        if (state == CallState.Answered)
                        {
                            // Record an introduction message
                            channel.FilePlayer.Say("Hello." +
                                                   "Please record an introduction message for " +
                                                   destinationAddress[1] +
                                                   "after the tone." +
                                                   "Press any digit to stop the recording.");
    
                            Thread.Sleep(1000);
    
                            // Start recording, enabling barge in
                            channel.FileRecorder.Start(recFileName, true);
    
                            // Play a tone to signal that recording has started
                            channel.DtmfPlayer.Play("0");
    
                            // Wait for a period for recording to complete (10 seconds of silence) 
                            // or the call to have been hung up
                            FileRecorderCause recCause = channel.FileRecorder.WaitUntilFinished(60);
                            if (recCause == FileRecorderCause.Timeout)
                            {
                                channel.FileRecorder.Stop();
                            }
    
                            // And play it back
                            if (channel.State != CallState.Idle)
                            {
                                // Replay the recorded message
                                channel.FilePlayer.Say("The following message has been recorded");
                                channel.FilePlayer.Play(recFileName);
                            }
                        }
                    }
    
                    // Make the second call on the extra channel
                    if (reply == ReturnCode.Success)
                    {
                        channel.FilePlayer.Say("Please wait while phoning contact.");
    
                        string callFrom = applicationParameters;
    
                        otherChannel = channel.ExtraChannels[0];
                        if (otherChannel.Call(destinationAddress[1], callFrom) == CallState.Answered)
                        {
                            // Play the introductory message to other call
                            otherChannel.FilePlayer.Play(recFileName);
    
                            // Connect the calls together
                            channel.FilePlayer.Say("Connecting call");
                            otherChannel.FilePlayer.Say("Connecting call");
                            channel.Connect(otherChannel);
                        }
    
                        // Wait for hang up
                        channel.WaitForIdle(Timeout.Infinite);
                    }
                }
                catch (Exception e)
                {
                    this.Trace.TraceError("Exception thrown {0}", e.Message);
                    reply = ReturnCode.ExceptionThrown;
                }
                finally
                {
                    channel.HangUp();
                    if (otherChannel != null)
                    {
                        otherChannel.HangUp();
                    }
                }
    
                this.Trace.TraceInfo("Completed");
                return (int)reply;
            }
        }
    }
  • Filename:

    Samples\VB\OutboundConnect\OutboundConnect.vb

    Description:

    In this application we extract two call destination addresses from the outboundParameters argument using the String.Split() method and then ensure we have at least one extra channel available. This will allow us to make one outbound call on the primary channel (the channel argument) and one outbound call on an extra channel.

    If either of the destination addresses are PSTN numbers then the source address (caller Id) that is passed into the application via the applicationParameters argument must be set to a PSTN number that has been validated from the Caller Id page on cloud.aculab.com.

    We call the first destination address on the primary channel using the channel.Call() method and when answered, we use TTS to ask the callee to record a message that will ultimately be played to the second callee. We can record a message using the channel.FileRecorder.Start() method. This requires a filename as a parameter to identify where to store the recorded data. To play a message prompt, we use the channel.DTmfPlayer.Play() method. We wait for silence from the other end for a couple of seconds before ending the recording.

    We then call the second destination address on one of the extra channels and when answered, we play the previously recorded message to the second callee. Then we use TTS to notify both callees that they are being connected and use the Connect() method to connect both calls together bidirectionally. To wait for either caller to hangup, we use the channel.WaitForIdle() method.

    Code:

    Imports AMSClassLibrary
    Imports UASAppAPI
    
    ' An outbound application that makes calls to two destination addresses (passed in).
    ' It prompts the first call to record a message and plays this to the second call 
    ' before tromboning the two calls together. It then waits for the calls to be hung up.
    '
    ' The Caller Id (callFrom) that is to be used when calling out should be supplied in
    ' the applicationsParameters field. For outgoing SIP calls this can be empty, but for
    ' outgoing PSTN calls see the Outbound Calls documentation for your platform.
    '
    ' Requires:
    ' [outboundParameters = two destination addresses for the two outgoing calls, semicolon delimited]
    ' [applicationParameters = a validated Caller Id]
    ' [1 extra channels]
    '
    ' e.g.
    ' outboundParameters = "sip:bob@bobscompany.com;sip:brian@brianscompany.com"
    ' applicationParameters = ""
    ' or
    ' outboundParameters = "441908081876;441908678180"
    ' applicationParameters = "441908876543"
    '
    Namespace OutboundConnect
    
        ' The application class.
        ' This must have the same name as the assembly and must inherit from either 
        ' UASInboundApplication or UASOutboundApplication.
        ' It must override the Run method.
        Public Class OutboundConnect
            Inherits UASOutboundApplication
    
            ' Possible return codes
            Enum ReturnCode
                ' Success Codes:
                Success = 0
                ' ... any positive integer
    
                ' Fail Codes:
                ' -1 to -99 reserved
                ExceptionThrown = -100
                ArgumentError = -101
                NoCallerIdError = -102
                NotSufficientExtraChannels = -103
            End Enum
    
            ' This is the entry point for the application
            ' applicationParameters - Caller Id (required for outgoing PSTN, optional for outgoing SIP)
            ' outboundParameters -    2 x destinationAddresses, semicolon delimited
            Overrides Function Run(ByVal channel As UASCallChannel, _
                                   ByVal applicationParameters As String, _
                                   ByVal outboundParameters As String) _
                                   As Integer
    
                Me.Trace.TraceInfo("Start - appParms [{0}] outParms [{1}]", _
                                   applicationParameters, _
                                   outboundParameters)
                Dim reply As ReturnCode = ReturnCode.Success
    
                Dim otherChannel As UASCallChannel = Nothing
                Dim recFileName = "recordings/introMessage"
    
                Try
                    ' Typically the outboundParameters field is simply the destination address.
                    ' However, in this case we require 2 destination addresses to be specified.
                    Dim destinationAddress = outboundParameters.Split(";")
                    If destinationAddress.Length < 2 Then
                        reply = ReturnCode.ArgumentError
                        Me.Trace.TraceError("This app requires 2 destination addresses in the outboundParameters field")
                    End If
    
                    ' Check we've got an extra Channel
                    If reply = ReturnCode.Success Then
                        If channel.ExtraChannels.Length < 1 Then
                            Me.Trace.TraceError("This app requires at least 1 extra channel to be configured")
                            reply = ReturnCode.NotSufficientExtraChannels
                        End If
                    End If
    
                    ' Check we've got a Caller Id supplied if either of these calls are PSTN
                    If reply = ReturnCode.Success Then
                        If Not (destinationAddress(0).Contains("@") And destinationAddress(1).Contains("@")) Then
                            ' At least one address is a PSTN number
                            If String.IsNullOrEmpty(applicationParameters) Then
                                Me.Trace.TraceError("This app requires a validated CallerId in the applicationParameters" + _
                                                    "if any PSTN calls are to be made")
                                reply = ReturnCode.NoCallerIdError
                            End If
                        End If
                    End If
    
                    ' Make the first call on the primary channel
                    If reply = ReturnCode.Success Then
                        Dim callFrom = applicationParameters
                        Dim state = channel.Call(destinationAddress(0), callFrom)
                        If state = CallState.Answered Then
                            ' Record an introduction message
                            channel.FilePlayer.Say("Hello." + _
                                                   "Please record an introduction message for " + _
                                                   destinationAddress(1) + _
                                                   "after the tone." + _
                                                   "Press any digit to stop the recording.")
    
                            Thread.Sleep(1000)
    
                            ' Start recording, enabling barge in
                            channel.FileRecorder.Start(recFileName, True)
    
                            ' Play a tone to signal that recording has started
                            channel.DtmfPlayer.Play("0")
    
                            ' Wait for a period for recording to complete or 
                            ' the call to have been hung up
                            Dim recCause = channel.FileRecorder.WaitUntilFinished(30)
                            If recCause = FileRecorderCause.Timeout Then
                                channel.FileRecorder.Stop()
                            End If
    
                            ' And play it back
                            If channel.State <> CallState.Idle Then
                                ' Replay the recorded message
                                channel.FilePlayer.Say("The following message has been recorded")
                                channel.FilePlayer.Play(recFileName)
                            End If
                        End If
                    End If
    
                    ' Make the second call on the extra channel
                    If reply = ReturnCode.Success Then
                        channel.FilePlayer.Say("Please wait while phoning contact.")
    
                        Dim callFrom = applicationParameters
    
                        otherChannel = channel.ExtraChannels(0)
                        If otherChannel.Call(destinationAddress(1), callFrom) = CallState.Answered Then
                            ' Play the introductory message to other call
                            otherChannel.FilePlayer.Play(recFileName)
    
                            ' Connect the calls together
                            channel.FilePlayer.Say("Connecting call")
                            otherChannel.FilePlayer.Say("Connecting call")
                            channel.Connect(otherChannel)
                        End If
    
                        ' Wait for hang up
                        channel.WaitForIdle(Timeout.Infinite)
                    End If
    
                Catch ex As Exception
                    Me.Trace.TraceError("Exception thrown {0}", ex.Message)
                    reply = ReturnCode.ExceptionThrown
                Finally
                    channel.HangUp()
                End Try
    
                Me.Trace.TraceInfo("Completed")
                Return reply
    
            End Function
    
        End Class
    
    End Namespace
  • Filename:

    Samples\F#\OutboundConnect\OutboundConnect.fs

    Description:

    In this application we first ensure we have at least one extra channel available. Then we extract two call destination addresses from the outboundParameters argument using the String.Split() method. This will allow us to make one outbound call on the primary channel (the channel argument) and one outbound call on an extra channel.

    If either of the destination addresses are PSTN numbers then the source address (caller Id) that is passed into the application via the applicationParameters argument must be set to a PSTN number that has been validated from the Caller Id page on cloud.aculab.com. You can set this in the Application Parameters field of the Outbound Service that runs this application. In the application this is checked using the recursive member function ContainsPSTNAddress().

    We call the first destination address on the primary channel using the channel.Call() method and when answered, we use TTS to ask the callee to record a message that will ultimately be played to the second callee. We can record a message using the channel.FileRecorder.Start() method. This requires a filename as a parameter to identify where to store the recorded data. To play a message prompt, we use the channel.DTmfPlayer.Play() method. We wait for silence from the other end for a couple of seconds before ending the recording.

    We then call the second destination address on one of the extra channels and when answered, we play the previously recorded message to the second callee. Then we use TTS to notify both callees that they are being connected and use the Connect() method to connect both calls together bidirectionally. To wait for either caller to hangup, we use the channel.WaitForIdle() method.

    Code:

    // An outbound application that makes calls to two destination addresses (passed in).
    // It prompts the first call to record a message and plays this to the second call 
    // before tromboning the two calls together. It then waits for the calls to be hung up.
    //
    // The Caller Id (callFrom) that is to be used when calling out should be supplied in
    // the applicationsParameters field. For outgoing SIP calls this can be empty, but for
    // outgoing PSTN calls see the Outbound Calls documentation for your platform.
    //
    // Requires:
    // [outboundParameters = two destination addresses for the two outgoing calls, semicolon delimited]
    // [applicationParameters = a validated Caller Id]
    // [1 extra channels]
    namespace OutboundConnect
    
        open System
        open System.Threading
        open AMSClassLibrary
        open UASAppAPI
    
        // Possible return codes
        type ReturnCode =
            // Success Codes:
            | Success = 0
            // ... any positive integer
    
            // Fail Codes:
            // -1 to -99 reserved
            | ExceptionThrown = -100
            | ArgumentError = -101
            | NoCallerIdError = -102
            | NotSufficientExtraChannels = -103
    
        // The application class.
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        type OutboundConnect() = 
            inherit UASOutboundApplication()
    
            // This is the entry point for the application
            override obj.Run(channel:UASCallChannel, applicationParameters:string, outboundParameters:string) : int = 
                
                obj.Trace.TraceInfo("Started")
                let mutable reply = ReturnCode.Success
    
                // Check we've got an extra Channel
                if channel.ExtraChannels.Length < 1 then
                    obj.Trace.TraceError("This app requires at least 1 extra channel to be configured")
                    int ReturnCode.NotSufficientExtraChannels
                else 
                    let otherChannel : UASCallChannel = channel.ExtraChannels.[0]
                    let recFileName = "recordings/introMessage"
    
                    try
                        try
                            // Typically the outboundParameters field is simply the destination address.
                            // However, in this case we require 2 destination addresses to be specified.
                            let destinationAddresses = outboundParameters.Split(';')
                            if destinationAddresses.Length < 2 then
                                reply <- ReturnCode.ArgumentError
                                obj.Trace.TraceError("This app requires 2 destination addresses in the outboundParameters field")
    
                            // Check we've got a Caller Id supplied if either of these calls are PSTN
                            if reply = ReturnCode.Success then
                                if obj.ContainsPSTNAddress(destinationAddresses) then
                                    // At least one address is a PSTN number
                                    if String.IsNullOrEmpty(applicationParameters) then
                                        obj.Trace.TraceError("This app requires a validated CallerId in the applicationParameters" +
                                                              "if any PSTN calls are to be made")
                                        reply <- ReturnCode.NoCallerIdError
                    
                            // Make the first call on the primary channel
                            if reply = ReturnCode.Success then
                                let callFrom = applicationParameters
    
                                let state = channel.Call(destinationAddresses.[0], callFrom)
                                if state = CallState.Answered then
                                    // Record an introduction message
                                    channel.FilePlayer.Say("Hello." +
                                                           "Please record an introduction message for " +
                                                           destinationAddresses.[1] +
                                                           "after the tone." +
                                                           "Press any digit to stop the recording.") |> ignore
    
                                    Thread.Sleep(1000)
    
                                    // Start recording, enabling barge in
                                    channel.FileRecorder.Start(recFileName, true) |> ignore
    
                                    // Play a tone to signal that recording has started
                                    channel.DtmfPlayer.Play("0") |> ignore
    
                                    // Wait for a period for recording to complete or 
                                    // the call to have been hung up
                                    let recCause = channel.FileRecorder.WaitUntilFinished(30)
                                    if recCause = FileRecorderCause.Timeout then
                                        channel.FileRecorder.Stop() |> ignore
    
                                    // And play it back
                                    if channel.State <> CallState.Idle then
                                        // Replay the recorded message
                                        channel.FilePlayer.Say("The following message has been recorded") |> ignore
                                        channel.FilePlayer.Play(recFileName) |> ignore
    
                            // Make the second call on the extra channel
                            if reply = ReturnCode.Success then
                                channel.FilePlayer.Say("Please wait while phoning contact.") |> ignore
    
                                let callFrom = applicationParameters
    
                                if otherChannel.Call(destinationAddresses.[1], callFrom) = CallState.Answered then
    
                                    // Play the introductory message to other call
                                    otherChannel.FilePlayer.Play(recFileName) |> ignore
    
                                    // Connect the calls together
                                    channel.FilePlayer.Say("Connecting call") |> ignore
                                    otherChannel.FilePlayer.Say("Connecting call") |> ignore
                                    channel.Connect(otherChannel) |> ignore
    
                                // Wait for hang up
                                channel.WaitForIdle(Timeout.Infinite) |> ignore
                        with
                            | _ as e->
                                obj.Trace.TraceError("Exception thrown {0}", e.Message)
                                reply <- ReturnCode.ExceptionThrown
                    finally
                        channel.HangUp() |> ignore
                        if otherChannel <> null then
                            otherChannel.HangUp() |> ignore
                    
                    obj.Trace.TraceInfo("Completed")
                    int reply
    
            // Check whether an array of addresses contains a PSTN address
            member obj.ContainsPSTNAddress (addresses : string[]) =
                let rec IsPSTNAddress(addresses : string[], index : int) : bool =
                    if index < addresses.Length then
                        false 
                    elif addresses.[index].Contains("@") then
                        true
                    else
                        IsPSTNAddress(addresses, index + 1)
                IsPSTNAddress(addresses, 0)
    

Cloud UAS Sample Pin Input

UAS API - Pin Input Sample Application

  • Filename:

    samples/pin_input.py

    Description:

    An inbound application that prompts the caller to enter a 4 digit pin. After ringing and answering an inbound call, the application uses TTS to ask for a four digit PIN using channel.FilePlayer.say(). The channel.DTMFDectector.get_digits() function is used to collect the DTMF digits. The count argument indicates the number of digits to collect, and the seconds_predigits_timeout argument specifies how long to wait for the first key press before timing out.

    The DTMF detector return cause is checked by using the channel.DTMFDetector.cause() function. In this case, if the correct number of digits were entered, TTS is use to play back the digits that were collected; otherwise an error message is spoken.

    Code:

    """
        An inbound application that prompts the caller to enter a 4 digit pin. 
        It waits at most 30 seconds for the caller to begin entering digits, then replays 
        the digits to the caller before hanging up.
    """
    
    from prosody.uas import Hangup, Error
    
    __uas_identify__ = "application"
    __uas_version__  = "1.0b2"
    
    def main(channel, application_instance_id, file_man, my_log, application_parameters):
        return_code = 0
        try:
            if channel.state() == channel.State.CALL_INCOMING:
                channel.ring()   # this can raise a Hangup exception
                channel.answer() # this can raise a Hangup exception
            else:
                raise Hangup('No inbound call')
    
            channel.FilePlayer.say("Please enter a four digit pin.", barge_in = True)
    
            # wait at most 30 seconds for the caller to begin entering digits
            digits = channel.DTMFDetector.get_digits(count=4, seconds_predigits_timeout = 30)
    
            if channel.DTMFDetector.cause() == channel.DTMFDetector.Cause.COUNT:
                channel.FilePlayer.say("The digits you entered are, {0}".format(", ".join(digits)))
            else:
                channel.FilePlayer.say ("No digits received. Hanging up.")
                return_code = -103
    
        except Hangup as exc:
            my_log.info("Got Hangup: {0}".format(exc))
            return_code = -100
    
        except Error as exc:
            my_log.error("Got Error: {0}".format(exc))
            return_code = -101
    
        except Exception as exc:
            my_log.exception("Got unexpected exception: {0}".format(exc))
            return_code = -102
    
        finally:
            if channel.state() != channel.State.IDLE:
                channel.hang_up()
        return return_code
    
  • Filename:

    Samples\C#\PinInput\PinInput.cs

    Description:

    Once the call is answered with channel.Answer(), we use TTS to prompt for a four digit PIN code. The channel.DtmfDetector can obtain the digits entered by the caller for us, using the GetDigits() method. The specific overload used requires the expected number of digits, an output string in which the resultant digits are stored and a timeout value of 30 seconds. The method returns a cause value indicating why the method returned. The DtmfDetectorCause.Count cause signifies that the expected count of digits were detected.

    The code then responds to the caller with the digits entered. Note that the text has some formatting to ensure that TTS reads it in a natural manner. The call is then disconnected using the channel.HangUp() method.

    Code:

    using System;
    using System.Threading;
    using AMSClassLibrary;
    using UASAppAPI;
    
    // An inbound application that answers a call, prompts for the caller to 
    // enter a 4 digit pin code. It waits for 30 seconds for 4 digits to be entered 
    // and then replays them to the caller before hanging up.
    namespace PinInput
    {
        // The application class.
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        public class PinInput : UASInboundApplication
        {
            // Possible return codes
            enum ReturnCode
            {
                // Success Codes:
                Success = 0,
                // ... any positive integer
    
                // Fail Codes:
                // -1 to -99 reserved
                ExceptionThrown = -100
            }
    
            // This is the entry point for the application
            public override int Run(UASCallChannel channel,
                                    string applicationParameters)
            {
                this.Trace.TraceInfo("Started");
                ReturnCode reply = ReturnCode.Success;
    
                try
                {
                    // Answer the call
                    CallState state = channel.Answer();
                    if (state == CallState.Answered)
                    {
                        // Prompt to enter a pin, allowing bargein
                        channel.FilePlayer.Say("Please enter a four digit pin code.", true);
    
                        // Wait for 30 seconds for four digits
                        string digits;
                        DtmfDetectorCause cause = channel.DtmfDetector.GetDigits(4, out digits, 30);
                        if (cause == DtmfDetectorCause.Count)
                        {
                            channel.FilePlayer.Say(
                        		"The pin code you entered was <say-as interpret-as='vxml:digits'>{0}</say-as>",
                        		digits);
                        }
    
                        channel.FilePlayer.Say("Goodbye.");
                    }
                }
                catch (Exception e)
                {
                    this.Trace.TraceError("Exception thrown {0}", e.Message);
                    reply = ReturnCode.ExceptionThrown;
                }
                finally
                {
                    channel.HangUp();
                }
    
                this.Trace.TraceInfo("Completed");
                return (int)reply;
            }
        }
    }
  • Filename:

    Samples\VB\PinInput\PinInput.vb

    Description:

    Once the call is answered with channel.Answer(), we use TTS to prompt for a four digit PIN code. The channel.DtmfDetector can obtain the digits entered by the caller for us, using the GetDigits() method. The specific overload used requires the expected number of digits, an output string in which the resultant digits are stored and a timeout value of 30 seconds. The method returns a cause value indicating why the method returned. The DtmfDetectorCause.Count cause signifies that the expected count of digits were detected.

    The code then responds to the caller with the digits entered. Note that the text has some formatting to ensure that TTS reads it in a natural manner. The call is then disconnected using the channel.HangUp() method.

    Code:

    Imports AMSClassLibrary
    Imports UASAppAPI
    
    ' An inbound application that answers a call, prompts for the caller to 
    ' enter a 4 digit pin code. It waits for 30 seconds for 4 digits to be entered 
    ' and then replays them to the caller before hanging up.
    Namespace PinInput
    
        ' The application class.
        ' This must have the same name as the assembly and must inherit from either 
        ' UASInboundApplication or UASOutboundApplication.
        ' It must override the Run method.
        Public Class PinInput
            Inherits UASInboundApplication
    
            ' Possible return codes
            Enum ReturnCode
                ' Success Codes:
                Success = 0
                ' ... any positive integer
    
                ' Fail Codes:
                ' -1 to -99 reserved
                ExceptionThrown = -100
            End Enum
    
            ' This is the entry point for the application
            Overrides Function Run(ByVal channel As UASCallChannel, _
                                   ByVal applicationParameters As String) _
                                   As Integer
    
                Me.Trace.TraceInfo("Started")
                Dim reply As ReturnCode = ReturnCode.Success
    
                Try
                    ' Answer the call
                    Dim state As CallState
                    state = channel.Answer()
    
                    If state = CallState.Answered Then
    
                        ' Prompt to enter a pin
                        channel.FilePlayer.Say("Please enter a four digit pin code.")
    
                        ' Wait for 30 seconds for four digits
                        Dim digits As String = ""
                        Dim cause = channel.DtmfDetector.GetDigits(4, digits, 30)
                        If cause = DtmfDetectorCause.Count Then
                            channel.FilePlayer.Say("The pin code you entered was {0}, {1}, {2}, {3}", _
                                digits(0), _
                                digits(1), _
                                digits(2), _
                                digits(3))
                        End If
    
                        channel.FilePlayer.Say("Goodbye.")
                    End If
                Catch ex As Exception
                    Me.Trace.TraceError("Exception thrown {0}", ex.Message)
                    reply = ReturnCode.ExceptionThrown
                Finally
                    channel.HangUp()
                End Try
    
                Me.Trace.TraceInfo("Completed")
                Return reply
    
            End Function
    
        End Class
    
    End Namespace
  • Filename:

    Samples\F#\PinInput\PinInput.fs

    Description:

    Once the call is answered with channel.Answer(), we use TTS to prompt for a four digit PIN code. The channel.DtmfDetector obtain the digits entered by the caller for us, using the GetDigits() method. The specific overload used requires the expected number of digits, an output string in which the resultant digits are stored and a timeout value of 30 seconds. The method returns a cause value indicating why the method returned. The DtmfDetectorCause.Count cause signifies that the expected count of digits were detected.

    The code then responds to the caller with the digits entered. Note that the text has some formatting to ensure that TTS reads it in a natural manner. The call is then disconnected using the channel.HangUp() method.

    Code:

    // An inbound application that answers a call, prompts for the caller to 
    // enter a 4 digit pin code. It waits for 30 seconds for 4 digits to be entered 
    // and then replays them to the caller before hanging up.
    namespace PinInput
    
        open System
        open System.Threading
        open AMSClassLibrary
        open UASAppAPI
    
        // Possible return codes
        type ReturnCode =
            // Success Codes:
            | Success = 0
            // ... any positive integer
    
            // Fail Codes:
            // -1 to -99 reserved
            | ExceptionThrown = -100
    
        // The application class.
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        type PinInput() = 
            inherit UASInboundApplication()
    
            // This is the entry point for the application
            override obj.Run(channel:UASCallChannel, applicationParameters:string) : int = 
                
                obj.Trace.TraceInfo("Started")
                let mutable reply = ReturnCode.Success
    
                try
                    // Answer the call
                    if channel.Answer() = CallState.Answered then
    
                        // Prompt to enter a pin
                        channel.FilePlayer.Say("Please enter a four digit pin code.") |> ignore
    
                        // Wait for 30 seconds for four digits
                        let mutable digits = ""
                        let cause = channel.DtmfDetector.GetDigits(4, &digits, 30)
                        match cause with
                            | DtmfDetectorCause.Count -> 
                                match digits.Length with
                                    | 0 -> 
                                        channel.FilePlayer.Say("Pin empty.") |> ignore
                                    | _ ->
                                        channel.FilePlayer.Say("The pin code you entered was {0}, {1}, {2}, {3}", digits.Chars(0), digits.Chars(1), digits.Chars(2), digits.Chars(3)) |> ignore
                            | _ -> 
                                channel.FilePlayer.Say("Pin Not entered.") |> ignore
    
                        channel.FilePlayer.Say("Goodbye.") |> ignore
                with 
                    | _ as e -> 
                        obj.Trace.TraceError("Exception thrown {0}", e.Message)
                        reply <- ReturnCode.ExceptionThrown
                    
                obj.Trace.TraceInfo("Completed")
                (int)reply
                

Cloud UAS Sample Transfer Menu

UAS API - Transfer Menu Sample Application

  • Filename:

    samples/transfer_menu.py

    Description:

    An inbound application that prompts the user to select a target to be transfered to. The target names (to be read out using TTS) and addresses (to be transfered to using the channel API) are given in application_parameters which is configured on the Inbound Services page. The target addresses must be other inbound services that have been registered on the Inbound Services page.

    This example requires that application_parameters is a semi-colon delimited list in the format: <target name>,<target address>;<target name>,<target address> for example: join a conference,sip:AddToConfService@sip-0-2-0.aculab.com;listen to music,sip:InBoundMusic@sip-0-2-0.aculab.com This application requires one extra channel.

    The application rings and answers the call, it then tries to get the extra channel. It then splits up the information in application_arguments to generate the transfer menu list. The application then uses TTS to prompt the caller for a menu choice. Finally, it uses the channel.transfer_to_inbound_service() function to transfer the caller to another inbound service. This function requires a reference to an extra channel.

    The get_menu_selection() function has a loop which says each item in the transfer menu list, and then waits for a valid DTMF digit (one which corresponds to a transfer option). The transfer name and destination are returned by the function.

    Code:

    __uas_identify__ = "application"
    __uas_version__ = "1.0b1"
    
    from prosody.uas import Hangup, Error, PlayableMedia
    from prosody.uas.highlevel import HighLevelCallChannel, HighLevelGrammar, HighLevelDigitInputOptions
    
    """
        An inbound application that prompts the user to select a target to be transferred to. 
        
        The target names and addresses - or phone numbers - are provided in application_parameters.
        These are set, during service registration, on the inbound service registration page at cloud.aculab.com.    
    
        The application_parameters must be a delimited string in the format: <name>, <address>; <name>, <address>
        
        For example:
        "Fred,sip:fred@place.com;Jack,sip:jack@place.com"
    
        The target names are used to create an automatic speech recognition (ASR) grammar.
        ASR is used to get the caller's choice and the call is then connected to the target address.
        
        A digit is associated with each name, and this can be entered on the telephone keypad instead of speaking.
    
        At application start, the target names are read out along with the associated digit.
    
        This application requires 1 extra channel.
        
        Actions:
            - wait for an inbound call
            - generate the transfer options menu
            - speak the options using TTS
            - listen for the caller's selection using ASR and DTMF
            - transfer the call
    
    """
    
    def transfer_menu(application_parameters, my_log):
        # Split the application_parameters up into transfer options
        # (split with semicolon), and then again with commas. Return the 
        # data as a dictionary
    
        try:
            return dict(tuple(a.split(',')) for a in application_parameters.split(';'))
        except Exceptionas exc:
             my_log.error("The application parameters could not be parsed correctly: {0}".format(exc))
        return {}
    
    
    def get_menu_selection(channel, transfer_list, my_log):
    
        channel.DTMFDetector.clear_digits()
        my_log.info("transfer_list: {0}".format(transfer_list))
        
        # create a speech recognition grammar of the IVR options
        my_grammar = HighLevelGrammar()
        my_grammar.create_from_alternatives(*transfer_list.keys())
        
        valid_digits = range(len(transfer_list))
        my_digit_options = HighLevelDigitInputOptions(valid_digits=''.join(map(str, valid_digits)))
    
        prompt_text = 'Please say the name of the person you want to call. Or press '
        for digit in valid_digits:
            # associate digits with the names
            prompt_text = prompt_text + "{0} for {1}, ".format(digit, transfer_list.keys()[digit])
    
        prompt = PlayableMedia(text_to_say=prompt_text, channel=channel)
        response = channel.capture_input(prompt, speech_recognition_grammar=my_grammar, 
                                      digit_input_options=my_digit_options)
        # if response is None, no valid input was detected
        if response is not None:
            # check whether we got speech or digits
            if response.type == response.Type.SPEECH:
                # return the name
                return response.input
            else:
                # return the name associated with the digit
                return transfer_list.keys()[int(response.input)]
        return None
    
    
    def main(channel, application_instance_id, file_man, my_log, application_parameters):
        my_log.info("Transfer menu started")
        return_code = 0
        try:
            channel.ring(1)
            channel.answer()
            my_log.info("Call answered")
    
            # in this application, we will using the high level API wrapper
            # for the channel object
            high_level_channel = HighLevelCallChannel(channel, my_log)        
            try:
                # an extra channel is required, the number of extra channels
                # available is set on the service page
                out_channel = channel.ExtraChannel[0]
            except:
                raise Error("You need to register an extra channel for this application.")
    
            # Convert the application_parameters into a transfer menu list for later use
            transfer_list = transfer_menu(application_parameters)
            if not transfer_list:
                raise Error("Invalid transfer menu")
            
            # Prompt for digit
            channel.FilePlayer.say("Hello. ")
            target = get_menu_selection(high_level_channel, transfer_list, my_log)
    
            if not target:
                channel.FilePlayer.say("There is nobody to call.")
            else:
                # we will use the high level channel to place an outbound call and connect
                # the inbound and outbound calls together. If the target is a PSTN call
                # you will have to supply a call_from as well - please see the online documentation
                # on placing outbound PSTN calls.
                print("Calling {0}".format(target))
                if high_level_channel.call_and_connect(out_channel, call_to=transfer_list[target]) is False:
                    channel.FilePlayer.say("I wasn't able to transfer you. Please try again later.")
                    channel.hang_up()
                
            channel.wait_for_idle()
    
        except Hangup as exc:
            my_log.info("Got Hangup")
            return_code = 100
    
        except Error as exc:
            my_log.error("Got Error: {0}".format(exc))
            return_code = -101
    
        except Exception as exc:
            my_log.exception("Got unexpected exception: {0}".format(exc))
            return_code = -102
    
        finally:
            if channel.state() != channel.State.IDLE:
                channel.hang_up()
        return return_code
    
  • Filename:

    Samples\C#\TransferMenu\TransferMenu.cs

    Description:

    This application first checks to ensure that the Inbound Service that invoked this application has allocated sufficient extra channels, by inspecting the channel.ExtraChannels array. Extra channels are required to make outbound calls in an inbound application and can be configured in the Inbound Service configuration. Once the check has been made, the application splits the applicationParameters into an array for further use.

    The call is answered, a small TTS message is sent to the user and then the GetMenuSelection() method is called. This method will prompt the user for a DTMF tone after giving a list of the transfer options. We use the channel.DtmfDetector.GetDigits() method to grab a single keypad press and then make sure the returned item is in our list of transfer options. This loop will continue until either a valid keypress has been detected, or the user hangs up.

    To transfer the call, we use the channel.TransferToInboundService() method. We specify the target address and the extra channel to use for the transfer. The function returns a boolean value indicating if the transfer attempt was successful. This transfer method uses the retrievable transfer mechanism and therefore we must maintain the state of the original channel to allow the transferred call to continue. So we wait for the transferred call to be hung up before terminating.

    Code:

    using System;
    using System.Threading;
    using System.Collections.Generic;
    using AMSClassLibrary;
    using UASAppAPI;
    
    // An inbound application that prompts the user to select a target inbound service 
    // to be transferred to. A prompt (to be read out) and service name (to be transferred to) 
    // for each possible target need to be listed in the applicationParameters when
    // this service is registered.
    //
    // Note: this sample will only run on platforms that support Transfer.
    //
    // Requires:
    // [applicationParameters = semicolon delimited list of <action>,<service name<
    //      e.g. "join a conference,AddToConference;
    //            listen to media file,InboundPlayWav"]
    // [1 extra channel]
    namespace TransferMenu
    {
        // The application class.join a 
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        public class TransferMenu : UASInboundApplication
        {
            // Possible return codes
            enum ReturnCode
            {
                // Success Codes:
                Success = 0,
                // ... any positive integer
    
                // Fail Codes:
                // -1 to -99 reserved
                ExceptionThrown = -100,
                NotSufficientExtraChannels = -101,
                NotSufficientDestinations = -102
            }
    
            // A class to represent each of the menu options
            class TransferTarget
            {
                public TransferTarget(string entry, int key)
                {
                    string[] details = entry.Split(',');
                    if (details.Length != 2)
                    {
                        throw new ArgumentException("Invalid destination details", "applicationParameters");
                    }
                    Prompt = details[0].Trim();
                    ServiceName = details[1].Trim();
                    Key = key;
                }
                public string Prompt;
                public string ServiceName;
                public int Key;
            }
    
            // This is the entry point for the application
            public override int Run(UASCallChannel channel,
                                    string applicationParameters)
            {
                this.Trace.TraceInfo("Started");
                ReturnCode reply = ReturnCode.Success;
                bool primaryCallHungUp = false;
    
                // Check we've got an extra Channel
                if (channel.ExtraChannels.Length < 1)
                {
                    this.Trace.TraceWarning("Needs 1 extra channel to be configured");
                    return (int)ReturnCode.NotSufficientExtraChannels;
                }
                UASCallChannel targetChannel = channel.ExtraChannels[0];
    
                try
                {
                    // Decipher the applicationParameters
                    string[] entries = applicationParameters.Split(';');
                    if (entries.Length < 1)
                    {
                        this.Trace.TraceWarning("Needs at least 1 transfer target to be configured");
                        return (int)ReturnCode.NotSufficientDestinations;
                    }
                    List<TransferTarget> targets = new List<TransferTarget>(entries.Length);
                    int key = 0;
                    foreach (string entry in entries)
                    {
                        targets.Add(new TransferTarget(entry, key++));
                    }
    
                    // The selected target
                    TransferTarget target = null;
    
                    // Answer the call
                    CallState state = channel.Answer();
                    if (state != CallState.Answered)
                    {
                        primaryCallHungUp = true;
                    }
    
                    if (!primaryCallHungUp)
                    {
                        this.Trace.TraceInfo("Call answered");
    
                        // Prompt for a digit
                        channel.FilePlayer.Say("Hello.");
                        target = getMenuSelection(channel, targets);
                        if (target == null)
                        {
                            primaryCallHungUp = true;
                        }
                    }
    
                    if (!primaryCallHungUp)
                    {
                        // Transfer to that target
                        channel.FilePlayer.Say("Transferring to {0}", target.Prompt);
                        state = channel.TransferToInboundService(
                                                    target.ServiceName,
                                                    targetChannel);
    
                        if (state != CallState.Transferred)
                        {
                            channel.FilePlayer.Say("I wasn't able to transfer you.");
                            channel.FilePlayer.Say("Please try again later.");
                        }
                        else
                        {
                            // Wait for transferree or far end to hangup 
                            channel.WaitForTransferredCallRetrieved(Timeout.Infinite);
                        }
                    }
                }
                catch (Exception e)
                {
                    this.Trace.TraceError("Exception thrown {0}", e.Message);
                    reply = ReturnCode.ExceptionThrown;
                }
                finally
                {
                    channel.HangUp();
                }
    
                this.Trace.TraceInfo("Completed");
                return (int)reply;
            }
    
            TransferTarget getMenuSelection(UASCallChannel channel, List<TransferTarget> targets)
            {
                // Prepare to receive digits
                channel.DtmfDetector.ClearDigits();
    
                // Get the target selected
                do
                {
                    // Play the transfer options to the caller with bargein
                    foreach (TransferTarget target in targets)
                    {
                        string msg = string.Format("Press {0} to {1}", target.Key, target.Prompt);
                        FilePlayerCause cause = channel.FilePlayer.Say(msg, true);
                        if (cause == FilePlayerCause.HangUp)
                        {
                            return null;
                        }
                        if (cause == FilePlayerCause.BargeIn)
                        {
                            break;
                        }
                    }
    
                    string digits;
                    channel.DtmfDetector.GetDigits(1, out digits, 10);
                    if (channel.DtmfDetector.Cause == DtmfDetectorCause.Count)
                    {
                        // Get the transfer target
                        int keyPressed = Convert.ToInt32(digits);
                        this.Trace.TraceInfo("Got keypress {0}", keyPressed);
                        if (keyPressed < targets.Count)
                        {
                            return targets[keyPressed];
                        }
                        channel.FilePlayer.Say("Selection not valid.");
                    }
                } while (channel.DtmfDetector.Cause != DtmfDetectorCause.HangUp);
    
                // returning null on hangup
                return null;
            }
        }
    }
  • Filename:

    Samples\VB\TransferMenu\TransferMenu.vb

    Description:

    This application first checks to ensure that the Inbound Service that invoked this application has allocated sufficient extra channels, by inspecting the channel.ExtraChannels array. Extra channels are required to make outbound calls in an inbound application and can be configured in the Inbound Service configuration. Once the check has been made, the application splits the applicationParameters into an array for further use.

    The call is answered, a small TTS message is sent to the user and then the GetMenuSelection() method is called. This method will prompt the user for a DTMF tone after giving a list of the transfer options. We use the channel.DtmfDetector.GetDigits() method to grab a single keypad press and then make sure the returned item is in our list of transfer options. This loop will continue until either a valid keypress has been detected, or the user hangs up.

    To transfer the call, we use the channel.TransferToInboundService() method. We specify the target address and the extra channel to use for the transfer. The function returns a boolean value indicating if the transfer attempt was successful. This transfer method uses the retrievable transfer mechanism and therefore we must maintain the state of the original channel to allow the transferred call to continue. So we wait for the transferred call to be hung up before terminating.

    Code:

    Imports System.Collections.Generic
    Imports AMSClassLibrary
    Imports UASAppAPI
    
    ' An inbound application that prompts the user to select a target inbound service 
    ' to be transferred to. A prompt (to be read out) and service name (to be transferred to) 
    ' for each possible target need to be listed in the applicationParameters when
    ' this service is registered.
    '
    ' Note: this sample will only run on platforms that support Transfer.
    '
    ' Requires:
    ' [applicationParameters = semicolon delimited list of <action>,<service name>
    '      e.g. "join a conference,AddToConference;listen to media file,InboundPlayWav"]
    ' [1 extra channel]
    Namespace TransferMenu
    
        Public Class TransferMenu
            Inherits UASInboundApplication
    
            ' Possible return codes
            Enum ReturnCode
                ' Success Codes:
                Success = 0
                ' ... any positive integer
    
                ' Fail Codes:
                ' -1 to -99 reserved
                ExceptionThrown = -100
                NotSufficientExtraChannels = -101
                NotSufficientDestinations = -102
            End Enum
    
            ' A class to represent each of the menu options
            Class TransferTarget
                Public Sub New(ByVal entry As String, _
                               ByVal keyin As Integer)
                    Dim details = entry.Split(",")
                    If details.Length <> 2 Then
                        Throw New ArgumentException("Invalid destination details", "applicationParameters")
                    End If
                    Prompt = details(0).Trim()
                    ServiceName = details(1).Trim()
                    Key = keyin
                End Sub
    
                Public Prompt As String
                Public ServiceName As String
                Public Key As Integer
            End Class
    
            ' This is the entry point for the application
            Overrides Function Run(ByVal channel As UASCallChannel, _
                                   ByVal applicationParameters As String) _
                                   As Integer
    
                Me.Trace.TraceInfo("Started")
    
                Dim reply = ReturnCode.Success
                Dim primaryCallHungUp = False
    
                ' Check we've got an extra Channel
                If channel.ExtraChannels.Length < 1 Then
                    Me.Trace.TraceWarning("Needs 1 extra channel to be configured")
                    Return ReturnCode.NotSufficientExtraChannels
                End If
    
                Dim targetChannel = channel.ExtraChannels(0)
    
                Try
                    ' Decipher the applicationParameters
                    Dim entries = applicationParameters.Split(";")
                    If entries.Length < 1 Then
                        Me.Trace.TraceWarning("Needs at least 1 transfer target to be configured")
                        Return ReturnCode.NotSufficientDestinations
                    End If
    
                    Dim targets = New List(Of TransferTarget)
                    Dim key = 0
                    For Each entry In entries
                        targets.Add(New TransferTarget(entry, key))
                        key += 1
                    Next
    
                    ' The selected target
                    Dim target As TransferTarget = Nothing
    
                    ' Answer the call
                    Dim state = channel.Answer()
                    If state <> CallState.Answered Then
                        primaryCallHungUp = True
                    End If
    
                    If Not primaryCallHungUp Then
                        Me.Trace.TraceInfo("Call answered")
    
                        ' Prompt for a digit
                        channel.FilePlayer.Say("Hello.")
                        target = getMenuSelection(channel, targets)
                        If target Is Nothing Then
                            primaryCallHungUp = True
                        End If
                    End If
    
                    If Not primaryCallHungUp Then
                        ' Transfer to that target
                        channel.FilePlayer.Say("Transferring to {0}", target.Prompt)
                        state = channel.TransferToInboundService(target.ServiceName, targetChannel)
    
                        If state <> CallState.Transferred Then
                            channel.FilePlayer.Say("I wasn't able to transfer you.")
                            channel.FilePlayer.Say("Please try again later.")
                        Else
                            ' Wait for transferree or far end to hangup 
                            channel.WaitForTransferredCallRetrieved(Timeout.Infinite)
                        End If
                    End If
                Catch e As Exception
                    Me.Trace.TraceError("Exception thrown {0}", e.Message)
                    reply = ReturnCode.ExceptionThrown
                Finally
                    channel.HangUp()
                End Try
    
                Me.Trace.TraceInfo("Completed")
                Return reply
    
            End Function
    
            Function getMenuSelection(ByVal channel As UASCallChannel, ByVal targets As List(Of TransferTarget)) As TransferTarget
                ' Prepare to receive digits
                channel.DtmfDetector.ClearDigits()
    
                ' Get the target selected
                Do
                    ' Play the transfer options to the caller with bargein
                    For Each target In targets
                        Dim msg = String.Format("Press {0} to {1}", target.Key, target.Prompt)
                        Dim cause = channel.FilePlayer.Say(msg, True)
                        If cause = FilePlayerCause.HangUp Then
                            Return Nothing
                        End If
                        If cause = FilePlayerCause.BargeIn Then
                            Exit Do
                        End If
                    Next
    
                    Dim digits As String = ""
                    channel.DtmfDetector.GetDigits(1, digits, 10)
                    If channel.DtmfDetector.Cause = DtmfDetectorCause.Count Then
                        ' Get the transfer target
                        Dim keyPressed = Convert.ToInt32(digits)
                        Me.Trace.TraceInfo("Got keypress {0}", keyPressed)
                        If keyPressed < targets.Count Then
                            Return targets(keyPressed)
                        End If
                        channel.FilePlayer.Say("Invalid selection.")
                    End If
                Loop While channel.DtmfDetector.Cause <> DtmfDetectorCause.HangUp
    
                ' returning null on hangup
                Return Nothing
            End Function
    
        End Class
    
    End Namespace

Cloud UAS Sample Add To Conference

UAS API - Add To Conference Sample Application

  • Filename:

    samples/add_to_conference.py

    Description:

    This sample application will transfer the caller to a conference room. Using channel.FilePlayer.say(), the application askes the caller to enter a four digit PIN, representing a conference room ID, channel.DTMFDetector.get_digits() is used to retrieve the digits. If the right number of digits has been collected, the application will call channel.transfer_to_conference() to transfer the caller to the conference room. If the conference room does not already exist, it will be created. There will be silence on the line until someone else enters.

    Code:

    """
        An inbound application that prompts the user to enter a 4-digit pin that represents a 
        conference room, to which they are then transferred. Please read the documentation about
        conference rooms.
    
        The application uses TTS to communicate with the caller.
    
        This application requires 1 extra channel.
    
        Actions:
            - wait for anbound call
            - wait for four DTMF digits
            - create a tone player
            - transfer the call to the conference room
            - wait for the caller to hang up
    
    """
    
    from prosody.uas import Hangup, Error, ToneManager
    
    __uas_identify__ = "application"
    __uas_version__  = "1.0b1"
    
    def main(channel, application_instance_id, file_man, my_log, application_parameters):
    
        return_code = 0
    
        try:
            if channel.state() == channel.State.CALL_INCOMING:
                channel.ring()   # this can raise a Hangup exception
                channel.answer() # this can raise a Hangup exception
            else:
                raise Hangup('No inbound call')
    
            # get the extra channel
            try:
                out_channel = channel.ExtraChannel[0]
            except:
                raise Error("You need to register an extra channel for this application")
    
            channel.FilePlayer.say("Please enter a four digit conference i d.", barge_in = True)
    
            digits = channel.DTMFDetector.get_digits(count=4, seconds_predigits_timeout = 10)
    
            if channel.DTMFDetector.cause() == channel.DTMFDetector.Cause.COUNT:
                channel.FilePlayer.say("Adding you to conference {0}".format(", ".join(digits)))
    
                # because this is a transfer, we need to create the tone player
                tone_manager = ToneManager(my_log)
                channel.create_tone_player(tone_manager)
                                        
                if channel.transfer_to_conference_room(out_channel, digits) is False:
                    my_log.error("Transfer to conference. Hanging up")
                    channel.FilePlayer.say ("Sorry, I could not connect you to your conference. Good bye")
                    return_code = -104
                else:
                    my_log.info ("Transfer to conference {0} succeeded. Waiting for idle".format (digits))
                    channel.wait_for_idle(seconds_timeout=None)
            else:
                channel.FilePlayer.say ("I did not receive four digits. Hanging up.")
                return_code = -103
                
        except Hangup as exc:
            my_log.info("Got Hangup")
            return_code = -100
    
        except Error as exc:
            my_log.error("Got Error {0}".format(exc))
            return_code = -102
    
        except Exception as exc:
            my_log.exception("Got unexpected exception {0}".format(exc))
            return_code = -101
    
        finally:
            if channel.state() != channel.State.IDLE:
                channel.hang_up()
        return return_code
    
  • Filename:

    Samples\C#\AddToConference\AddToConference.cs

    Description:

    We ask for a four digit PIN code, representing the conference ID number, receive it using DTMF detection and then repeat the number back to the caller for confirmation. We can then use the channel.TransferToConferenceRoom() method, that will manage the transfer for us, passing it one of the extra channels to use for the transfer.

    We construct a ConferencePartyMediaSettings object to allow us to disable DTMF suppression which is enabled by default. The conference is configured to produce silence on the line until someone else enters the conference room.

    Code:

    using System;
    using System.Threading;
    
    using AMSClassLibrary;
    using UASAppAPI;
    
    // An inbound application that prompts the user to enter a 4-digit pin that represents 
    // the id of a conference to which they are then transferred.
    //
    // Note: this sample will only run on platforms that support Transfer.
    //
    // Requires:
    // [1 extra channel]
    namespace AddToConference
    {
        // The application class.
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        public class AddToConference : UASInboundApplication
        {
            // Possible return codes
            enum ReturnCode
            {
                // Success Codes:
                Success = 0,
                // ... any positive integer
    
                // Fail Codes:
                // -1 to -99 reserved
                ExceptionThrown = -100,
                NotSufficientExtraChannels = -101
            }
    
            // This is the entry point for the application
            public override int Run(UASCallChannel channel,
                                    string applicationParameters)
            {
                this.Trace.TraceInfo("Started");
                ReturnCode reply = ReturnCode.Success;
                string conferenceId;
    
                // Check we've got an extra Channel
                if (channel.ExtraChannels.Length < 1)
                {
                    this.Trace.TraceWarning("Needs 1 extra channel to be configured");
                    return (int)ReturnCode.NotSufficientExtraChannels;
                }
                UASCallChannel targetChannel = channel.ExtraChannels[0];
    
                try
                {
                    // Answer the call
                    CallState state = channel.Answer();
                    if (state == CallState.Answered)
                    {
                        this.Trace.TraceInfo("Call answered");
    
                        // Prompt for a conference id, enabling bargein
                        channel.FilePlayer.Say("Please Enter a four digit conference i d.", true);
    
                        string digits;
                        DtmfDetectorCause cause = channel.DtmfDetector.GetDigits(4, out digits, 30);
                        if (cause == DtmfDetectorCause.Count)
                        {
                            conferenceId = digits;
    
                            // Inform the caller what is happening
                            channel.FilePlayer.Say(
                                "Adding you to conference <say-as interpret-as='vxml:digits'>{0}</say-as>",
                                conferenceId);
    
                            // Create settings to determine how the party is connected to the conference room
                            ConferencePartyMuteDigits muteDigits = new ConferencePartyMuteDigits('*', '#');
                            ConferencePartyMediaSettings settings = new ConferencePartyMediaSettings(
                                null, null, false, '\0', muteDigits);
                            settings.SuppressDtmf = false;
    
    						// Uncomment this to start the party muted. 
                            // settings.StartMuted = true;
    
                            if (!channel.TransferToConferenceRoom(
                                    conferenceId, targetChannel, ConferencePartyType.TalkerAndListener,
                                    ConferenceLifetimeControl.FullControl,
                                    settings, 30))
                            {
                                channel.FilePlayer.Say("Failed to transfer to conference. Hanging up.");
                                channel.HangUp();
                            }
                        }
                        else
                        {
                            channel.FilePlayer.Say("No digits received. Hanging up.");
                            channel.HangUp();
                        }
                    }
    
                    // Wait for 10min for the call to be Idle
                    channel.WaitForIdle(60 * 10);
                }
                catch (Exception e)
                {
                    this.Trace.TraceError("Exception thrown {0}", e.Message);
                    reply = ReturnCode.ExceptionThrown;
                }
    
                this.Trace.TraceInfo("Completed");
                return (int)reply;
            }
        }
    }
  • Filename:

    Samples\VB\AddToConference\AddToConference.vb

    Description:

    We ask for a four digit PIN code, representing the conference ID number, receive it using DTMF detection and then repeat the number back to the caller for confirmation. We can then use the channel.TransferToConference() method, that will manage the transfer for us, passing it one of the extra channels to use for the transfer. This conference is configured to produce silence on the line until someone else enters the conference.

    We construct a ConferencePartyMediaSettings object to allow us to disable DTMF suppression which is enabled by default. The conference is configured to produce silence on the line until someone else enters the conference room.

    Code:

    Imports AMSClassLibrary
    Imports UASAppAPI
    
    ' An inbound application that prompts the user to enter a 4-digit pin that represents 
    ' the id of a conference to which they are then transferred.
    '
    ' Note: this sample will only run on platforms that support Transfer.
    '
    ' Requires:
    ' [1 extra channel]
    Namespace AddToConference
    
        ' The application class.
        ' This must have the same name as the assembly and must inherit from either 
        ' UASInboundApplication or UASOutboundApplication.
        ' It must override the Run method.
        Public Class AddToConference
            Inherits UASInboundApplication
    
            ' Possible return codes
            Enum ReturnCode
                ' Success Codes:
                Success = 0
                ' ... any positive integer
    
                ' Fail Codes:
                ' -1 to -99 reserved
                ExceptionThrown = -100
                NotSufficientExtraChannels = -101
            End Enum
    
            ' This is the entry point for the application
            Overrides Function Run(ByVal channel As UASCallChannel, _
                                   ByVal applicationParameters As String) _
                                   As Integer
    
                Me.Trace.TraceInfo("Started")
                Dim reply As ReturnCode = ReturnCode.Success
                Dim conferenceId As String
    
                ' Check we've got an extra Channel
                If channel.ExtraChannels.Length < 1 Then
                    Me.Trace.TraceWarning("Needs 1 extra channel to be configured")
                    Return ReturnCode.NotSufficientExtraChannels
                End If
                Dim targetChannel = channel.ExtraChannels(0)
    
                Try
                    ' Answer the call
                    Dim state As CallState
                    state = channel.Answer()
    
                    If state = CallState.Answered Then
                        Me.Trace.TraceInfo("Call answered")
    
                        ' Prompt for a conference id, enabling bargein
                        channel.FilePlayer.Say("Please Enter a four digit conference i d.", True)
    
                        Dim digits As String = ""
                        Dim cause = channel.DtmfDetector.GetDigits(4, digits, 30)
                        If cause = DtmfDetectorCause.Count Then
                            conferenceId = digits
    
                            ' Inform the caller what is happening
                            channel.FilePlayer.Say( _
                                "Adding you to conference <say-as interpret-as='vxml:digits'>{0}</say-as>", _
                                conferenceId)
    
                            ' Create settings to determine how the party is connected to the conference room
                            Dim muteDigits = New ConferencePartyMuteDigits("*", "#")
                            Dim settings = New ConferencePartyMediaSettings(Nothing, Nothing, False, "\0", muteDigits)
                            settings.SuppressDtmf = False
    
                            ' Uncomment this to start the party muted. 
                            ' settings.StartMuted = True;
    
                            If Not channel.TransferToConferenceRoom( _
                                    conferenceId, targetChannel, ConferencePartyType.TalkerAndListener, _
                                    ConferenceLifetimeControl.FullControl, _
                                    settings, 30) Then
                                channel.FilePlayer.Say("Failed to transfer to conference. Hanging up.")
                                channel.HangUp()
                            End If
                        Else
                            channel.FilePlayer.Say("No digits received. Hanging up.")
                            channel.HangUp()
                        End If
                    End If
    
                    ' Wait for 10min for the call to be Idle
                    channel.WaitForIdle(60 * 10)
    
                Catch ex As Exception
                    Me.Trace.TraceError("Exception thrown {0}", ex.Message)
                    reply = ReturnCode.ExceptionThrown
                End Try
    
                Me.Trace.TraceInfo("Completed")
                Return reply
    
            End Function
    
        End Class
    
    End Namespace

Cloud UAS Sample Connect To Conference

UAS API - Connect To Conference Sample Application

  • Filename:

    samples/connect_to_conference.py

    Description:

    This sample application will connect the caller to a conference room. Using channel.FilePlayer.say(), the application askes the caller to enter a four digit PIN, representing a conference room ID, channel.DTMFDetector.get_digits() is used to retrieve the digits. If the right number of digits has been collected, the application will call use the high level API function call_and_connect_to_conference() to connect the caller to the conference room. If the conference room does not already exist, it will be created. There will be silence on the line until someone else enters.

    Code:

    """
        An inbound application that prompts the user to enter a 4-digit pin that represents a 
        conference room, to which they are then connected. Please read the documentation about
        conference rooms.
    
        The application uses TTS to communicate with the caller.
    
        This application requires 1 extra channel.
    
        Actions:
            - wait for inbound call
            - wait for four DTMF digits
            - create a tone player
            - connect the call to the conference room
            - wait for the caller to hang up
    
    """
    
    from prosody.uas import Hangup, Error
    from prosody.uas.highlevel import HighLevelCallChannel
    
    __uas_identify__ = "application"
    __uas_version__  = "1.0b1"
    
    def main(channel, application_instance_id, file_man, my_log, application_parameters):
    
        return_code = 0
    
        try:
            if channel.state() == channel.State.CALL_INCOMING:
                channel.ring()   # this can raise a Hangup exception
                channel.answer() # this can raise a Hangup exception
            else:
                raise Hangup('No inbound call')
    
            # get the extra channel
            try:
                out_channel = channel.ExtraChannel[0]
            except:
                raise Error("You need to register an extra channel for this application")
    
            channel.FilePlayer.say("Please enter a four digit conference i d.", barge_in = True)
    
            digits = channel.DTMFDetector.get_digits(count=4, seconds_predigits_timeout = 10)
    
            if channel.DTMFDetector.cause() == channel.DTMFDetector.Cause.COUNT:
                channel.FilePlayer.say("Adding you to conference {0}".format(", ".join(digits)))
    
                high_level_channel = HighLevelCallChannel(channel, my_log)
                if high_level_channel.call_and_connect_to_conference(other_call=out_channel, 
                                                                     conference_room_name=digits) is False:
                    my_log.error("Connect to conference. Hanging up")
                    channel.FilePlayer.say ("Sorry, I could not connect you to your conference. Good bye")
                    return_code = -104
                else:
                    my_log.info ("Connect to conference {0} succeeded. Waiting for idle.".format (digits))
                    channel.wait_for_idle(seconds_timeout=None)
            else:
                channel.FilePlayer.say ("I did not receive four digits. Hanging up.")
                return_code = -103
                
        except Hangup as exc:
            my_log.info("Got Hangup")
            return_code = -100
    
        except Error as exc:
            my_log.error("Got Error {0}".format(exc))
            return_code = -102
    
        except Exception as exc:
            my_log.exception("Got unexpected exception {0}".format(exc))
            return_code = -101
    
        finally:
            if channel.state() != channel.State.IDLE:
                channel.hang_up()
        return return_code
    
  • Filename:

    Samples\C#\ConnectToConference\ConnectToConference.cs

    Description:

    We ask for a four digit PIN code, representing the conference ID number, receive it using DTMF detection and then repeat the number back to the caller for confirmation. We can then use the CallConferenceRoom() method, that will call the conference on the extra channel supplied.

    We construct a ConferencePartyMediaSettings object to allow us to disable DTMF suppression which is enabled by default. The conference is configured to produce silence on the line until someone else enters the conference room.

    Code:

    using System;
    using System.Threading;
    
    using AMSClassLibrary;
    using UASAppAPI;
    
    // An inbound application that prompts the user to enter a 4-digit pin that represents 
    // the id of a conference to which they are then connected.
    //
    // Requires:
    // [1 extra channel]
    namespace ConnectToConference
    {
        // The application class.
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        public class ConnectToConference : UASInboundApplication
        {
            // Possible return codes
            enum ReturnCode
            {
                // Success Codes:
                Success = 0,
                // ... any positive integer
    
                // Fail Codes:
                // -1 to -99 reserved
                ExceptionThrown = -100,
                NotSufficientExtraChannels = -101
            }
    
            // This is the entry point for the application
            public override int Run(UASCallChannel channel,
                                    string applicationParameters)
            {
                this.Trace.TraceInfo("Started");
                ReturnCode reply = ReturnCode.Success;
                string conferenceId;
    
                // Check we've got an extra Channel
                if (channel.ExtraChannels.Length < 1)
                {
                    this.Trace.TraceWarning("Needs 1 extra channel to be configured");
                    return (int)ReturnCode.NotSufficientExtraChannels;
                }
                UASCallChannel conferenceChannel = channel.ExtraChannels[0];
    
                try
                {
                    // Answer the call
                    CallState state = channel.Answer();
                    if (state == CallState.Answered)
                    {
                        this.Trace.TraceInfo("Call answered");
    
                        // Prompt for a conference id, enabling bargein
                        channel.FilePlayer.Say("Please Enter a four digit conference i d.", true);
    
                        string digits;
                        DtmfDetectorCause cause = channel.DtmfDetector.GetDigits(4, out digits, 30);
                        if (cause == DtmfDetectorCause.Count)
                        {
                            conferenceId = digits;
    
                            // Inform the caller what is happening
                            channel.FilePlayer.Say(
                                "Adding you to conference <say-as interpret-as='vxml:digits'>{0}</say-as>",
                                conferenceId);
    
                            // Create settings to determine how the party is connected to the conference room
                            ConferencePartyMuteDigits muteDigits = new ConferencePartyMuteDigits('*', '#');
                            ConferencePartyMediaSettings settings = new ConferencePartyMediaSettings(
                                null, null, false, '\0', muteDigits);
                            settings.SuppressDtmf = false;
    
                            // Uncomment this to start the party muted. 
                            // settings.StartMuted = true;
    
                            if (conferenceChannel.CallConferenceRoom(
                                conferenceId,
                                ConferencePartyType.TalkerAndListener,
                                ConferenceLifetimeControl.FullControl,
                                settings,
                                30) == CallState.Answered)
                            {
                                // Connect the calls together
                                if (!channel.Connect(conferenceChannel))
                                {
                                    channel.FilePlayer.Say(
                                        "Failed to connect to conference. Hanging up.");
                                    channel.HangUp();
                                }
                            }
                            else
                            {
                                channel.FilePlayer.Say(
                                    "Failed to call conference <say-as interpret-as='vxml:digits'>{0}</say-as>. Hanging up.",
                                    conferenceId);
                                channel.HangUp();
                            }
                        }
                        else
                        {
                            channel.FilePlayer.Say("No digits received. Hanging up.");
                        }
                    }
    
                    // Wait for the call to be Idle
                    channel.WaitForIdle(360);
                }
                catch (Exception e)
                {
                    this.Trace.TraceError("Exception thrown {0}", e.Message);
                    reply = ReturnCode.ExceptionThrown;
                }
    
                this.Trace.TraceInfo("Completed");
                return (int)reply;
            }
        }
    }
  • Filename:

    Samples\VB\ConnectToConference\ConnectToConference.vb

    Description:

    We ask for a four digit PIN code, representing the conference ID number, receive it using DTMF detection and then repeat the number back to the caller for confirmation. We can then use the CallConferenceRoom() method, that will call the conference on the extra channel supplied. This conference is configured to produce silence on the line until someone else enters the conference.

    We construct a ConferencePartyMediaSettings object to allow us to disable DTMF suppression which is enabled by default. The conference is configured to produce silence on the line until someone else enters the conference room.

    Code:

    Imports AMSClassLibrary
    Imports UASAppAPI
    
    ' An inbound application that prompts the user to enter a 4-digit pin that represents 
    ' the id of a conference to which they are then connected.
    '
    ' Requires:
    ' [1 extra channel]
    Namespace ConnectToConference
    
        ' The application class.
        ' This must have the same name as the assembly and must inherit from either 
        ' UASInboundApplication or UASOutboundApplication.
        ' It must override the Run method.
        Public Class ConnectToConference
            Inherits UASInboundApplication
    
            ' Possible return codes
            Enum ReturnCode
                ' Success Codes:
                Success = 0
                ' ... any positive integer
    
                ' Fail Codes:
                ' -1 to -99 reserved
                ExceptionThrown = -100
                NotSufficientExtraChannels = -101
            End Enum
    
            ' This is the entry point for the application
            Overrides Function Run(ByVal channel As UASCallChannel, _
                                   ByVal applicationParameters As String) _
                                   As Integer
    
                Me.Trace.TraceInfo("Started")
                Dim reply As ReturnCode = ReturnCode.Success
                Dim conferenceId As String
    
                ' Check we've got an extra Channel
                If channel.ExtraChannels.Length < 1 Then
                    Me.Trace.TraceWarning("Needs 1 extra channel to be configured")
                    Return ReturnCode.NotSufficientExtraChannels
                End If
                Dim conferenceChannel = channel.ExtraChannels(0)
    
                Try
                    ' Answer the call
                    Dim state As CallState
                    state = channel.Answer()
    
                    If state = CallState.Answered Then
                        Me.Trace.TraceInfo("Call answered")
    
                        ' Prompt for a conference id, enabling bargein
                        channel.FilePlayer.Say("Please Enter a four digit conference i d.", True)
    
                        Dim digits As String = ""
                        Dim cause = channel.DtmfDetector.GetDigits(4, digits, 30)
                        If cause = DtmfDetectorCause.Count Then
                            conferenceId = digits
    
                            ' Inform the caller what is happening
                            channel.FilePlayer.Say( _
                                "Adding you to conference <say-as interpret-as='vxml:digits'>{0}</say-as>", _
                                conferenceId)
    
                            ' Create settings to determine how the party is connected to the conference room
                            Dim muteDigits = New ConferencePartyMuteDigits("*", "#")
                            Dim settings = New ConferencePartyMediaSettings(Nothing, Nothing, False, "\0", muteDigits)
                            settings.SuppressDtmf = False
    
                            ' Uncomment this to start the party muted. 
                            ' settings.StartMuted = True;
    
                            If (conferenceChannel.CallConferenceRoom( _
                                conferenceId, _
                                ConferencePartyType.TalkerAndListener, _
                                ConferenceLifetimeControl.FullControl, _
                                settings, _
                                30) = CallState.Answered) Then
                                ' Connect the calls together
                                If Not channel.Connect(conferenceChannel) Then
                                    channel.FilePlayer.Say( _
                                        "Failed to connect to conference. Hanging up.")
                                    channel.HangUp()
                                End If
                            Else
                                channel.FilePlayer.Say( _
                                    "Failed to call conference <say-as interpret-as='vxml:digits'>{0}</say-as>. Hanging up.", _
                                    conferenceId)
                                channel.HangUp()
                            End If
                        Else
                            channel.FilePlayer.Say("No digits received. Hanging up.")
                            channel.HangUp()
                        End If
                    End If
    
                    ' Wait for 10min for the call to be Idle
                    channel.WaitForIdle(60 * 10)
    
                Catch ex As Exception
                    Me.Trace.TraceError("Exception thrown {0}", ex.Message)
                    reply = ReturnCode.ExceptionThrown
                End Try
    
                Me.Trace.TraceInfo("Completed")
                Return reply
    
            End Function
    
        End Class
    
    End Namespace

Archive

The Aculab blog

News, views and industry insights from Aculab

  • Eliminating Barriers to Communication with Live Audio Translation for Phone Calls

    In an increasingly interconnected world, clear and effective communication is more essential than ever. That’s why Aculab intends to help break down language barriers and foster cross-cultural communications.

    Continue reading

  • The End of the PSTN in the US

    As the technical world has evolved, so has the way we communicate. The gradual, global transition away from the Public Switched Telephone Network (PSTN) is the most noticeable change in recent years. This begs the question, is the PSTN in the US headed towards a slow end as we transition into the digital era?

    Continue reading

  • Revolutionising the Landscape of Remote Authentication

    In a time where borders blur and workplaces extend beyond the confines of traditional offices, the significance of remote authentication has taken centre stage. As we advance, so does the need for secure and efficient ways to verify and authenticate our identity remotely. Finding the balance between security and user convenience is key when seeking to implement successful remote authentication.

     

    Continue reading

  • Choosing The Ideal Communication Platform: Key Considerations to Optimise Your Business

    Communication Platforms as a Service have become a necessity in the current digital age; allowing businesses to obtain frictionless means of communicating effectively. However, as technology rapidly evolves, so must communications. Much of the platforms on offer today are homogenous, so choosing the best fit for your business can be difficult. In this blog, we have shared some key points and trends for to consider, so your business can amplify communications and increase operational efficiency!

     

    Continue reading

  • 10 questions people are asking about The Big Switch Off

    With The Big Switch Off fast approaching, people naturally have questions and concerns ahead of the shutdown. The transition from conventional networks to digital technology is unavoidable in the fast-evolving world of telecommunications. In this blog, we address ten common questions people have about the Big PSTN Switch Off, shedding light on the topic and providing clarity.

     

    Continue reading