Keep it simple
Sometimes making things more complicated than they need to be because it sounds awesome is really fun. However, when it really comes down to it simplifying things is the way to go.
Sometimes making things more complicated than they need to be because it sounds awesome is really fun. However, when it really comes down to it simplifying things is the way to go.
After my monthly billing for my Internet and Phone service rose $25 dollars in one month, sending my fees for Internet and phone from $75 to $98, I decided that it was time to buckle down and work on something that I had been thinking about for a long time. Zero dollar per year phone service including long distance. The goal was building a highly functioning personal VOIP environment to entirely replace my traditional land line phone service and include complete integration with Google Voice. My monthly fees were pulled back down to a more manageable $60 dollars for Internet and a purely basic local only phone line with no frills because the bundled package was still cheaper than just Internet. More for less go figure. My phone feature frills are handled elsewhere now.
What I’ve ended up with is Asterisk configured as my PBX, all extensions are currently SIP VOIP users, with registered trunks to Gizmo5 for each Google Voice account I want to integrate. Google Voice dialing can be done straight from the client/phone which means there is no need to initiate the call manually from the Google Voice webpage. I just assign a unique extension per account and within the dial plan call the script gvoice provided by pygooglevoice using System() to complete the call. More details on that later.
Inspired by an article I read here there was enough detail to get things started. There are many limitations to the details described in that article but I’ve been able to work through most of them over the past week and I think I’ve made some excellent improvements. Two things that I was able to improve on are your outgoing calls do not depend on Gizmo’s 3 minutes free/outgoing minutes charges and dialing directly from the web is no longer high jacked by a potentially non-existent parked line on incoming calls from your Google account.
I will make the assumption here that you already have Asterisk installed, you’ve configured pygooglevoice to be usable on the asterisk server and that you have a Google Voice account. There are many other posts out there on the Internet that cover getting asterisk up and running. When I began to install my asterisk environment I tried to use FreePBX but really felt as though it was in my way. I could never get things working using it. I’m sure that it has it’s place and works well, most other posts about configuring asterisk and out of the box Linux PBX distributions use it, but it was not working for me. Not understanding yet what it took to make asterisk work probably was the main issue with not being able to use it. Instead I just wrote the config files for asterisk manually. The two most important configuration files in this discussion are extensions.conf (where the dial plans and dirty stuff goes on) and sip.conf (user accounts, SIP registrations and sip configuration).
There are two important configurations to get asterisk off the ground. User accounts for SIP users and Dial plans defined for system extensions. The first is created in the file sip.conf and the later in extensions.conf. Things to keep in mind here that come in handy later are setting useful context and defining your user sections [phone1], [GizmoUser1] etc..
Let’s set up the basics. Two sip accounts and extensions to allow them to be dialed.
sip.conf
[1111]
type=friend
context=from-internal
host=dynamic
secret=URPASSWORD
callerid=User1 <1111>
canreinvite=yes
dtmfmode=auto
disallow=all
allow=ulaw
;allow=ilbc
callingpres=allowed_passed_screen
[2222]
type=friend
context=from-internal
nat=yes
host=dynamic
secret=URPASSWORD
callerid=User2 <2222>
canreinvite=yes
dtmfmode=auto
disallow=all
allow=ulaw
;allow=ilbc
callingpres=allowed_passed_screen
extension.conf – notice that above we defined these accounts within the context=from-internal so extensions must be associated with that context.
[from-internal] exten => 1111,1,Dial(SIP/1111,120,t) exten => 1111,n,Macro(fastbusy) exten => 2222,1,Dial(SIP/2222,120,t) exten => 2222,n,Macro(fastbusy)
Next we define how we’re are going to go about communicating with Gizmo5 (sipphone.com). This happens in sip.conf in two places.
First we register with the network. The key here is that if you have multiple accounts that you are registering make sure to define their context with /CONTEXT at the end of the register entry. This allows you to uniquely identify incoming calls from the separate accounts later in extensions.conf.
register => 1747XXXXXXX:PASSWORD@proxy01.sipphone.com/GizmoAct1
register => 1747XXXXXXX:PASSWORD@proxy01.sipphone.com/GizmoAct2
Next we define a sip user for each account. Again notice here the context is set as from-google this is important for all incoming calls coming from these accounts when we configure the dial plans.
It would make sense here to name them in a way that tie to the register entries. i.e. GizmoUser1 <-> GizmoAct1
[GizmoUser1] type=friend context=from-google disallow=all allow=ulaw ;allow=ilbc dtmfmode=rfc2833 host=proxy01.sipphone.com fromdomain=proxy01.sipphone.com insecure=port,invite ;qualify=yes fromuser=1747XXXXXXX authuser=1747XXXXXXX username=1747XXXXXXX secret=PASSWORD canreinvite=yes [GizmoUser2] type=friend context=from-google disallow=all allow=ulaw ;allow=ilbc dtmfmode=rfc2833 host=proxy01.sipphone.com fromdomain=proxy01.sipphone.com insecure=port,invite ;qualify=yes fromuser=1747XXXXXXX authuser=1747XXXXXXX username=1747XXXXXXX secret=PASSWORD canreinvite=yes
Alright back to extensions.conf, here are the good bits in my opinion.
Set some global variables for the various accounts, some bits and pieces regarding where you’re going to park calls while the gvoice script goes and does it’s thing, account information so it’s easily reused and anything else that seems exciting.
[globals] ; LOCAL CONFIGURATION MYGOO-ACCTNAME=mygoogle@gmail.com MYGOO-ACCTPASS=PASSWORD MYGOO-GVNUM= MYGOO-RINGBACK=1747XXXXXXX ; Gizmo DID MYGOO-ISPARK=0 MYGOO-CALLPARK=705 OTHERGOO-ACCTNAME=othergoogle@gmail.com OTHERGOO-ACCTPASS=PASSWORD OTHERGOO-GVNUM= OTHERGOO-RINGBACK=1747XXXXXXX OTHERGOO-ISPARK=0 OTHERGOO-CALLPARK=706
Create a unique dial extension for your accounts so that the outgoing is associated with the right Google Voice account.
[GizmoAct1-google-out]
exten => _8.,1,Dial(local/${EXTEN:1}@GizmoAct1-google-voice,300)
[GizmoAct2-google-out]
exten => _9.,1,Dial(local/${EXTEN:1}@GizmoAct2-google-voice,300)
Define what happens when the call is made. Here we initiate the call to @GizmoAct1-google-voice, play back a message, poke Google Voice using the gvoice script to us call back and park the call. I set a global variable here, ISPARK, to indicate that this call was generated from my SIP client and parked. This helps fix an issue with the other dial plan examples that I found where the ability to initiate calls from the web would break and treat every incoming call from Google Voice the same and try to attach it to an existing parked call even if that parked call did not exist. You see later that I check for the ISPARK flag.
[GizmoAct1-google-voice]
exten => _X.,1,Wait(5)
exten => _X.,n,Playback(wait-moment)
exten => _X.,n,System(gvoice -e ${MYGOO-ACCTNAME} -p ${MYGOO-ACCTPASS} call ${EXTEN} ${MYGOO-RINGBACK})
exten => _X.,n,Set(GLOBAL(MYGOO-ISPARK)=1)
exten => _X.,n,Set(PARKINGEXTEN=${MYGOO-CALLPARK})
exten => _X.,n,Park()
exten => _X.,n,Hangup
[GizmoAct2-google-voice]
exten => _X.,1,Wait(5)
exten => _X.,n,Playback(wait-moment)
exten => _X.,n,System(gvoice -e ${OTHERGOO-ACCTNAME} -p ${OTHERGOO-ACCTPASS} call ${EXTEN} ${OTHERGOO-RINGBACK})
exten => _X.,n,Set(GLOBAL(OTHERGOO-ISPARK)=1)
exten => _X.,n,Set(PARKINGEXTEN=${OTHERGOO-CALLPARK})
exten => _X.,n,Park()
exten => _X.,n,Hangup
Once that happens and your original call is parked you should hear the wonderful hold music you configured for your asterisk environment. gvoice has fired, logs into Google Voice and has initiated the call back to your Gizmo DID which immediately comes back into your own PBX. Otherwise, someone has called your Google Voice number and you are receiving the incoming call or you’ve started a call from the web. So we have to figure out what to do with the incoming call. These calls come in via the from-google context.
[from-google]
include => from-internal
exten => GizmoAct1,1,Wait(1)
exten => GizmoAct1,n,Set(GVNUM=${MYGOO-GVNUM})
exten => GizmoAct1,n,NoOp(**CALLERID: ${CALLERID(number)})
; does the call come from our Google voice caller id and is there a parked call
*** line breaks here for blog readability ***
exten => GizmoAct1,n,
GotoIf($[$["${CALLERID(number)}"="${MYGOO-GVNUM}"]
& $["${MYGOO-ISPARK}" = "1"]]?gopark:direct)
*** line breaks here for blog readability ***
exten => GizmoAct1,n(gopark),Set(GLOBAL(MYGOO-ISPARK)=0)
exten => GizmoAct1,n(gopark),ParkedCall(${MYGOO-CALLPARK})
; otherwise it's a direct call.
exten => GizmoAct1,n(direct),Dial(SIP/2222,120,t)
exten => GizmoAct1,n(direct),Goto(GizmoAct1-next-${DIALSTATUS},1)
; first line is unavailable try the next extension
exten => GizmoAct1-next-CHANUNAVAIL,1,Dial(SIP/2222,120,t)
exten => GizmoAct1-next-.,n,NoOp
exten => GizmoAct2,1,Wait(1)
exten => GizmoAct2,n,Set(GVNUM=${OTHERGOO-GVNUM})
exten => GizmoAct2,n,NoOp(**CALLERID: ${CALLERID(number)})
*** line breaks here for blog readability ***
exten => GizmoAct2,n,
GotoIf($[$["${CALLERID(number)}"="${OTHERGOO-GVNUM}"]
& $["${OTHERGOO-ISPARK}" = "1"]]?gopark:direct)
*** line breaks here for blog readability ***
exten => GizmoAct2,n(gopark),Set(GLOBAL(OTHERGOO-ISPARK)=0)
exten => GizmoAct2,n(gopark),ParkedCall(${OTHERGOO-CALLPARK})
exten => GizmoAct2,n(direct),Dial(SIP/1111,120,t)
And there you have it.
Here are full examples of sip.conf and extensions.conf which should pull it all together.
You’ll notice there is a dial plan and extension in there called GizmoAct1-land-google-callback which is an example of dialing a phone number from a SIP extension that rings back to an existing land line outside of your asterisk network. This allows for an existing phone line to be included into your PBX without having to configure it as a zap device. When you read the configuration it should make sense and it works well, dial from SIP line and walk away, rings back to land line which you answer and the call connects, SIP line hangs itself up.
rinse, repeat, serve hot with a double shot of espresso.