Asterisk: Combining “Background” and “Read”

If you’ve ever had to do an IVR in Asterisk it is likely that you will have entered a scenario where you want a user to punch an identifier of indefinite length.

Simple right? Most people just use the build in Asterisk dialplan command called Read()

The syntax itself is pretty simple:

Read(variable[,filename][,maxdigits][,option][,attempts][,timeout])

Reads a #-terminated string of digits a certain number of times from the user in to the given variable.

variable: variable where the user’s response will be stored.
filename: file to play before reading digits.
maxdigits: maximum acceptable number of digits. Stops reading after maxdigits have been entered (without requiring the user press the ‘#’ key). Defaults to 0 – no limit – wait for the user press the ‘#’ key. Any value below 0 means the same. Max accepted value is 255.
option: There are 3 options:(sin). s(skip):to return immediately if the line is not up. i(indication):Rather than playing a prompt, play an indication tone of some sort (such as the dialtone). n(noanswer) to read digits even if the line is not up.
attempts: if greater than 1, that many attempts will be made in the event no data is entered.
timeout: Timeout in seconds. If greater than 0, that value will override the default timeout.

One would normally implement it like so:

[my-ivr]
exten => s,1,Noop(We are in the IVR, ask the user to enter an ID number up to 8 digits long)

exten => s,n,Background(welcome-to-ivr)
exten => s,n,Background(pls-enter-cust-id)
exten => s,n,Read(CUSTID,,8)
exten => s,n,Goto(validate-id,s,1)

While this works exactly as shown there are some usability problems with this. Because Read does not tie in with Background, the end user MUST wait for the prompt in Background to complete before entering their ID. Also Read() does not appear to support multiple languages of filenames in my current version of Asterisk. Finally, what if you wanted to play multiple dynamic sound files that were broken into pieces. Read() only supports a single file whereas many IVR’s use several Background() commands to chunk and re-use prompt portions. If you leveraged the filename parameter in Read(), you are stuck with only a single playback file!

This is the exact problem listed in this Asterisk Forum post here : http://forums.asterisk.org/viewtopic.php?f=13&t=18482

So how do we solve this? By working around it using Background(), Waitexten(), and Read()

[my-ivr]
exten => s,1,Noop(In IVR, play our two sounds and ask for ID)
exten => s,n,Background(welcome-to-ivr)
exten => s,n,Background(pls-enter-cust-id)
exten => s,n,Waitexten(10)
exten => _X,1,Read(tmp,,7)
exten => _X,n,set(CUSTID=${EXTEN}${tmp})
exten => _X,n,Goto(validate-id,s,1)

Essentially we leverage the dialplan command Waitexten() but the secret is that it is only used to get the first digit! So long as the ONLY extensions in that context are “s” and “_X“, it will match immediately and take us to the next Read() command also notice that Read has a max length of our max id length Minus 1. As soon as execution for Read is completed, we stitch the results of WaitExten and Read back together to get our full value.

Good luck and Happy VoIP’ing!

Advertisements

Thoughts? Comments? Reply here!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: