As we left things last time, we had a nicely organised dial plan that had the minimum of duplicated code, and was essentially a set of tables that mapped endpoints to extensions or queues. Let’s remind ourselves.
[internal-extensions]
; Numeric aliases
exten => 2100,1,Goto(andyp,1)
exten => 2101,1,Goto(wife,1)
exten => 2102,1,Goto(handytone1,1)
exten => 2103,1,Goto(handytone2,1)
exten => 2200,1,Goto(residential,1)
exten => 2201,1,Goto(business,1)
; Named extensions -- endpoints named after sip.conf sections
exten => andyp,1,Gosub(stdexten,s,1(SIP/${EXTEN},${EXTEN}))
exten => andyp,hint,SIP/${EXTEN}
exten => wife,1,Gosub(stdexten,s,1(SIP/${EXTEN},${EXTEN}))
exten => wife,hint,SIP/${EXTEN}
exten => handytone1,1,Gosub(stdexten,s,1(SIP/${EXTEN},${EXTEN}))
exten => handytone1,hint,SIP/${EXTEN}
exten => handytone2,1,Gosub(stdexten,s,1(SIP/${EXTEN},${EXTEN}))
exten => handytone2,hint,SIP/${EXTEN}
; Named extensions -- ring groups
exten => residential,1,Gosub(stdqueue,s,1(${EXTEN}))
exten => business,1,Gosub(stdqueue,s,1(${EXTEN}))
[internal-residential]
include => internal-extensions
exten => _0X.,1,Dial(SIP/voiptalkRESIDENTIAL/${EXTEN})
[internal-business]
include => internal-extensions
exten => _0X.,1,Dial(SIP/voiptalkOFFICE/${EXTEN})
[external]
exten => voiptalkRESIDENTIAL,1,Goto(internal-residential,residential,1)
exten => voiptalkOFFICE,1,Goto(internal-business,business,1)
We’ll leave our endpoints behind now. I want to talk about adding facilities to our two virtual phone systems, [internal-residential]
and [internal-business]
. First, outgoing line selection. If I’m sat in the lounge and want to make a business call, I shouldn’t have to go into the office just because the business line is the outgoing line for the office extension. I want to be able to change line from the residential extension. The method uses techniques we’ve already used extensively.
[internal-residential]
include => internal-extensions
exten => _#X.,1,Goto(internal-business,${EXTEN:1},1)
exten => _0X.,1,Dial(SIP/voiptalkRESIDENTIAL/${EXTEN})
[internal-business]
include => internal-extensions
exten => _#X.,1,Goto(internal-residential,${EXTEN:1},1)
exten => _0X.,1,Dial(SIP/voiptalkOFFICE/${EXTEN})
When the extension dialled starts with a hash, these new dialplan entries simply call the same number in the other context. We’ve used ${EXTEN:1}
as the target extension to call, which makes Asterisk automatically strip of the first digit (in this case the hash) when it goes to the other context. The “other†line is now easily accessible from any extension.
Normally, when you have a standard analogue phone connected to an ATA, the ATA provides the dial tone. I prefer to have the dialtone provided by Asterisk, getting away from the control of the ATA as soon as possible – I’ve found the quality of their indication tones to be “variableâ€, and configuring the dial timeouts in different ways for different devices is a chore.
Both the HandyTone and Linksys/Sipura ATAs have this “offhook auto-dial†facility. On the HandyTone it’s simply a field on the web page. On the Linksys device, you have to specify it using a special dialplan. For example, on the SPA3000 you switch to advanced mode, then on the “Line 1†tab, near the bottom you’ll find “Dial planâ€; set that to “(S0<:disa>)
†and it will dial the “disa†extension instantly when you go off-hook. We need to provide this extension in Asterisk though.
[disa]
exten => disa,1,Answer
exten => disa,n,Disa(no-password,${CONTEXT})
[internal-residential]
include => internal-extensions
include => disa
exten => _#X.,1,Goto(internal-business,${EXTEN:1},1)
exten => _0X.,1,Dial(SIP/voiptalkRESIDENTIAL/${EXTEN})
[internal-business]
include => internal-extensions
include => disa
exten => _#X.,1,Goto(internal-residential,${EXTEN:1},1)
exten => _0X.,1,Dial(SIP/voiptalkOFFICE/${EXTEN})
I’ve added it as an “include†so that, as usual, we can avoid duplicating code merely to change a couple of parameters. The “disa†extension simply calls the Asterisk function, Disa()
with the current context as its parameter. Because the [disa]
context is included in other contexts, ${CONTEXT}
actually internal-residential
or internal-business
when it’s expanded.
The Disa()
function does exactly what we want: provides a dial tone. Our ATA can instantly call the ‘disa’ extension, and the user need never know the difference between an ATA-provided dialtone or Asterisk-provided dialtone.
asterisk1 asterisk2 asterisk3 asterisk4 asterisk5 asterisk6 asterisk7