Multiple Google Voice (and Sipgate) on Trixbox

nttranbao
Posts: 189
Member Since:
2008-02-16

Hi all,

As promised in the PM with some people, here is how I host multiple Google Voice (GV) numbers (along with corresponding Sipgate accounts -SG) separately on Trixbox CE 2.6.2.3.

In this sample you will have 2 pair of GV and SG as below:

1. GV1 forwarded to SG1. SG1 is registered on Trixbox. This pair is assigned to exten EXT1
2. GV2 forwarded to SG2. SG2 is registered on Trixbox. This pair is assigned to exten EXT2

EXT1 can both receive incoming calls and make outgoing call with GV1 uniquely. And the same with EXT2 on GV2.

This method utilizes Meetme function to bridge the calls, and 100% implemented in dialplan scripts. No FreePBX action is required.

Many thanks to Nerdvittles and pygooglevoice for the initial setup of single GV number.

PREREQUISITE:
a. pygooglevoice python script is installed. See more at http://code.google.com/p/pygooglevoice/
b. Both extension EXT1 and EXT2 belong to custom context different than "from-internal", like "from-gv-internal" in this example

HOWTO:

Step 0: Create and register 2 Sipgate trunks as below:

a. Edit sip_registration_custom.conf:

;---note that 1111111e1 is SIPID for Sipgate 1, and 2222222e1 is SIPID for Sipgate 2
register=1111111e1:SG1-password@sipgate.com/1111111e1
register=2222222e1:SG2-password@sipgate.com/2222222e1

b. Edit sip_custom.conf:

[SG1]
disallow=all
username=1111111e1
type=friend
srvlookup=yes
secret=SG1-password
qualify=yes
nat=yes
insecure=very
host=sipgate.com
fromuser=1111111e1
fromdomain=sipgate.com
dtmfmode=rfc2833
context=from-trunk
canreinvite=no
authuser=1111111e1
allow=g729


[SG2]
disallow=all
username=2222222e1
type=friend
srvlookup=yes
secret=SG2-password
qualify=yes
nat=yes
insecure=very
host=sipgate.com
fromuser=2222222e1
fromdomain=sipgate.com
dtmfmode=rfc2833
context=from-trunk
canreinvite=no
authuser=2222222e1
allow=g729

Step 1: Create 2 extension: EXT1-number and EXT2-number, assign "from-gv-internal" context for these 2 Extensions. Add in extensions_custom.conf

[from-gv-internal]
;dial 10 digit of USA phone number, no leading 1
exten => _ZXXXXXXXXX,1,NoOP(Dial USA using GV)

;if called from EXT1 => route to outgoing GV1
exten => _ZXXXXXXXXX,n,GotoIf($["${CALLERID(num)}" = "EXT1-number"]?from1)
exten => _ZXXXXXXXXX,n,GotoIf($["${CALLERID(num)}" = "EXT2-number"]?from2)


exten => _ZXXXXXXXXX,n(from1),NoOp(New call originated from EXT1 => initialize outgoing call via GV1)
exten => _ZXXXXXXXXX,n,Set(_FROMEXT=1)
exten => _ZXXXXXXXXX,n,Dial(local/1${EXTEN}@custom-gv-meetme-method)
exten => _ZXXXXXXXXX,n,Goto(finish)

;if called from EXT2 => route to outgoing GV2
exten => _ZXXXXXXXXX,n(from2),NoOp(New call originated from EXT2 => initialize outgoing call via GV2)
exten => _ZXXXXXXXXX,n,Set(_FROMEXT=2)
exten => _ZXXXXXXXXX,n,Dial(local/1${EXTEN}@custom-gv-meetme-method)
exten => _ZXXXXXXXXX,n,Goto(finish)

;finish
exten => _ZXXXXXXXXX,n(finish),Verbose(CALL FINISHED)
exten => _ZXXXXXXXXX,n,Hangup

;----------------------------------end of dial USA----------------------------

Step 2: create [custom-gv-meetme-method] in extensions_custom.conf

[custom-gv-meetme-method]

;for all pairs
; pair 1 is for EXT1:  GV1 and SG1 => FROMEXT=1
; pair 2 is for EXT2:  GV2 and SG2 => FROMEXT=2

exten => _X.,h,Hangup
exten => _X.,1,NoOp(Will call gvoice script)
exten => _X.,n,NoOp(FROMEXT is ${FROMEXT})
exten => _X.,n,GotoIf($["${FROMEXT}"="1"]?from1)
exten => _X.,n,GotoIf($["${FROMEXT}"="2"]?from2)
exten => _X.,n,Hangup

