3.1. Programming "How-to"

A major challenge in writing a book like this one is that every reader comes to it with a different level of previous experience. A book on Asterisk might be read by administrators, programmers, telephone specialists, and hobbyists, all with different levels of practical experience. To take full advantage of Asterisk, a basic level of programming skill and a grasp of the fundamentals is necessary. Through this how-to, we hope to provide the newcomer with the basic understanding needed to make useful dialplans, through the use of plenty of examples and with frequent reference to Appendix B, Applications in the dialplan. You will probably recognize some of the material from other chapters. This little how-to should give you the overview you need to get started.

Program structure

Each telephone number defined in the Asterisk dialplan (/etc/asterisk/extensions.conf) is really a small program. In Asterisk, the program is called an "extension." An extension looks like this:
exten => 1001,1,Answer()
exten => 1001,n,Playback(hello-world)
exten => 1001,n,Hangup()
Priorities may also numbered sequentially:
exten => 1001,1,Answer()
exten => 1001,2,Playback(hello-world)
exten => 1001,3,Hangup()
The two extensions depicted here are functionally identical. If you use n, however, it makes adding and deleting entries in the extension much easier later on.

Variables

Use the application Set() to create and change variables:
exten => 1002,1,Set(Favoriteanimal = "Tiger")
exten => 1002,n,Set(Favoritenumber = 23)
Use the syntax ${VARIABLENAME} to read and print variables. You can print variable values on the CLI with NoOp() (with verbosity level 3 and up):
exten => 1003,1,NoOp(${Favoriteanimal})
exten => 1003,n,NoOp(${Favoritenumber})
There are different kinds of variables:
  • Global variables
    Valid anywhere in the dialplan and created or modified with Set(<variable>=<content>,g):
    exten => 1004,1,Set(READABLEANYWHERE = 23,g)
    exten => 1004,n,NoOp(${READABLEANYWHERE})
  • Channel variables
    Valid only in the current channel (a channel could be a connection between two people having a phone conversation). Created or modified with Set(<variable>=<content>) (without the g):
    exten => 1005,1,Set(READABLEHEREONLY= 42)
    exten => 1005,n,NoOp(${READABLEHEREONLY})
  • System variables
    These dynamic variables are set by Asterisk and may be called in the dialplan without needing to create them. A frequently used system variable is ${EXTEN}:
    exten => 1006,1,NoOp(Dialed number: ${EXTEN})

Labels and Goto()

Goto() lets you jump from one dialplan entry to another. If you are using n priorities, this can be problematic. The solution is to use labels to tag specific entries and then call the entry by label in Goto().
Examples:
  • Within an extension:
    exten => 1007,1,Answer()
    exten => 1007,n(Start),Wait(1)
    exten => 1007,n,Playback(hello-world)
    exten => 1007,n,Goto(Start)
  • Between extensions:
    exten => 1008,1,Answer()
    exten => 1008,n,Goto(1009,Ping)
    
    exten => 1009,1(Ping),Playback(hello-world)
    exten => 1009,n,Wait(2)
    exten => 1009,n,Goto(1010,Pong)
    
    exten => 1010,1(Pong),Playback(tt-weasels)
    exten => 1010,n,Wait(2)
    exten => 1010,n,Goto(1009,Ping)
  • Between contexts:
    [hq]
    exten => 1011,1,Answer()
    exten => 1011,n,Playback(hello-world)
    exten => 1011,n,Goto(sales,1012,1)
    
    [sales]
    exten => 1012,1,Playback(hello-world)
    exten => 1012,n,Hangup()

While() loops

Use While() to run loops in the dialplan:
exten => 1013,1,Answer()
exten => 1013,n,Set(i=1)
exten => 1013,n,While($[${i} < 10])
exten => 1013,n,SayNumber(${i})
exten => 1013,n,Wait(1)
exten => 1013,n,Set(i=$[${i} + 1])
exten => 1013,n,EndWhile()
exten => 1013,n,Hangup()

GotoIf() conditional

You can jump to other parts of the dialplan depending on a specific condition being met with GotoIf():
exten => 1014,1,Answer()
exten => 1014,n,Set(Favoritestation = 0815)
exten => 1014,n,NoOp(Check to see if ${Favoritestation} is calling.)
exten => 1014,n,GotoIf($[${CALLERID(num) = ${Favoritestation}]?yes,no)

exten => 1014,n(yes),Playback(hello-world)
exten => 1014,n,Hangup()

exten => 1014,n(no),Playback(tt-monkeys)
exten => 1014,n,Hangup()

Gosub() subroutines

With Gosub() the call is directed to a subroutine; it can be returned to the intiating priority with Return() wieder zurück:
exten => 1015,1,Gosub(cid-set)
exten => 1015,n,Dial(SIP/${EXTEN})

exten => 1015,n(cid-set),Set(CALLERID(all)=Apfelmus GmbH <012345678>)
exten => 1015,n,Return()