Unlimited Incoming/Outgoing cellphone calls with
Asterisk
Part 3, examples of my setup.
Note that your setup may be different than mine, this is just how I set things up. Also, while it
works for me, there may be better ways to do what I've done (in fact, I know I have used some
deprecated functions which still work now, but may be removed later). This should help to get you up
and running, but please look into what these settings do and tailor it to your own needs.
Ok, first I needed a number that I could call from my cellphone and would receive DTMF (remember,
cellphone to cellphone did not pass DTMF). I also did not want to pay for another line, and needed a
unique line used solely for calling in via cellphone. I used an IPKall number at www.ipkall.com. Normally you'd setup a FWD number first and have your
IPKall number forwarded to it, but that would introduce an extra point of failure that I did not want.
I setup my IPKall number to forward directly to my server. To do this you will need either a static
ip, or a dynamic dns address. I have a dynamic ip, so I signed up for a dyndns account, and run a
client on my server that checks the current ip and updates as necessary. Setting this up is beyond the
scope of this howto, but suffice to say that you need a number setup that you can call from your
cellphone and enter in some dtmf digits.
This isn't necessary, but I have used variables in several places in my extensions.conf. This makes it
very easy to make broad changes, such as changing my primary long-distance provider, or adding a new
ata. Here's a list of variables that are used later in the examples:
LD1=IAX2/username:[email protected]
LD2=IAX2/username:[email protected]
My primary (LD1) and secondary (LD2) long-distance providers. The first is voxee, and costs
1.1cents/minute. The second is voicepulse, which costs 2.9cents/minute. Voicepulse seems to be more
reliable, but is more expensive. In my dialplan, it tries voxee first, then voicepulse, so unless both
are down all calls will go through.
HOURS=07:59-16:00|sun-sat|*|*?asleep|s|1
Variable used with GotoIfTime, this matches during the hours of 7:59AM to 4:00PM, every day, and sends
the caller to the [asleep] context, the s extension (s for start), and priority 1. Unless you're a
night person like we are, you will probably want to change the hours to match during the night, instead
of during the day.
HOURSCELL=06:50-21:10|mon-fri|*|*?
This matches between the hours of 6:50AM to 9:10PM, Monday through Friday. This is when the cellphone
uses anytime minutes, all other times it's nights and weekends and long-distance calls are free. I did
not set the context, extension, or priority here, but did so later on when this variable was used (you
can set this anywhere you want, I'm just explaining why my extensions.conf looks the way it
does). BTW, my nights and weekends is from 9PM to 7AM, but I don't trust the cellphone
company's clock to be as accurate as mine, so I gave them an extra ten minutes (in this setup,
nights and weekends starts at 9:10AM and ends at 6:50AM, if Cingular is more than ten minutes
off there's something wrong).
ALLPHONES=SIP/103&SIP/104&SIP/105&SIP/106
The last variable, this is a list of my sip phones. You won't need to use this, but is included here
for completeness. The samples given are pulled directly from my working setup.
Ok, on to the good stuff! Notice that I will have all entries in extensions.conf in bold, and any
comments are preceded by a semicolon (you may leave the comments in if you wish, asterisk will ignore
them, but they aren't necessary). Also note that I have a lot of NoOp commands scattered throughout.
I put them there so I could add additional commands later, and not have to reorder all my priorities (I
began with one NoOp in between each actual command, you can tell where I have had to go back and add
more commands in). BTW, NoOp stands for No Operation, it's just a placeholder.
Here's the context for the incoming line. The extension is 777 in my case, but it could also be s, or
the actual number, or any number of other things in your particular setup.
[inbound]
exten => 777,1,NoOp
exten => 777,2,Wait(1)
exten => 777,3,NoOp
exten => 777,4,Answer
exten => 777,5,NoOp
exten => 777,6,SetCIDNum(${CALLERIDNUM})
;We get the callerid number of the calling party
exten => 777,7,Wait(1)
exten => 777,8,DigitTimeout,5
exten => 777,9,NoOp
exten => 777,10,Read(dncdigitsa,custom/please-enter,11,s)
;We are going to read the dtmf digits entered, store them in a variable called dncdigitsa,
;and will read up to 11 digits (any past 11, we ignore). We wait up to five seconds between
;digits. Once five seconds is up we assume the caller is done entering the number. Each
;time they press a button, this five second timeout is restarted. The prompt played is
;called "please-enter" and is in the "custom" sounds directory.
exten => 777,11,Set(dncdigitsb=${dncdigitsa:-10})
;This takes the number entered, takes the last ten digits, and saves that in a variable
;called digitsb. It seems a bit silly, especially when you see the next line.
exten => 777,12,Set(dncdigits=1${dncdigitsb})
;Here, we create a new variable called dncdigits, and set it to 1 plus the value of
;dndigitsb. So, why did we strip the 1 off the number, just to add it back? Well, we didn't
;actually strip off the 1, we just took the last ten digits. If you dial 1 + area code +
;number, then you have eleven digits. Take the last ten, and you have area code + number.
;Add a 1 in front, and you have 1 + area code + number. But what if you let other people
;use this system, people who aren't used to dialing a 1 in front of the area code? If they
;dial area code + number, and you take the last ten digits, you are left with area code +
;number. Add a 1 in front, and you have 1 + area code + number. It's just a hack to insure
;you end up with 1 + area code + number, whether the caller remembered to dial the 1 in
;front. I call this the "Aunt Sue" code.
exten => 777,13,Playback(you-entered,s)
exten => 777,14,Saydigits(${dncdigits:0:1})
;This says the digits, skipping 0 numbers, and reading 1
exten => 777,15,Wait(0.5)
;This puts in a pause of half a second, makes the number easier to understand when read back
exten => 777,16,Saydigits(${dncdigits:1:3})
;This says the digits, skipping 1 number, and reading the next 3 (in this case, the area
;code)
exten => 777,17,NoOp
exten => 777,18,Wait(0.5)
exten => 777,19,NoOp
exten => 777,20,Saydigits(${dncdigits:4:3})
;This says the digits, skipping 4 numbers, and reading the next 3 (the prefix)
exten => 777,21,NoOp
exten => 777,22,Wait(0.5)
exten => 777,23,NoOp
exten => 777,24,Saydigits(${dncdigits:7:4})
;This says the digits, skipping 7 numbers, and reading the next 4 (the last of the number)
exten => 777,25,NoOp
exten => 777,26,Wait(0.5)
exten => 777,27,NoOp
exten => 777,28,BackGround(custom/correct)
;Another custom prompt named "correct"; it asks the caller if this was correct press 1,
;otherwise press 2.
exten => 777,29,NoOp
exten => 777,30,DigitTimeout(1)
;We're only looking for one digit, so as soon as one digit (a 1 or 2 in our case) we're done
exten => 777,31,NoOp
exten => 777,32,ResponseTimeout,10
;Give them up to 10 seconds before giving up
exten => 777,33,NoOp
exten => 777,34,NoOp
exten => 777,35,NoOp
exten => 1,1,Goto(inbound-success,s,1)
;They pressed 1, so we go to extension 1. Extension 1 sends us to the [inbound-success]
;context, extension s, priority 1. Why do this? Because we need to do some further processing
;on the call after we hangup. If we stay in this context, then the call file we want to create
;will get created whenever the call is hungup, whether the user dialed 1, or got frustrated and
;hung up, etc. We only want to process the call file if the user pressed 1 and hung up.
exten => 2,1,Goto(inbound,777,7)
;Well, something messed up and we didn't get the number they wanted to dial correctly
;(maybe fat fingers, maybe a bad connection and the some dtmf tones didn't make it
;through). We stay in the [inbound] context, and go back to the 777 extension, priority 7
;(just before we ask them to enter the number they wish to reach).
exten => t,1,Playtones(congestion)
exten => t,2,Wait(5)
exten => t,3,Hangup
;"t" is the timeout extension, used if we prompt the user to enter some digits but they
;don't respond in a timely fashion. Here we play congestion tones for 5 seconds, then
;hangup.
[inbound-success]
exten => s,1,NoOp
exten => s,2,Playback(custom/connected-soon,s)
;Another custom prompt, letting the caller know that they should hang up and their call
;will be connected soon
exten => s,3,Wait(1)
exten => s,4,Hangup
;Of course there will be those that don't hangup, so we hang up for them. Once the line has
;been hung up, we go to the "h" extension below.
exten => h,1,NoOp
exten => h,2,NoOp
exten => h,3,System(echo channel: Local/1${CALLERIDNUM}@cell-out/n > /tmp/${CALLERIDNUM})
;The channel we want to call the user back on. A 1 is added to the callerid number, since
;IPKall (and most, but not all, other providers) present callerid as area code + number.
exten => h,4,System(echo MaxRetries: 0 >> /tmp/${CALLERIDNUM})
;MaxRetries is set to 0. This means if it doesn't succeed on the first attempt, it won't
;try again. This way, the user will know it failed in less than a minute, and can just dial
;the number directly. Obviously something has failed, or asterisk is using the local cellphone
;for another call.
exten => h,5,System(echo context: main >> /tmp/${CALLERIDNUM})
;The context we want to use to dial the number the user entered
exten => h,6,NoOp
exten => h,7,System(echo extension: ${dncdigits} >> /tmp/${CALLERIDNUM})
;Here we set the extension to be dialed to equal the number that the user entered
exten => h,8,NoOp
exten => h,9,System(echo priority: 2 >> /tmp/${CALLERIDNUM})
;We'll jump to priority 2, instead of priority 1. Not necessary, but in my setup priority 1
;sets the callerid number to be used for the outgoing long-distance calls (and for calls
;which are local, it's just a NoOp line). We skip this, so that asterisk will use the
;callerid number we assign below. This way we use only one extension for outgoing long-
;distance calls, and if we call from a regular line connected to asterisk callerid gets
;set to an appropriate number, and if we call from an outside cellular phone callerid
;gets set to that cellular number. Really not necessary, unless you let other people
;use their cellphone with your setup (which I do).
exten => h,10,NoOp
exten => h,11,System(echo Callerid: ${CALLERIDNUM} >> /tmp/${CALLERIDNUM})
;We set the callerid to be the callerid we received from the caller's phone
exten => h,12,NoOp
exten => h,13,System(echo sleep 5 > /tmp/${CALLERIDNUM}.2)
;Sleep for 5 seconds, give the other end a time to completely end the call before we call
back
exten => h,14,NoOp
exten => h,15,System(echo cp /tmp/${CALLERIDNUM} /var/spool/asterisk/outgoing >> /tmp/${CALLERIDNUM}.2)
exten => h,16,NoOp
exten => h,17,System(chmod 775 /tmp/${CALLERIDNUM}.2)
exten => h,18,NoOp
exten => h,19,System(/tmp/${CALLERIDNUM}.2)
exten => h,20,NoOp
exten => h,21,Hangup()
;Why hangup an extension that's already hung up? I dunno, but that's what I had and it
;works *shrug*
That's pretty much it right there. Just make sure you have the proper extensions in the [main] context
to handle 1 + area code + number calls, and this part is done! Just for reference, here's the relevant
part of my [main] context:
[main]
exten => _1NXXNXXXXXX,1,SetCallerID(9315551212)
;I set my callerid number here. When the call file is created, it skips this line and jumps
;right to priority 2 below
exten => _1NXXNXXXXXX,2,NoOp
exten => _1NXXNXXXXXX,3,NoOp
exten => _1NXXNXXXXXX,4,SetVar(CALLFILENAME=${TIMESTAMP}-${CALLERIDNUM}-${EXTEN})
;This is where I setup the name of the file for the recorded call. Not necessary.
exten => _1NXXNXXXXXX,5,NoOp
exten => _1NXXNXXXXXX,6,GotoIfTime(${HOURSCELL}main|${EXTEN}|10)
;If the time is between 6:50AM and 9:10PM, we're sent to the [main] context, extension
;stays the same, and we goto priority 10. Basically, we're skipping priority 8 below and going
;straight to priority 10.
exten => _1NXXNXXXXXX,7,NoOp
exten => _1NXXNXXXXXX,8,Goto(cell-out,${EXTEN},1)
;Woohoo, we didn't jump to priority 10, so it must be nights and weekends! No need to pay
;for long-distance calls, we'll just make them through the local cellphone. Party time!
exten => _1NXXNXXXXXX,9,NoOp
exten => _1NXXNXXXXXX,10,Monitor(gsm,${CALLFILENAME},m)
;Crap, it must be between 6:50AM and 9:10PM on a Monday through Friday, so we were sent to
;priority 10. Here, we start recording the call (again, not necessary).
exten => _1NXXNXXXXXX,11,NoOp
exten => _1NXXNXXXXXX,12,Dial(${LD1}/${EXTEN})
exten => _1NXXNXXXXXX,13,NoOp
exten => _1NXXNXXXXXX,14,Dial(${LD2}/${EXTEN})
exten => _1NXXNXXXXXX,15,NoOp
exten => _1NXXNXXXXXX,16,Congestion
exten => _1NXXNXXXXXX,113,NoOp
exten => _1NXXNXXXXXX,114,Dial(${LD2}/${EXTEN})
exten => _1NXXNXXXXXX,115,Congestion
;Just dialing one long-distance provider, and if that fails try the other.
[cell-out]
exten => _1NXXNXXXXXX,1,NoOp
exten => _1NXXNXXXXXX,2,NoOp
exten => _1NXXNXXXXXX,3,NoOp
exten => _1NXXNXXXXXX,4,SetGroup(cellout)
exten => _1NXXNXXXXXX,5,CheckGroup(1)
exten => _1NXXNXXXXXX,6,Dial(BLT/Motorola/${EXTEN})
exten => _1NXXNXXXXXX,7,NoOp
exten => _1NXXNXXXXXX,8,Dial(${LD1}/${EXTEN})
exten => _1NXXNXXXXXX,9,NoOp
exten => _1NXXNXXXXXX,10,Dial(${LD2}/${EXTEN})
exten => _1NXXNXXXXXX,11,NoOp
exten => _1NXXNXXXXXX,12,Congestion
exten => _1NXXNXXXXXX,106,NoOp
exten => _1NXXNXXXXXX,107,NoOp
exten => _1NXXNXXXXXX,108,Dial(${LD1}/${EXTEN})
exten => _1NXXNXXXXXX,109,Congestion
exten => _1NXXNXXXXXX,209,NoOp
exten => _1NXXNXXXXXX,210,Dial(${LD2}/${EXTEN})
exten => _1NXXNXXXXXX,211,Congestion
This could be bad, if someone calls in and the cellphone is busy, it'll try to dial them using the
long-distance line. We need some kind of fallback though, in case this is used from a local extension
during nights and weekends. It's an easy fix, I just haven't done it yet.
To be continued.
Questions? Ask in the
forum or
email me.
For the Privacy Policy, click
here. | |