;outgoing GV call from EXT1
exten => _X.,n(from1),Set(ACCTNAME=gv1@email.com)
exten => _X.,n,Set(ACCTPASS=gv1password)
exten => _X.,n,Set(RINGBACK=SG1-number)
exten => _X.,n,Set(GVCONFNO=9001)
exten => _X.,n,MeetMeCount(9001,mmCount)
exten => _X.,n,GotoIf($["${mmCount}" = "0"]?ROOM1READY)
exten => _X.,n,Playback(no-empty-conferences)
exten => _X.,n,Hangup  ; room not ready
exten => _X.,n(ROOM1READY),AGI(gvoice.php,${ACCTNAME},${ACCTPASS},${EXTEN},${RINGBACK})
exten => _X.,n,GotoIf($["${DIALSTATUS}" = "ANSWER"]?USER)
exten => _X.,n,Answer
exten => _X.,n,SetMusicOnHold(ConnectingToneMoH) 
exten => _X.,n(USER),Set(MEETME_OPTS=AqMF)   ;A is marked, M is MoH, F is DTMF enabled in-call
exten => _X.,n,MeetMe(${GVCONFNO},${MEETME_OPTS},${PIN})
exten => _X.,n,Hangup

;outgoing GV call from EXT2
exten => _X.,n(from2),Set(ACCTNAME=gv2@email.com)
exten => _X.,n,Set(ACCTPASS=gv2password)
exten => _X.,n,Set(RINGBACK=SG2-number)
exten => _X.,n,Set(GVCONFNO=9002)
exten => _X.,n,MeetMeCount(9002,mmCount)
exten => _X.,n,GotoIf($["${mmCount}" = "0"]?ROOM2READY)
exten => _X.,n,Playback(no-empty-conferences)
exten => _X.,n,Hangup  ; room not ready
exten => _X.,n(ROOM2READY),AGI(gvoice.php,${ACCTNAME},${ACCTPASS},${EXTEN},${RINGBACK})
exten => _X.,n,GotoIf($["${DIALSTATUS}" = "ANSWER"]?USER)
exten => _X.,n,Answer
exten => _X.,n,SetMusicOnHold(ConnectingToneMoH) 
exten => _X.,n(USER),Set(MEETME_OPTS=AqMF)   ;A is marked, M is MoH, F is DTMF enabled in-call
exten => _X.,n,MeetMe(${GVCONFNO},${MEETME_OPTS},${PIN})
exten => _X.,n,Hangup

Note: As you can see here, the extension that makes outgoing GV call will be sent to its meetme room. In the meantime, we await a call-back from Google Voice via Sipgate account, which will be well handled in the next step.

Step 3: Create routes for incoming calls for these 2 GVs -> route to a custom context [custom-meetme-for-GV] for further process. Add in extensions_custom.conf:

[ext-did-custom]
;----------------------inbound routes for SGs trunks
;-----GV1
;---note that 1111111e1 is SIPID for Sipgate 1
exten => 1111111e1,1,Noop(There is an incoming call in SG1 trunk. We will route alls to [custom-meetme-for-GV] context to check and see if this is call-back or just normal incoming call)
exten => 1111111e1,n,Set(__FROM_DID=${EXTEN})
exten => 1111111e1,n,Gosub(app-blacklist-check,s,1)
exten => 1111111e1,n,ExecIf($[ "${CALLERID(name)}" = "" ] ,Set,CALLERID(name)=${CALLERID(num)})
exten => 1111111e1,n,Set(__CALLINGPRES_SV=${CALLINGPRES_${CALLINGPRES}})
exten => 1111111e1,n,SetCallerPres(allowed_not_screened)
exten => 1111111e1,n,Goto(custom-meetme-for-GV,s,1)

;-----GV2 
;---note that 2222222e1 is SIPID for Sipgate 2
exten => 2222222e1,1,Noop(There is an incoming call in SG2 trunk. We will check and see if this is call-back or just normal incoming call)
exten => 2222222e1,n,Set(__FROM_DID=${EXTEN})
exten => 2222222e1,n,Gosub(app-blacklist-check,s,1)
exten => 2222222e1,n,ExecIf($[ "${CALLERID(name)}" = "" ] ,Set,CALLERID(name)=${CALLERID(num)})
exten => 2222222e1,n,Set(__CALLINGPRES_SV=${CALLINGPRES_${CALLINGPRES}})
exten => 2222222e1,n,SetCallerPres(allowed_not_screened)
exten => 2222222e1,n,Goto(custom-meetme-for-GV,s,1)

Step 4: Create context [custom-meetme-for-GV] to check and route to different destination between normal incoming call and "call-back" one. Add in extensions_custom.conf:

