Friday, February 14, 2020

Asterisk Dynamic Routes module examples

The Dynamic Routes module for FreePBX, specifically the one in the ISSABEL distribution lets you route based database lookups, asterisk variables, agi 's.  The version I'm testing with is in the ISSABEL distro, however although the GUI is slightly different, this applies to regular FreePBX as well.

I've provided a few different examples of what you can do with the Dynamic Routes.  Its quite powerful feature and you can do some neat things without needing to tear apart and customize a dialplan with it in most cases.

EXAMPLE 1a:
SQL LOOKUP (hardcoded value)


This will do a hard coded lookup for a specific value each time.  In this case the system will see if the hard value of "1000" exists in the extension column of the "USER" table in the "ASTERISK" database

I'm doing lookups in the SQL database that exists, but you could easily make a table and put in your own values.   

Here is "USER" the table in Asterisk with some test data.


+-----------+----------+-------+-----------+-----------+----------+-----------+----------+
| extension | password | name  | voicemail | ringtimer | noanswer | recording | mohclass |
+-----------+----------+-------+-----------+-----------+----------+-----------+----------+
| 1000      |          | Agent1| default   |         0 |          |           | default  |
+-----------+----------+-------+-----------+-----------+----------+-----------+----------+

Here is what my Dynamic Route looks like for a hard coded SQL data lookup.


The QUERY is executed and will always look for the existence extension 1000 

select extension from users where extension = 1000


The select statement looks to see if there is anything in the "Extension" column that has the value of "1000", and there is a match.  Anything that matches 1000 goes to the Feature Code Admin "Echo Test".

IF the SQL statement were to change to hardcoded value "1001"

select extension from users where extension = 1001

If the script were run, this script would FAIL  and go to the "DEFAULT DESTINATION" (dial voicemail) and NOT Speaking Clock because there is no extension 1001 in my SQL example.

IF you were to add extension 1001 to the PBX, and call from that extensions and ran that select statement, the system would then go to "Speaking Clock" 

EXAMPLE 1b:
SQL LOOKUP (hardcoded value built in "PINSETS").

We can do something similar as above, but use a system already built into IssabelPBX to create unique SQL tables, the PINSET module.  We can use this module to maintain a SQL table of data without needing to create one.  

In the example below, a PINSET with the description of "DynamicRoutePinSet" is created.  I've included a single number of " 1 " which will use along with a "0" to control our call path.



For this example, using PINSET, its important to only use one single entry.  Don't put in multiple pins because of the way PINSET is saved in the database. 


Now create a dynamic route that does a MSQL look up, enter in your MYSQL login information.

For a query put in:

select passwords from pinsets where description = 'DynamicRoutePinSet'




Set a destination for 1 and 0 to go to a destination of your choice.  In my example, I'm using 1 to goto a queue or 0 to goto a mail box.

Setting the value in PINset to 1 or 0 will adjust the direction of this traffic automatically. 

When you run this, you'll see it in the live log.  It will look something like this:




EXAMPLE 2a:
SQL Lookup (Dynamic Lookup) with touch tone phone input

This example, the caller will be asked to enter in data using their number pad on their phone (DTMF) which the system will look for a match in the database.

The caller will be asked to enter an extension and press the # key.

The value entered into the phone is stored in the Input Variable " UserExt "

That variable is passed to the Query statement, formatted to look like this: '[UserExt]'    It will need the single quote tick and square bracket on both sides.

The complete Query will look like this for the example shown here

select extension from users where extension = '[UserExt]'

Here is what the config looks like in Dynamic Routes



The caller enters the dynamic route, and enters "1000#"
The system will look at the USERS table, and look at the EXTENSION column and see if the value stored in "UserExt" (which would be 1000) exists.


In our example there would be a match, and the caller would be sent to the "ECHO TEST" system.

EXAMPLE 2b:
SQL Lookup (Dynamic Lookup) with touch tone phone using PINSETS as a qualifier

This example will let you use PINSETS to control a lookup.  Again this is for example purposes to give you some usecases.

Lets create a pinset with some PINS in it. 500, 200 and 689
(Due to a technical limitation, please make all PINS in this the same length.)


Now we'll create a dynamic route to query the PINSet database.

Set DTMF input, and put an input variable of PINnumber.


put this in the QUERY

select MID((select passwords from pinsets where description = 'DynamicRoutePinSet'), INSTR ((select passwords from pinsets), '[PINnumber]'),3)

Note that in the query, the "DynamicRoutePinSet" is the PINSET description, the PINnumber is the database variable, and the "3" at the very end of the statement is the length of the pins numbers.

Now we'll need to use a bit of a long query with PINSET because of the way it is configured in the database, just copy and paste the following in the query.

Make a test call. Entering in 500 will take you to the queue, and 200 will take you to voicemail.

EXAMPLE 2c:
SQL Lookup (Dynamic Lookup) using PINSETS to route calls based on CallerID number

Do you want to route calls based on callerdID number?  Here's a way you can do it in Issabel deployment of asterisk

Create a PIN set for each of your different extensions you want to receive specific calls.

