官术网_书友最值得收藏!

Variables

Variables are key to making the dialplan and system work in a manner that a user expects. The user would expect the system to know everything they have set on their extension, and not have to enter codes or dial special access numbers.

There are a number of places in which variables can be stored including the dialplan, sip.conf, iax.conf, chan_DAHDI.conf (in version1.6), and the Asterisk database (AstDB). For example, if we have a number of static dial strings we wish to store for each type of call and carrier we use, and then use them in a number of sections, the [globals] section of the extensions.conf file is the obvious place to declare them. If we wish to set a variable when a call is initiated from a SIP device, external caller ID or account codes are a good example, the setvar command in the sip.conf file is ideal for that purpose. Just remember that it won't work for calls sent to that device just when the calls are made. Finally, the AstDB is great for variables that are more transient in nature, such as call counts.

Inheritance of channel variables through the dialplan

On occasion, when using complicated dialplans you may wish for a variable's value to be kept as the call progresses. This is achieved by adding a _ [underscore] or a __ [double underscore] before the variable name.

A single _ will cause that variable to be inherited into the channel that started from the original channel, for example:

Set(_name1=value1)

If you want the variable to be inherited to all child channels indefinitely, then add __ before the variable name. For example:

Set(__name2=value2)

This should not be confused with setting the variable with the g option, as this sets it as a global variable. Doing so makes the variable available to all channels globally.

So, you may ask "why might we store dial strings as a variable?" The simple reason is that it allows a minimal amount of code for dialing all numbers, but still allows for different classes of restriction, by which we mean allowing different users to have different restrictions in what they can and cannot dial.

To pass these variables we will use a macro. Macros are like a template that we can use for repeated tasks, and they allow the passing of variables in an ordered fashion to the macro context. The call will jump to the s extension. The calling extension, context, and priority are stored in ${MACRO_EXTEN}, ${MACRO_CONTEXT}, and ${MACRO_PRIORITY} respectively. Arguments passed are accessed as ${ARG1}, ${ARG2}, and so on within the Macro. While a Macro is being executed, it becomes the context, so you must be able to handle the h, i, and t extensions if required within that context.

Let's build our small macro dialplan. We have a variable defined in the globals section of the extensions.conf file as follows:

[globals]
INT_CALL=IAX2/username@peer_out/
INT_CALL_ID=01234123456 ; default international callerID
INT_CALL_LIMIT=5 ; Limit on the number of calls

In the context that we use for dialing, we have:

; International long distance through trunk
exten => _90.,1,Macro(outdial,${INT_CALL})

Here, we have defined the macro we are going to pass the call to, along with a single variable we defined in the globals section (the value of the calling extension can be retrieved within the macro by using ${MACRO_EXTEN}).

The macro context looks like this:

[macro-outdial]
exten => s,4,Dial(${ARG1}${MACRO_EXTEN:1},180)

This is the same as the dial string:

exten => s,4,Dial(IAX2/username@peer_out/01234123456,180)

We have seen that we can pass one dial string, but let's now pass other variables to the Dial() application, such as a backup route for outgoing calls, and the caller ID we want to use for the call.

exten => _90.,1,Macro(outdial,${INTCALL},${INT_CALL_ID},${INT_CALL_LIMIT})
[macro-outdial]
exten => s,1,Set(GROUP()=OUTBOUND_GROUP) ;Set Group
exten => s,2,GotoIf($[${GROUP_COUNT(OUTBOUND_GROUP)} > ${ARG3}]?103) ;Exceeded?
exten => s,3,Set(CALLERID(num)=${ARG2})
exten => s,4,Dial(${ARG1}${MACRO_EXTEN:1},180)

Now it's time to bring some .conf file variables into the mix. Using the setvar facility in the sip.conf, iax.conf and chan_dahdi.conf files, we can set variables specific for every user such as unique caller ID, call limits, whether we want to record the call, account codes. Basically, anything that will help you handle calls more efficiently.

setvar=account_code=2206
setvar=callidnum=01234123456
setvar=tenantID=2

Note

One problem using .conf files is that the relevant channel module needs to be reloaded after a change, and in the case of DAHDI, Asterisk would need to be restarted. This isn't too much of an issue but the need can be removed by using the AstDB for storing commonly changed settings, such as caller ID and recordings.

You may think that all this variable use is over-complicated, but consider a system that supports multiple tenants. Using these techniques, you will only need one dialplan for multiple tenants instead of one per tenant. Simply set the tenantID in the relevant .conf file and then store the tenants' features in the globals section of the dialplan and in the AstDB, and all calls will go out as that tenant group. The concept is the same for other scenarios, such as departments that require cross charging of telephone costs.

Using the AstDB

Setting and retrieving variables in the AstDB is very simple and achieved through the use of the Set() application. Variables can exist in splendid isolation or be grouped into families. The syntax for setting a variable is:

Set(DB(family/variable)=value)

Retrieving the variable's value is equally as simple:

Set(result=${DB(family/variable)})

So, let's have a look at how we can implement a simple multi-tenant dialplan using multiple variable stores:

INT_CALL1=IAX2/username@peer_out_1/
INT_CALL2=IAX2/username@peer_out_1/
INT_CALL_LIMIT1=5 ; Limit on the number of calls
INT_CALL_LIMIT2=5 ; Limit on the number of calls
exten => _90[1-2]XXXXXXXXX,1,Set(INTCALL=INTCALL${tenantID})
exten => _90[1-2]XXXXXXXXX,n,Set(INT_CALL_LIMIT=INT_CALL_LIMIT${tenantID})
exten => _90[1-2]XXXXXXXXX,n,Macro(outdial,${INTCALL}, ${callidnum},${INT_CALL_LIMIT})

As we can see, we have been able to cut down the amount of code and make it universal for different types of users and systems. Using a macro lets us pass an ordered list of arguments. It is easiest to think of macro arguments as a list of variables since they are handled the same way.

Note

Due to the way macro is implemented, it executes the priorities contained within it via a sub-engine, and a fixed per-thread memory stack allowance. Macros are limited to seven levels of nesting. It can be possible that stack-intensive applications in deeply-nested macros could cause Asterisk to crash. Take this into account and be very careful when nesting macros.

主站蜘蛛池模板: 金川县| 杂多县| 柞水县| 井冈山市| 九寨沟县| 中宁县| 米泉市| 特克斯县| 安新县| 台安县| 收藏| 黄陵县| 雅江县| 讷河市| 横山县| 葫芦岛市| 环江| 北碚区| 孝义市| 博湖县| 无为县| 库车县| 长沙县| 宁陕县| 杭锦后旗| 四川省| 静海县| 大悟县| 靖边县| 洛浦县| 华蓥市| 昌平区| 葫芦岛市| 德保县| 普定县| 宝鸡市| 秦安县| 阿克| 榆树市| 盖州市| 天峻县|