[custom-meetme-for-GV]
; this context is for routing incoming calls via desired SG trunks based on DID.
; then if CALLERID(number) matches SG's GV Number, then it is call back -> send to Meetme
; if not, then it is normal incoming call, route to desired extension (EXT1 or EXT2)
; we use "FROMEXT" variables
; pair 1 is for GV1 => SG1 => FROMEXT=1, MeetmeRoom = 9001
; pair 2 is for GV2 => SG2 => FROMEXT=2, MeetmeRoom = 9002

;DID is blank by default, so we can only distingush SG channel by CALLERID(name), which is set to SG number
; CALLERID(number) is normal (set to caller phone number)
exten => s,1,NoOp(Start to distinguish between call-back and normal incoming call)
exten => s,n,NoOp(DID is ${DID} - CALLERID(name) is ${CALLERID(name)})
exten => s,n,GotoIf($["${CALLERID(name)}"="SG1-Number"]?label1)
exten => s,n,GotoIf($["${CALLERID(name)}"="SG2-number"]?label2)
exten => s,n,Hangup
;incoming call on GV1
exten => s,n(label1),Wait(0)
exten => s,n,Set(GVNUM=GV1-number)
exten => s,n,NoOp(**CALLERID: ${CALLERID(num)}) ; for debug
exten => s,n,GotoIf($["${CALLERID(num)}"="${GVNUM}"]?iscallback1:normal1)
exten => s,n(iscallback1),Goto(custom-conference-script,9001,1) ; this incoming is call-back -> route to meetme script
; at this step, incoming calls are normal => route to extension EXT1
exten => s,n(normal1),Goto(from-gv-internal,EXT1-number,1)
exten => s,n,Hangup


;incoming call on GV2
exten => s,n(label2),Wait(0)
exten => s,n,Set(GVNUM=GV2-number)
exten => s,n,NoOp(**CALLERID: ${CALLERID(num)}); for debug
exten => s,n,GotoIf($["${CALLERID(num)}"="${GVNUM}"]?iscallback2:normal2) 
exten => s,n(iscallback2),Goto(custom-conference-script,9002,1) ; this incoming is call-back -> route to meetme script
;at this step, incoming calls are normal => route to extension EXT2
exten => s,n(normal2),Goto(from-gv-internal,EXT2-number,1) 

Step 5: create custom script to join Meetme room. Add in extensions_custom.conf

[custom-conference-script]
;-------------------------------------------------------------------------
exten => STARTMEETME,1,MeetMe(${MEETME_ROOMNUM},${MEETME_OPTS},${PIN})
exten => STARTMEETME,n,Hangup
exten => h,1,Hangup


;-------------------------------------------------------
exten => 9001,1,Macro(user-callerid,)
exten => 9001,n,Set(MEETME_ROOMNUM=9001)
; check if room available. If not, hangup.
; incase user hangup right just after dialing
exten => 9001,n,MeetMeCount(9001,mmCount)   
exten => 9001,n,NoOP(mmCount for conf 9001 is : ${mmcount}) ; for debug
exten => 9001,n,GotoIf($["${mmCount}" = "1"]?ROOMREADY)
exten => 9001,n,Hangup  ; room not ready
exten => 9001,n(ROOMREADY),GotoIf($["${DIALSTATUS}" = "ANSWER"]?USER)
exten => 9001,n,Answer
exten => 9001,n,Wait(1)
exten => 9001,n(USER),Set(MEETME_OPTS=qx)
exten => 9001,n,Goto(STARTMEETME,1)

;----------------------------------------------------------
exten => 9002,1,Macro(user-callerid,)
exten => 9002,n,Set(MEETME_ROOMNUM=9002)
; check if room available. If not, hangup.
; incase user hangup right just after dialing
exten => 9002,n,MeetMeCount(9002,mmCount)   
exten => 9002,n,NoOP(mmCount for conf 9002 is : ${mmcount}) ; for debug
exten => 9002,n,GotoIf($["${mmCount}" = "1"]?ROOMREADY)
exten => 9002,n,Hangup  ; room not ready
exten => 9002,n(ROOMREADY),GotoIf($["${DIALSTATUS}" = "ANSWER"]?USER)
exten => 9002,n,Answer
exten => 9002,n,Wait(1)
exten => 9002,n(USER),Set(MEETME_OPTS=qx)
exten => 9002,n,Goto(STARTMEETME,1)

Step 4: Creat meetme room. Add in meetme.conf

[rooms]
#include meetme_additional.conf
;add by nttranbao  ;  9001 GV1;  9002 GV2
conf => 9001
conf => 9002

DONE.

--

----------------------
IT/VOIP consultancy, VOIP eStore, Support Forum
Bao Nguyen IT Co., Ltd.
http://www.baonguyen.vn
WE MAKE IT