The Pinset description will be used to direct matching calls in dynmaic routes.

The pinset "PIN LIST" will contain the CallerID numbers you want to match


Now create a Dynamic route

Give it a descriptive name, then select SOURCE TYPE "MYSQL"

Put in your host, user and password for your SQL database, then in "QUERY" put in this command

select description from pinsets where passwords like '%${REALCALLERIDNUM}%'



You'll see how I've placed in the "MATCH" column the descriptive names from the PINSETS.  Any CLID number that matches in pinset, will return its descriptor that we can use to route the call.


EXAMPLE 3:
ROUTE BASED ON ASTERISK VARIABLE

The system can route based on an internal asterisk variable.  Active variables in asterisk can be utilized.  In this example, we'll use the variable ${AMPUSER}, which is a system variable, its value containing the extension number making the call.

We set the SOURCE TYPE to be asterisk variable

In the Variable String we put in the asterisk string ${AMPUSER}

When an extension makes a call through this dynamic route, it will get the value of ${AMPUSER} and route based on that number.  Since my examples I'm testing from extension 1000, that is the value of AMPUSER.

If extension 1000 is calling the dynamic route, the call will go to "ECHO TEST"

If extension 1001 is calling the dynamic route, the system will play "SYSTEM CLOCK"

If there is no match, the system will play "DIAL VOICEMAIL"

You can use most any asterisk variable to route a call.

REGEX
You can further do some REGEX command in the variable box to check for a value.
For example, putting in this will have the system check to see if callerID number STARTS with 155 .  If it does, it will return a "1" as a value (true).  
^155.  means anything starting with 155, regardless of length.

${REGEX("^155." ${CALLERID(num)})}

By putting in a 1 as match destination, all calls starting with 155 will go to that route.

Refer to "REGEX" for linux to get some other matches

EXAMPLE 4:
Route based on a URL result

This one is a little more strict, has quite a few limitations, but this will send callers to a destination based on the text on a web page that return very simple text responses.

We can test this easily in an Issabel deployment using the built in "HELP" system.

If you go to this URL (put in the IP of your server)


You should get something like : "The selected menu is not valid"


Put in the URL that you want the system to check. (change my IP to your PBX ip or server name)

https://10.1.80.193/help/frameRight.php

Now I've copy and pasted the EXACT return into the box match box

"The selected menu is not valid."

When the caller enters the Dynamic Rout, the server will check that web page, and if it sees the matching data, it will play the Speaking Clock.

For troubleshooting, you can sometimes see exactly what asterisk sees when it goes to a URL by looking at the live log with an entry similar to this:

 -- Executing [s@dynroute-2:7] Set("SIP/1000-0000002e", "dynroute=The selected menu is not valid.") in new stack

The entry "dynroute=" will contain what asterisk received when it went to that site.


EXAMPLE 5:
Route based on a AGI result

I haven't done a lot with the AGI, but here is a demo config of kind of how it would work.

The AGI script and parameters contains the path to the .AGI file you want to run.
AGI variable is where the return data gets stored

In the above example, we call the AGI, it returns with the hard coded variable dynroute value of 0

We can then put the values we expect and route.  In the example, we send the call to "ECHO TEST" if it returns a 0.

I haven't done anything else with AGI, so if anyone has information for this I would love to add it!


Dynamic Route CONFIG PARAMETERS


Dynamic Route
The following information documents how to fill in the fields of a Dynamic Route. This documentation refers to the V13 functionality. Not all options are available in previous versions.
Field name
Comment
Dynamic Route Name
The name of the dynamic route. This can be chosen at will. It is used to identify the route when selecting it as a destination from other applications or inbound routes.
Dynamic Route Description
Optional description text for the Dynamic Route. This is for documentation purposes only
Enable DTMF Input
Setting: Yes or No. Default: No. If set to yes the call waits for input on the touch tone keypad. This can be used to capture caller input (for example a customer number).
Announcement
The system recording to be played back. If Enable DTMF input is set to Yes then playback takes place before waiting for DTMF input.
Timeout
Timeout in seconds to wait for DTMF input. This value is only used if Enable DTMF Input is set to Yes. If no value is given for timeout, the default for the channel is used. It is best to set an explicit value to avoid doubts.
Validation
Validation rules using a Asterisk regular expression (see Asterisk REGEX). For example to ensure the input is between 3 and 4 digits long you could use ^[0-9]\{3,4\}$
Invalid Retries
Number of times to retry if DTMF input does not match validation rules.
Invalid Retry Recording
Recording to play if DTMF input does not match validation rules.
Invalid Recording
Recording to play if DTMF input does not match validation rules and Invalid Retries have been exhausted.
Invalid Destination
The destination to send the call to if DTMF input does not match the validation rules and Invalid Retries ahve been exhausted. The call is sent to this destination after playing the Invalid Recording if it is defined.
Saved input variable name
Name of variable in which to save DTMF input for future use in the dial plan or further dynamic routes. This is available as [name] in the query/lookup where name is the name of the variable you specify here. To use the variable in the dial plan (e.g. custom applications) it is necessary to prefix it with DYNROUTE_ e.g. DYNROUTE_name
Saved result variable name
Name of variable in which to save lookup result for future use in the dial plan or further dynamic routes. This is available as [name] in the query/lookup where name is the name of the variable you specify here. To use the variable in the dial plan (e.g. custom applications) it is necessary to prefix it with DYNROUTE_ e.g. DYNROUTE_name
Source Type
The type of lookup (see under Source types below for further information
Default Destination
Destination to send the call to if the lookup result does not match one of the match values in the Dynamic Route Entries section or if the lookup fails. This is optional but is strongly recommended. If there is no default destination defined, then in the case of a lookup failure or if the lookup result does not match one of the defined values, the call will be disconnected. If this is not what is required, define the default destination with the desired behaviour.
Dynamic Route Entries
Zero or more entries to be matched by the lookup result. If the lookup matches, then the call is routed to the chosen destination. Each match is tried in the order given until one matches. If no match is found then the call is sent to the Default Destination. Additional rows may be added by clicking the + symbol. Entries may be deleted by cancelling the value in the Match field.
Source Type
The following are the currently available source types for lookups. Each source type has its own specific fields for defining the lookup parameters.
Source Type
Comment
none
No lookup is carried out. The call is sent to the default destination
MySQL
A lookup is done to a MySQL database. The parameters used are:
·         MySQL hostname: hostname of server
·         MySQL database: database name
·         MySQL username: username
·         MySQL password: password
·         MySQL query: the SQL to be used. It can contain substitutions as indicated in the table below. Example: select destination from callerid_table where calleridnum like '%[NUMBER]'
ODBC
A lookup is done to an Asterisk ODBC data source. The parameters used are:
·         ODBC function: the Asterisk ODBC function name that has been configured
·         ODBC query: the query. It can contain substitutions as indicated in the table below. Example: select destination from callerid_table where calleridnum like '%[NUMBER]'
For information about setting up ODBC see this article
URL
A lookup is done to a URL. The parameters used are:
·         URL Looup: the URL to be used for the lookup. The results must be text only. HTML, XML and JSON is not supported. The URL may contains parameters and the parameter values may include the substitutions indicated in the following table. Example: http://localhost/test.php?param1=4&param2=[NUMBER]
AGI
A lookup is done by launching an Asterisk AGI script. The parameters used are:
·         AGI Lookup: the name of the Asterisk AGI script to be launched.
·         AGI Result Variable: the name of the variable that the script uses to communicate the result. The script should execute a SET VARIABLE command using this variable name at the end of execution in order to pass back the lookup result. An example script is given in the installation directory (test.agi).
Asterisk Variable
The lookup value is read from an Asterisk Variable. The parameters used are:
·         Asterisk Variable: the variable name from which to read the result. Example: ${xxx}. Complex expressions may also be written provided they use valid Asterisk functions, for example: ${REGEX("^1.3$" ${DYNROUTE_dtmf})} would check that the DTMF input was in the range 1000-1999 (providing that the Saved input variable name was set to "dtmf")
Substitutions
In the lookup
When defining the query field for the lookup, the following Variable Names will be substituted by the corresponding value at the time of the call routing.
Variable Name
Substituted by
[INPUT]
The DTMF input by the caller on the touchtone keypad
[NUMBER]
The callerid of the incoming call
[DID]
The called number
[name]
Where "name" is the value of one of these two fields: Saved input varibale name or Saved result varibale name. In the case of Saved input variable name, the DTMF input is saved under this name. This is useful if you are using two levels of Dynamic Route so that you can save the DTMF from the previous Dynamic Route in a uniquely named variable and use that variable in the lookup of the second Dynamic Route. In the case of Saved result variable name, the result returned from the lookup is saved to the variable name and can be used in a later Dynamic Route.

If you want to use a variable created outside Dynamic Routes in the lookup, then name the variable with a DYNROUTE_ prefix. Then [name] will be substituted by the value of the asterisk variable DYNROUTE_name. There is currently no way of reading an arbitrarily named asterisk variable, except for the lookup type "Asterisk variable".
In custom dial plan or other FreePBX modules
Variable Name
Substituted by
DYNROUTE_name
Where "name" is the value of one of these two fields: Saved input varibale name or Saved result varibale name. In the case of Saved input variable name, the DTMF input is saved under this name. This is useful if you need to use the value in a custom dial plan application or another FreePBX module. In the case of Saved result variable name, the result returned from the lookup is saved to the variable name and can be used in a custom dial plan application or another FreePBX module. To obtain the value of the variable named name, use ${DYNROUTE_name} in the Asterisk dial plan.


5 comments:

  1. Thank you because you have been willing to share information with us. we will always appreciate all you have done here because I know you are very concerned with our. asterisk based phone systems

    ReplyDelete
  2. Thank you ! Very nice documentation !

    ReplyDelete
  3. si quisiera hacer una encuesta como seria? no necesito consultar. lo que necesito es almacenar la evaluacion que pueda hacer el cliente luego de seleccionar la opcion. Calificar servicio en el IVR. por ejemplo

    ReplyDelete