En aquest post us comentaré com tinc muntat el dialplan al Asterisk de casa. Pot servir com a exemple de qualsevol instal·lació de VoIP domèstica: una màquina linux amb Asterisk, dues targetes x100p una connectada a una línia convencional (menta) amb trucades nacionals gratuïtes, i l'altra connectada a un trunk GSM amb un mòbil (movistar) de prepagament.

A part d'això tenim varies opcions per fer trucades per VoIP, que resumeixo a continuació:

  • VoipJet: El proveïdor amb terminació IAX més econòmic que hem trobat.

  • VoipBuster: Un altre proveïdor amb terminació IAX, una mica més car que l'anterior però que permet trucar gratis a fixes d'Espanya i varis països més.

  • VoIP User: Proveïdor amb terminació SIP que ofereix trucades gratuïtes a fixes de varis països.

  • Free World DialUP: Proveïdor amb terminació IAX que permet trucar gratuïtament a altres membres d'aquest proveïdor, a clients de Voz Telecom i a telèfons toll-free de varis països.

  • Free World DialOut: Xarxa d'intercanvi de trucades amb terminació IAX. Permet fer trucades gratuïtes a altres països, a canvi de que nosaltres deixem que gent de fora les faci per la nostra línia (nacionals a través de menta que ens surt gratis).

  • Adam: Proveïdor espanyol amb terminació SIP que ofereix trucades gratuïtes entre els usuaris d'aquest proveïdor i altres xarxes.

Introducció

El dialplan es configura al fitxer /etc/asterisk/extensions.conf. Primer definim una serie de paràmetres de configuració generals i variables globals. Fixeu-vos que al Asterisk tinc 3 usuaris (l'Esteve, el Diego i jo), i que compartim el mateix account als proveïdors gratuïts, però tenim comptes separats per als proveïdors de pagament, així cadascú controla el que gasta per separat.

[general]
static=yes
writeprotect=yes

[globals]
; Some global vars
POFMOV=656xxxxxx
ESTEVEMOV=636xxxxxx
DIEGOMOV=677xxxxxx
; VoipJet accounts
POFVOIPJET=xxxx
ESTEVEVOIPJET=xxxx
DIEGOVOIPJET=xxxx
; Free World DialOUT
POFFWDOUT=xxxx
[email protected]
; Free World DialUP Settings
FWDNUMBER=646499                                ; your calling number
FWDCIDNAME=646499                               ; your caller id
FWDPASSWORD=xxxx                                ; your password
FWDRINGS=sip/200                                ; the phone to ring
FWDVMBOX=200                                    ; the VM box for this user

Evidentment les xxxx van substituïdes pels corresponents números de telèfon o passwords. Això només son variables, per no haver d'escriure cada cop el meu telèfon, posteriorment utilitzo ${POFMOV}.

Macros

A continuació defineixo unes macros que utilitzaré també posteriorment en el fitxer. Les macros són com funcions dins d'un programa i els podem passar tants arguments com vulguem quan les cridem, dintre de la macro es substitueixen les variables ${ARG1}, ${ARG2}, etc... pel valor del paràmetre que hem passat quan hem cridat a la macro.

Macro mactollfree

L'objectiu de la següent macro és trucar al número que se li passi com a primer paràmetre per FWD i en cas de que no es pugui, trucar per FWDOUT.

;--------------------------------------------
; macros
;--------------------------------------------

[macro-mactollfree]
;   ${ARG1} - Extension  (we could have used ${MACRO_EXTEN} here as well
;        Truco amb FreeWorldDialUp (s'ha de posar un * davant)
;        si no va, truco amb FreeWorldDialOut (perdo credits)
exten => s,1,SetCallerID,${FWDCIDNAME}
exten => s,2,Playback(pof-fwdup)
exten => s,3,Dial(IAX2/${FWDNUMBER}@fwd-gw/*${ARG1},60,g)
exten => s,4,NoOp(Contestat:${ANSWEREDTIME})
exten => s,5,GotoIf($["${ANSWEREDTIME}" = ""]?6:9)
exten => s,6,SetCallerID,${POFMAIL}
exten => s,7,Playback(pof-fwdout)
exten => s,8,Dial(IAX2/${POFFWDOUT}@fwdOUT/q${ARG1},60)
exten => s,9,Hangup

Analitzem la macro pas per pas: Aquesta macro es crida posteriorment, de la següent manera:

exten => _1800NXXXXXX,1,Macro(mactollfree,${EXTEN})

Que traduït per als que no estigueu familiaritzats amb la sintaxi d'asterisk vol dir això: quan el numero marcat començi per 1800 (és com el prefixe 900 d'aquí però a USA, son números gratuïts), seguit d'un nombre del 2 al 9 (la N), seguit de 6 nombres del 0 al 9 (les 6 X's) executa la Macro mactollfree passant-li com a paràmetre 1 la extensió completa, es a dir, el número marcat.

Llavors la macro executarà la seqüència de comandes que conté:

  1. Posa't com a CallerID el meu número de FWD, emmagatzemat en la variable FWDCIDNAME que hem definit al principi del fitxer.

  2. Reprodueix el fitxer pof-fwdup, que és un fitxer d'àudio que m'informa de que la trucada s'enrutarà a través de FWDUP.

  3. Executa la comanda Dial que és la que fa efectiva la trucada, fixeu-vos que li passem 3 paràmetres separats per comes:

    • IAX2/${FWDNUMBER}@fwd-gw/*${ARG1}: Trucada a través del protocol IAX2 de 646499 (el valor de la variable FWDNUMBER definit al principi) a través de fwd-gw (definit a /etc/asterisk/iax.conf) cap a *${ARG1} que és la extensió marcada (el número 1-800) amb un asterisk al davant, ja que amb FWD s'ha de marcar un * al davant dels números toll-free.
    • 60: 60 segons de timeout de trucada, si en aquest temps no contesten acaba la execució de Dial.
    • g: Opció que indica a Dial que quan finalitzi la execució, continui executant més comandes en el context actual, és a dir que no finalitzi aquí sinó que segueixi. Aquesta opció és important, ja que és la que ens permet fer que si la trucada no s'enruta correctament a través de FWD continui executant més comandes i truqui utilitzant FWDOUT, un altre proveïdor que també ofereix trucades gratuïtes a números toll-free.
  4. El NoOp és una comanda que indica a Asterisk que no faci rés, bé... casi res, la utilitzem com a printf o echo per a que ens imprimeixi el valor de la variable ${ANSWEREDTIME} per la consola d'Asterisk. Només és útil per debugar.

  5. Després de la execució de Dial la variable ANSWEREDTIME conté el temps que s'ha contestat la trucada, en el cas de que aquesta hagi estat contestada, sinó no conté res. El que fem en aquesta línia és dir: Si ANSWEREDTIME no té valor salta a la línia 6 (com no s'ha pogut efectuar la trucada per FWD saltem al següent proveïdor), en cas contrari (ANSWEREDTIME té algun valor) saltem a la línia 9 on farem un Hangup perquè la trucada ha finalitzat correctament.

  6. Si estem en aquesta línia vol dir que la trucada no ha anat bé per FWD, per tant la enrutarem a través de FWDOUT, que vol que li passem una adreça de mail com a CallerID. Això és el que fem aquí.

  7. Igual que abans, reproduïm un fitxer d'àudio informant a la persona que truca a través de quin proveïdor s'enrutarà la trucada.

  8. Executem la comanda Dial que fa efectiva la trucada, els paràmetres que li passem són molt semblants als que passàvem anteriorment, només comentar que aquí la q que posem davant de la extensió serveix per a que FWDOUT no reprodueixi la locució informant dels credits que et queden. Fixeu-vos que aquí ja no utilitzem la g com a paràmetre, ja que no hem de seguir executant comandes en el context després d'aquest Dial.

  9. Per finalitzar, penjem la trucada.

Macro macvoipjet

A continuació tinc una altra macro que utilitzo per a trucar a través de VoipJet. Aquesta macro té dues coses importants:

  1. Utilitza els 3 servidors de VoipJet, així si el primer està caigut salta al segon... i sinó al tercer. Per fer això utilitzo el mateix mètode que he descrit abans, comprovant el valor de ANSWEREDTIME.

  2. Envia correctament el número a VoipJet sense que l'usuari s'hagi de preocupar: 011 davant dels números internacionals, i sense 011 als números del NANPA.

[macro-macvoipjet]
;   ${ARG1} - Extension
;   ${ARG2} - CallerID  (x.ej: ${POFMOV})
;   ${ARG3} - Account   (x.ej: ${POFVOIPJET})
;   ${ARG4} - Server1   (x.ej: voipjet-pau-out)
;   ${ARG5} - Server2   (x.ej: voipjet-pau-out2)
;   ${ARG6} - Server3   (x.ej: voipjet-pau-out3)
; Faig trucades pels 3 servidors de voipjet, en cas de q un estigui caigut
; NANPA: North American Numbers dialed as 1 + area code
exten => s,1,SetCallerID(0${ARG2})
exten => s,2,Playback(pof-voipjet)
exten => s,3,GotoIf($["${ARG1:0:4}" = "0111"]?4:12)
exten => s,4,Dial(IAX2/${ARG3}@${ARG4}/${ARG1:3},60,g)
exten => s,5,NoOp(Contestat:${ANSWEREDTIME})
exten => s,6,GotoIf($["${ANSWEREDTIME}" = ""]?7:20)
exten => s,7,Dial(IAX2/${ARG3}@${ARG5}/${ARG1:3},60,g)
exten => s,8,NoOp(Contestat:${ANSWEREDTIME})
exten => s,9,GotoIf($["${ANSWEREDTIME}" = ""]?10:20)
exten => s,10,Dial(IAX2/${ARG3}@${ARG6}/${ARG1:3},60)
exten => s,11,Hangup
; WORLD: International Numbers dialed as 011 + country code + number
exten => s,12,GotoIf($["${ARG1:0:3}" = "011"]?13:20)
exten => s,13,Dial(IAX2/${ARG3}@${ARG4}/011${ARG1:3},60,g)
exten => s,14,NoOp(Contestat:${ANSWEREDTIME})
exten => s,15,GotoIf($["${ANSWEREDTIME}" = ""]?16:20)
exten => s,16,Dial(IAX2/${ARG3}@${ARG5}/011${ARG1:3},60,g)
exten => s,17,NoOp(Contestat:${ANSWEREDTIME})
exten => s,18,GotoIf($["${ANSWEREDTIME}" = ""]?19:20)
exten => s,19,Dial(IAX2/${ARG3}@${ARG6}/011${ARG1:3},60)
exten => s,20,Hangup

Si heu entès la macro mactollfree que he comentat anteriorment no us costarà entendre aquesta, així que comentaré només els punts que considero més "difícils de desxifrar", si a algú li interessa i no entén alguna cosa podeu preguntar als comentaris.

  • Al SetCallerID poso un 0 davant, per que VoipJet obliga a que el CallerID tingui 10 dígits.
  • Sempre crido a la macro amb 011 davant de la extensió (número a trucar), i a la macro comprovo si te 0111 és un NANPA, sinó és un número d'un altre país.
  • Als NANPA els extrec el 011 de davant amb el :3 que hi ha al final de la extensió: ${ARG1:3}.
  • Als que no són NANPA també els extrec els 3 primers dígits (és una tonteria, no caldria fer-ho) però els hi poso fixes abans de la variable: /011${ARG1:3}.

Macro macpof-dialout

A continuació una altra macro, molt semblant a la anterior, però que afegeix un nou proveïdor: VoipBuster. Aquí el que faig és que en cas de que la trucada sigui a Estats Units la envio per VoipBuster, perquè té tarifes més econòmiques que VoipJet. Si VoipBuster estigués caigut, provaria els 3 servidors de VoipJet. Si la trucada no és a USA, llavors la envio per VoipJet i si els 3 servidors de VoipJet estiguessin caiguts sortiria per VoipBuster.

[macro-macpof-dialout]
;   ${ARG1} - Extension
;   ${ARG2} - CallerID  (x.ej: ${POFMOV})
;   ${ARG3} - Account   (x.ej: ${POFVOIPJET})
;   ${ARG4} - Server1   (x.ej: voipjet-pau-out)
;   ${ARG5} - Server2   (x.ej: voipjet-pau-out2)
;   ${ARG6} - Server3   (x.ej: voipjet-pau-out3)
; Faig trucades pels 3 servidors de voipjet, en cas de q un estigui caigut
; si els 3 servers de voipjet estan caiguts, surto per voipbuster
; NANPA: North American Numbers dialed as 1 + area code
; usa calls are cheaper with voipbuster
exten => s,1,SetCallerID(0${ARG2})
exten => s,2,GotoIf($["${ARG1:0:4}" = "0111"]?3:16)
exten => s,3,Playback(pof-voipbuster)
exten => s,4,Dial(IAX2/pauoliva@voipbuster-pau-out/00${ARG1:3},60,g)
exten => s,5,NoOp(Contestat:${ANSWEREDTIME})
exten => s,6,GotoIf($["${ANSWEREDTIME}" = ""]?7:29)
exten => s,7,Playback(pof-voipjet)
exten => s,8,Dial(IAX2/${ARG3}@${ARG5}/${ARG1:3},60,g)
exten => s,9,NoOp(Contestat:${ANSWEREDTIME})
exten => s,10,GotoIf($["${ANSWEREDTIME}" = ""]?11:29)
exten => s,11,Dial(IAX2/${ARG3}@${ARG6}/${ARG1:3},60,g)
exten => s,12,NoOp(Contestat:${ANSWEREDTIME})
exten => s,13,GotoIf($["${ANSWEREDTIME}" = ""]?14:29)
exten => s,14,Dial(IAX2/${ARG3}@${ARG4}/${ARG1:3},60)
exten => s,15,Hangup
; WORLD: International Numbers dialed as 011 + country code + number
exten => s,16,GotoIf($["${ARG1:0:3}" = "011"]?17:29)
exten => s,17,Playback(pof-voipjet)
exten => s,18,Dial(IAX2/${ARG3}@${ARG4}/011${ARG1:3},60,g)
exten => s,19,NoOp(Contestat:${ANSWEREDTIME})
exten => s,20,GotoIf($["${ANSWEREDTIME}" = ""]?21:29)
exten => s,21,Dial(IAX2/${ARG3}@${ARG5}/011${ARG1:3},60,g)
exten => s,22,NoOp(Contestat:${ANSWEREDTIME})
exten => s,23,GotoIf($["${ANSWEREDTIME}" = ""]?24:29)
exten => s,24,Dial(IAX2/${ARG3}@${ARG6}/011${ARG1:3},60,g)
exten => s,25,NoOp(Contestat:${ANSWEREDTIME})
exten => s,26,GotoIf($["${ANSWEREDTIME}" = ""]?27:29)
exten => s,27,Playback(pof-voipbuster)
exten => s,28,Dial(IAX2/pauoliva@voipbuster-pau-out/00${ARG1:3},60) ; for voipbuster
exten => s,29,Hangup

Fins aquí les 3 macros que tinc definides, si queden dubtes als comentaris :)

Ara anem a veure la resta de contextos definits en el dialplan. Bàsicament l'he dividit en 6 parts:

  1. Context per defecte
  2. Extensions d'usuaris
  3. Trucades a l'exterior utilitzant prefixes per enrutar
  4. Trucades a l'exterior sense marcar cap prefix previ
  5. Trucades entrants
  6. Contextos d'usuaris per separar privilegis

Context per defecte

La part que veureu a continuació és el context per defecte, on van a parar les trucades entrants que és fan a la linea fixa de Menta connectada a la X100P i les trucades que es fan al número de mòbil Movistar que tinc connectat al trunk.

Primer defineixo les extensions "s" (start), "t" (timeout) i "i" (invalid).

;--------------------------------------------
; context per defecte (default), aqui entren totes les trucades
;--------------------------------------------

[default]

exten => s,1,Wait,1                             ; Wait 1 seconds
exten => t,1,Goto(#,1)                          ; If they take too long, give up
exten => i,1,Playback(invalid)                  ; "That's not valid, try again"

La extensió "s" s'executa quan entra una trucada, faig que s'espere 1 segón abans de contestar la trucada.

Redefineixo la extensió "t" per a que quan es produeixi un timeout vagi a executar les comandes de la extensió "#" a partir de la primera linia. Ho veurem amb més detall més endavant.

Quan l'usuari marca una extensió invalida, l'informo amb un missatge de veu.

; pof
exten => s/${POFMOV},2,Answer                   ; contesta
exten => s/${POFMOV},3,DigitTimeout(5)          ; set digit timeout 5 sec
exten => s/${POFMOV},4,ResponseTimeout(20)      ; response timeout 20 sec
exten => s/${POFMOV},5,Authenticate(xxxxx)      ; password
exten => s/${POFMOV},6,DISA(no-password|pofhq)  ; si el password es correcte transfereix al contexte

; esteve
exten => s/${ESTEVEMOV},2,Answer                        ; contesta
exten => s/${ESTEVEMOV},3,DigitTimeout(5)               ; set digit timeout 5 sec
exten => s/${ESTEVEMOV},4,ResponseTimeout(20)           ; response timeout 20 sec
exten => s/${ESTEVEMOV},5,Authenticate(xxxxx)           ; password
exten => s/${ESTEVEMOV},6,DISA(no-password|esteve)      ; si el password es correcte transfereix al contexte

Si la trucada ve del meu mòbil o del mòbil de l'Esteve, demano un password i si és correcte envio la trucada al contexte de l'usuari (meu o de l'Esteve), que permetrá realitzar trucades amb els nostres proveïdors.

Això el que em permet és per exemple, si he de trucar a USA i estic fora de casa marco el número del mòbil movistar del trunk desde el meu mòbil, la trucada fins al movistar em surt per 1 centim/minut ja que el tinc com a "mi favorito", i llavors poso el password que he definit anteriorment i l'asterisk em dona tó al meu context, des d'on puc marcar el número de USA que s'enrutarà per VoipBuster amb la macro definida anteriorment (macpof-dialout) i trucaré gratis a USA :)

A continuació veiem la extensió "#" que he comentat anteriorment, on arribem quan es produeix un timeout:

exten => #,1,Answer                             ; contesta
exten => #,2,DigitTimeout(5)                    ; set digit timeout 5 sec
exten => #,3,ResponseTimeout(20)                ; response timeout 20 sec
exten => #,4,Background(pof-calabria)           ; Let them know what's going on
exten => #,5,DISA(no-password|usuaris)          ; transfereix al contexte sense demanar paswd

Aquí arriben les trucades que tenen un CallerID diferent dels que hem especificat anteriorment (tots els números, excepte el meu mòbil i el de l'Esteve). El que faig és reproduir un missatge de veu on informo a la persona que truca de que pot marcar el 200 per trucar-me a mi , el 201 per trucar a l'Esteve, etc...

Seguidament definim el mític echo test, per comprovar la qualitat de l'enllaç. Arribem al echo test marcant el 600.

exten => 600,1,Playback(demo-echotest)          ; Let them know what's going on
exten => 600,2,Echo                             ; Do the echo test
exten => 600,3,Playback(demo-echodone)          ; Let them know it's over
exten => 600,4,Hangup                           ; Start over

Finalment, definexio dues extensions la 8500 i la 8501 per a consultar la bustia de veu.

; Servei de contestador automàtic, per callerID
exten => 8500,1,VoiceMailMain(${CALLERIDNUM})
exten => 8500,2,Hangup

; Per accedir al contestador d'un altre usuari (demana extensio)
exten => 8501,1,VoicemailMain
exten => 8501,2,Hangup

La extensió 8500 ens portarà directament a la bustia de veu de l'usuari que fa la trucada, només ens demanarà el password. Si volem consultar la bustia de veu d'un altre usuari podem fer-ho marcant el 8501, llavors ens demanarà la mailbox i el password.

Extensions d’usuaris

A continuació definim les extensions SIP dels usuaris del Asterisk:

;--------------------------------------------
; extensions d'usuaris
;--------------------------------------------

[sip]
;Pau
exten => 200,1,Dial(SIP/200,20,t)
exten => 200,2,Voicemail(200)
exten => 200,3,Hangup
exten => 200,102,Voicemail(200)
exten => 200,103,Hangup

;Esteve
exten => 201,1,Dial(SIP/201,20,t)
exten => 201,2,Voicemail(201)
exten => 201,3,Hangup
exten => 201,102,Voicemail(201)
exten => 201,103,Hangup

;Diego
exten => 203,1,Dial(SIP/203,20,t)
exten => 203,2,Voicemail(203)
exten => 203,3,Hangup
exten => 203,102,Voicemail(203)
exten => 203,103,Hangup

Tots els usuaris estàn creats de la mateixa manera, com veieu, si l'usuari no contesta la trucada en 20 segons s'envia al Voicemail.

Trucades a l’exterior utilitzant prefixes per enrutar

L'objectiu d'aquesta part del dialplan és fer que puguem decidir per on s'enruta la trucada marcant un prefix abans del número al que volem trucar. Despres veurem com fer que la trucada s'enrute automàticament per on més ens interessi sense marcar prefix, però de vegades ens interessa poder desviar una trucada per una determinada ruta, i això és el que fem aquí.

Cada proveïdor té uns requisits respecte a com s'ha de marcar, si s'han de posar prefixes o no, etc... Amb aquest dialplan el que fem es unificar-los tots, de manera que truquem per on truquem no ens haugem de recordar dels prefixes que el proveïdor ens obliga a marcar, sino que l'Asterisk ho farà per nosaltres. Sempre utilitzarem la següent estructura per trucar:

prefix_de_ruta + codi_de_pais + num_de_telefon.

Els prefixos de ruta he fet que comencin sempre per zero, ja que no hi ha cap país que tingui aquest prefix, així podem combinar els dos sistemes (trucades amb prefix de ruta i sense).

;--------------------------------------------
; trucades al exterior, extensions predefinides
;--------------------------------------------

[menta-out] ;055+num
exten => _05534[69]XXXXXXXX,1,Playback(pof-menta)
exten => _05534[69]XXXXXXXX,2,Dial(Zap/1/067${EXTEN:5},60)
exten => _05534[69]XXXXXXXX,3,Hangup
exten => _055[69]XXXXXXXX,1,Playback(pof-menta)
exten => _055[69]XXXXXXXX,2,Dial(Zap/1/067${EXTEN:3},60)
exten => _055[69]XXXXXXXX,3,Hangup

El codi que teniu a sobre d'aquestes linies pertany al prefixe predefinit per trucar amb la PSTN (linia de menta), per trucar marcarem 055 + numero de fixe o mobil on volem trucar. Podem posar el 34 davant o no posar-lo. Només deixo marcar a números que comencin per 6 o 9 (la majoría de mòbils i fixes, encara que també inclouria 900 o 901, 902..).

Fixeu-vos amb la sintàxis: el _ indica que el que ve a continuació és una expressió regular d'Asterisk, la sintaxis és la següent:

X Qualsevol digit del 0 al 9
Z Qualsevol digit del 1 al 9
N Qualsevol digit del 2 al 9
[1237-9] Qualsevol digit entre els corxets, en aquest exemple 1,2,3,7,8,9.
. El punt es un wilcard, indica qualsevol nombre de caràcters (un o més digits)

A continuació us deixo la resta dels prefixes predefinits, que pertanyen als operadors que he comentat al prinicipi del post. Si heu entés l'exemple anterior i la sintàxis correctament no tindreu problema en entendre la resta de prefixes.

[fwdout-out] ;056+num
exten => _056.,1,SetCallerID,[email protected]
exten => _056.,2,Playback(pof-fwdout)
exten => _056.,3,Dial(IAX2/${POFFWDOUT}@fwdOUT/${EXTEN:3},60)
exten => _056.,4,Hangup

[iaxfwd] ;057+num
; echo test: 057613, coffe house: 057614, trucar a VozTelecom: 057**868+num
exten => _057.,1,SetCallerID,${FWDCIDNAME}
exten => _057.,2,Playback(pof-fwdup)
exten => _057.,3,Dial(IAX2/${FWDNUMBER}@fwd-gw/${EXTEN:3},60)
exten => _057.,4,Hangup

[outgoing_voipuser-pof] ;058+num
exten => _058.,1,Playback(pof-voipuser)
exten => _058.,2,Dial(SIP/00${EXTEN:3}@voipuser-pof,60)
exten => _058.,3,Hangup

[outgoing_voipuser-esteve] ;058+num
exten => _058.,1,Playback(pof-voipuser)
exten => _058.,2,Dial(SIP/00${EXTEN:3}@voipuser-esteve,60)
exten => _058.,3,Hangup

[movistar-out] ;060+num
exten => _06034[69]XXXXXXXX,1,Playback(pof-movistar)
exten => _06034[69]XXXXXXXX,2,Dial(Zap/2/#31#${EXTEN:5},60)
exten => _06034[69]XXXXXXXX,3,Hangup
exten => _060.,1,Playback(pof-movistar)
exten => _060.,2,Dial(Zap/2/#31#${EXTEN:3},60)
exten => _060.,3,Hangup

[adamvoip] ;061+num
; 0611114 --> conferencia / 0611111 --> echo test
exten => _061.,1,Playback(pof-adam)
exten => _061.,2,Dial(SIP/${EXTEN:3}@adamvoip,60)
exten => _061.,3,Hangup

[voipjet-pau-out] ;011+num
exten => _0111NXXNXXXXXX,1,Macro(macvoipjet,${EXTEN},${POFMOV},${POFVOIPJET},voipjet-pau-out,voipjet-pau-out2,voipjet-pau-out3)
exten => _0111NXXNXXXXXX,2,Hangup
exten => _011.,1,Macro(macvoipjet,${EXTEN},${POFMOV},${POFVOIPJET},voipjet-pau-out,voipjet-pau-out2,voipjet-pau-out3)
exten => _011.,2,Hangup

[voipjet-esteve-out] ;011+num
exten => _0111NXXNXXXXXX,1,Macro(macvoipjet,${EXTEN},${ESTEVEMOV},${ESTEVEVOIPJET},voipjet-esteve-out,voipjet-esteve-out2,voipjet-esteve-out3)
exten => _0111NXXNXXXXXX,2,Hangup
exten => _011.,1,Macro(macvoipjet,${EXTEN},${ESTEVEMOV},${ESTEVEVOIPJET},voipjet-esteve-out,voipjet-esteve-out2,voipjet-esteve-out3)
exten => _011.,2,Hangup

[voipjet-diego-out] ;011+num
exten => _0111NXXNXXXXXX,1,Macro(macvoipjet,${EXTEN},${DIEGOMOV},${DIEGOVOIPJET},voipjet-diego-out,voipjet-diego-out2,voipjet-diego-out3)
exten => _0111NXXNXXXXXX,2,Hangup
exten => _011.,1,Macro(macvoipjet,${EXTEN},${DIEGOMOV},${DIEGOVOIPJET},voipjet-diego-out,voipjet-diego-out2,voipjet-diego-out3)
exten => _011.,2,Hangup

[voipbuster-pau-out]
exten => _012.,1,SetCallerID,${POFMOV}
exten => _012.,2,Playback(pof-voipbuster)
exten => _012.,3,Dial(IAX2/pauoliva@voipbuster-pau-out/00${EXTEN:3},60)
exten => _012.,4,Hangup

Fixeu-vos amb l'ús de la macro macvoipjet per a les trucades amb VoipJet. També hi ha un parell de detalls, com per exemple l'ús de 067 davant dels números que surten pel fixe i de #31# davant dels números que surten pel mòbil, això el que fa és amagar el CallerID.

Com sempre, si teniu algun dubte o suggerència utilitzeu els comentaris.

Trucades a l’exterior sense marcar cap prefix previ

Normalment el que ens interessarà serà marcar el numero de telèfon al que volem trucar i deixar que l'Asterisk "decideixi" per quina ruta enviar la trucada automàticament, sense haver-nos de preocupar de marcar un prefixe com hem fet en l'apartat anterior. A continuació veureu la part del dialplan que s'encarrega de ---en funció del codi de país i de la longitud del número marcat--- sel·leccionar el proveïdor que ofereixi la tarifa més econòmica per a dur a terme la trucada. Si per qualsevol raó aquest proveïdor no estigués disponible intentarem sempre fer la trucada amb el següent proveïdor que ens oferís la millor tarifa.

Comencem enrutant els números gratuïts (toll-free) dels paísos on podem arribar sense pagar:

;--------------------------------------------
; trucades al exterior
;--------------------------------------------

[tollfree]
; els paisos que conec quina longitud té la numeració estan exactes
; els que no ho conec tenen un . q pot ser qualsevol longitud

;=========USA=======
exten => _1800NXXXXXX,1,Macro(mactollfree,${EXTEN})
exten => _1700NXXXXXX,1,Macro(mactollfree,${EXTEN})
exten => _1888NXXXXXX,1,Macro(mactollfree,${EXTEN})
exten => _1877NXXXXXX,1,Macro(mactollfree,${EXTEN})
exten => _1866NXXXXXX,1,Macro(mactollfree,${EXTEN})

;=========Netherlands=======
exten => _31800.,1,Macro(mactollfree,${EXTEN})

;=========UK=======
exten => _44800XXXXXXX,1,Macro(mactollfree,${EXTEN})
exten => _44500XXXXXXX,1,Macro(mactollfree,${EXTEN})
exten => _44808XXXXXXX,1,Macro(mactollfree,${EXTEN})

;=========Norway=======
exten => _47800.,1,Macro(mactollfree,${EXTEN})

;=========Germany=======
exten => _49800.,1,Macro(mactollfree,${EXTEN})
exten => _49130.,1,Macro(mactollfree,${EXTEN})

;=========Spain========
exten => _900XXXXXX,1,Playback(pof-menta)
exten => _900XXXXXX,2,Dial(Zap/1/067${EXTEN},60)
exten => _900XXXXXX,3,Hangup
exten => _34900XXXXXX,1,Playback(pof-menta)
exten => _34900XXXXXX,2,Dial(Zap/1/067${EXTEN:2},60)
exten => _34900XXXXXX,3,Hangup

Fixeu-vos que si conec la longitud del número la especifíco amb "X", i si no poso un "." que indica qualsevol longitud. Per als toll-free internacionals utilitzo la macro mactollfree que hem comentat al inici del post, per al 900 (espanya) utilitzo la línea de menta.

A continuació definirem que fer amb les trucades a fixes d'espanya, deixem trucar tant amb un 34 al davant com sense, com si la trucada es fes des d'una línea espanyola. La trucada s'enrutarà per defecte per la línea fixa de menta que té trucades nacionals gratuites, en cas de que la linea estigués ocupada faríem sortir la trucada per VoipBuster, que també ofereix trucades gratuïtes als fixes d'Espanya.

[spain-free]
; trucades a fixes d'espanya, primer provem per menta
; si no va entrutem per voipbuster que també son gratis
exten => _9ZXXXXXXX,1,Playback(pof-menta)
exten => _9ZXXXXXXX,2,Dial(Zap/1/067${EXTEN},60,g)
exten => _9ZXXXXXXX,3,NoOp(Contestat:${ANSWEREDTIME})
exten => _9ZXXXXXXX,4,GotoIf($["${ANSWEREDTIME}" = ""]?5:6)
exten => _9ZXXXXXXX,5,Dial(IAX2/pauoliva@voipbuster-pau-out/0034${EXTEN},60)
exten => _9ZXXXXXXX,6,Hangup

exten => _349ZXXXXXXX,1,Playback(pof-menta)
exten => _349ZXXXXXXX,2,Dial(Zap/1/067${EXTEN:2},60,g)
exten => _349ZXXXXXXX,3,NoOp(Contestat:${ANSWEREDTIME})
exten => _349ZXXXXXXX,4,GotoIf($["${ANSWEREDTIME}" = ""]?5:6)
exten => _349ZXXXXXXX,5,Dial(IAX2/pauoliva@voipbuster-pau-out/00${EXTEN},60)
exten => _349ZXXXXXXX,6,Hangup

Fixeu-vos en que aquí he utilitzat la "Z", ja que els fixes sempre porten un número del 1 al 9 després del 9. Si hagués posat una X en lloc d'una Z se m'haguessen pogut colar les trucades a números especials com els 901 o 902.

Ara veurem que fer amb les trucades a mòbils. El trunk que tinc connectat té un SIM Movistar de prepagament amb la tarifa activa tu tiempo, que surt per 12 centims/minut de les 16h fins a les 4 del matí, i a 48 centims/minut la resta d'hores. Les hores que la tarifa de movistar surt a 12 centims enrutaré les trucades pel trunk, i la resta d'hores les enrutaré a través de VoipJet que les trucades a mòbils d'Espanya surten a 19,6 centims / minut. I finalment, si VoipJet estigués caigut fariem sortir la trucada per VoipBuster que tindría un cost de 22,6 centims/minut.

Per això que us comento, utilitzo la comanda GotoIfTime de la següent manera:

[callout-pau]
; les trucades a mòbil van pel trunk (només de 16 a 4h)
exten => _346XXXXXXXX,1,GotoIfTime(03:55:01-16:05:00,mon-fri,*,*?callout-normal,${EXTEN},1)
exten => _346XXXXXXXX,2,Playback(pof-movistar)
exten => _346XXXXXXXX,3,Dial(Zap/2/#31#${EXTEN:2},60)
exten => _346XXXXXXXX,4,Hangup

exten => _6XXXXXXXX,1,GotoIfTime(03:55:01-16:05:00,mon-fri,*,*?callout-normal,${EXTEN},1)
exten => _6XXXXXXXX,2,Playback(pof-movistar)
exten => _6XXXXXXXX,3,Dial(Zap/2/#31#${EXTEN},60)
exten => _6XXXXXXXX,4,Hangup

exten => _XXXXXXXXXX.,1,Macro(macpof-dialout,011${EXTEN},${POFMOV},${POFVOIPJET},voipjet-pau-out,voipjet-pau-out2,voipjet-pau-out3)
exten => _XXXXXXXXXX.,2,Hangup


[callout-normal]
; les trucades a mòbil de les 4 de la nit a les 16h van per voipjet
exten => _346XXXXXXXX,1,Macro(macpof-dialout,011${EXTEN},${POFMOV},${POFVOIPJET},voipjet-pau-out,voipjet-pau-out2,voipjet-pau-out3)
exten => _6XXXXXXXX,1,Macro(macpof-dialout,01134${EXTEN},${POFMOV},${POFVOIPJET},voipjet-pau-out,voipjet-pau-out2,voipjet-pau-out3)

Amb els paràmetres de la comanda GotoIfTime indico que si l'hora està compresa entre les 03:55:01 i les 16:05:00 de dilluns a divendres (mon-fri... els caps de setmana la activa tutiempo em deixa trucar a 12 centims/min tot el dia) envïi la trucada a la linea 1 del contexte [callout-normal], definit a sota de [callout-pau]. En cas contrari seguiría a la linea 2 de [callout-pau], que s'encarregará de fer sortir la trucada pel trunk amb Movistar.

Un altre punt a tenir en compte és el final del context [callout-pau] ---marcat en vermell---, que sería com una mena de ruta per defecte o catch-all, el que indica és: "tots els números que tinguin més de 10 digits envials cap a la macro macpof-dialout", que si recordeu el que fa es provar els 3 servers de voipjet, i si no funciona VoipJet enrutar la trucada per VoipBuster. És molt important que aquesta línea estigui en aquesta posició del dialplan, ja que aquí ja hem enrutat les trucades a numeros gratuïts, fixes i mòbils d'espanya per on voliem. La limitació de "més de 10 digits" és per que tots els números internacionals tenen com a mínim 11 digits (si incloem el codi del pais).

NOTA: Si has segut capaç de seguir tot el que anat explicant fins ara (m'enrotllo com una persiana!) i estàs al dia de les tarifes de VoipJet i VoipBuster te'n hauràs adonat de que aquest dialplan no és perfecte... si no te'n has adonat, passo a explicar el "problema" que té, i com posar-hi remei de forma cutre...

El problema aquí és que per defecte totes les trucades a números internacionals (excepte USA) surten per VoipJet, que és l'operador més econòmic, però amb VoipBuster tenim trucades gratuites a fixes de Australia, Austria, Belgica, República Checa, Dinamarca, Finalndia, França, Alemania, Grecia, Irlanda, Luxemburg, Holanda, Noruega, Portugal, Suècia, Suissa i Anglaterra... Com no em sé tots els prefixes de fixes i mòbils de tots aquests països no he pogut implementar que fassi la trucada cap als fixes a través de VoipBuster en lloc de a través de VoipJet, per tant si truquem a un fixe de per exemple Holanda, la trucada s'enrutaría per VoipJet i pagariem. Per evitar aquest problema hem de tenir en compte que si truquem a un telèfon fixe d'un d'aquests països hem de marcar el 012 al davant, obligant així a que la trucada s'enrute a través de VoipBuster (amb els prefixes estàtics predefinits que he explicat al apartat anterior) i sigui gratuita. Si algú sap alguna manera d'automatitzar això, o coneix on trobar un llistat actualitzat de tots els prefixes de fixos i mòbils d'aquests països estaría molt agraït de que ho compartís amb tothom :)

A continuació la resta del dialplan per a l'Esteve i el Diego, que no tenen account de VoipBuster ni accés al Movistar del trunk, per tant tot surt per VoipJet.

[callout-esteve]
; les trucades van directes per voipjet:
exten => _346XXXXXXXX,1,Macro(macvoipjet,011${EXTEN},${ESTEVEMOV},${ESTEVEVOIPJET},voipjet-esteve-out,voipjet-esteve-out2,voipjet-esteve-out3)
exten => _346XXXXXXXX,2,Hangup
exten => _6XXXXXXXX,1,Macro(macvoipjet,01134${EXTEN},${ESTEVEMOV},${ESTEVEVOIPJET},voipjet-esteve-out,voipjet-esteve-out2,voipjet-esteve-out3)
exten => _6XXXXXXXX,2,Hangup
exten => _XXXXXXXXXX.,1,Macro(macvoipjet,011${EXTEN},${ESTEVEMOV},${ESTEVEVOIPJET},voipjet-esteve-out,voipjet-esteve-out2,voipjet-esteve-out3)
exten => _XXXXXXXXXX.,2,Hangup


[callout-diego]
exten => _346XXXXXXXX,1,Macro(macvoipjet,011${EXTEN},${DIEGOMOV},${DIEGOVOIPJET},voipjet-diego-out,voipjet-diego-out2,voipjet-diego-out3)
exten => _346XXXXXXXX,2,Hangup
exten => _6XXXXXXXX,1,Macro(macvoipjet,011${EXTEN},${DIEGOMOV},${DIEGOVOIPJET},voipjet-diego-out,voipjet-diego-out2,voipjet-diego-out3)
exten => _6XXXXXXXX,2,Hangup
exten => _XXXXXXXXXX.,1,Macro(macvoipjet,011${EXTEN},${DIEGOMOV},${DIEGOVOIPJET},voipjet-diego-out,voipjet-diego-out2,voipjet-diego-out3)
exten => _XXXXXXXXXX.,2,Hangup

Fixeu-vos en el cas anterior, com "arreglo" el número que enviem a la macro macvoipjet posant el 34 al davant en el cas de que marquen el número de mòbil espanyol sense posar el codi del país. Fixeu-vos també que en aquest cas la primera linea de cada contexte sería redundant, ja que la última contempla el mateix cas.

Trucades entrants

En aquesta secció veurem com tractar les trucades entrants que no arriben per cap interficie Zap, ja que aquestes les hem tractat al context [default].

En resum, tenim trucades que poden arribar al meu número de FWD, trucades que poden arribar a través de FWDOUT i trucades que poden arribar al meu DID de Voipuser.

Aquí us deixo la configuració bàsica, aviat faré un altre post (espero que no tan llarg com aquest!) amb algun truquillo que podem fer servir aquí... ;)

;--------------------------------------------
; trucades entrants
;--------------------------------------------

[fromiaxfwd]
exten => ${FWDNUMBER},1,Dial(${FWDRINGS},20)
exten => ${FWDNUMBER},2,Voicemail,u${FWDVMBOX}
exten => ${FWDNUMBER},102,Voicemail,b${FWDVMBOX}

Quan arriba una trucada cap al número de FWD definit a la variable ${FWDNUMBER} truquem a la extensió definida a la variable ${FWDRINGS} (la 200, la meva extensió). Si contesto la trucada el procés finalitza aquí (no s'executen la resta de comandes (2 i 102). Si en 20 segons no contesto passem a la seqüència 2, on la trucada serà atesa pel meu Voicemail com a unanswered (això ho indica la u que passem davant de la extensió ${FWDVMBOX}. En el cas de que jo estigués comunicant, la comanda Dial salta a la sequència actual + 101, per tant aniría a parar al 102, on la trucada serà atesa pel Voicemail com a busy (ho indica la b).

El cas de FWDOUT és una mica més complicat, veiem-lo a continuació:

[fromfwdOUT] ;match the context in iax.conf
; tots els fixes (349...) excepte els 90X, ej 908 902...
exten => _349ZXXXXXXX,1,Dial(ZAP/1/067${EXTEN:2},60,T,L(1800000:1790000))
; tots els 900, son num. gratuits...
exten => _34900XXXXXX,1,Dial(ZAP/1/067${EXTEN:2},60,T,L(1800000:1790000))
include => fromfwdOUT-catchall

[fromfwdOUT-catchall]
exten => _X.,1,NoOp(--- ${CALLERID} calling to (${EXTEN}) ---)
exten => _X.,2,Hangup
exten => h,1,Hangup     ;hangup event
exten => i,1,Hangup     ;invalid event
exten => t,1,Hangup     ;timeout event

Aquí recollim totes les trucades que ens arriben per IAX amb la ruta que publico a FWDOUT. Aquestes trucades entren al context [fromfwdOUT] on es chequeja el número al que vol trucar la persona que fa la trucada, si el número coincideix amb la expressió _349ZXXXXXXX (34 (espanya) + 9 + un número del 1 al 9 + 7 digits més) o _34900XXXXXX (34 (espanya) + 900 + 6 digits més), es a dir, és un número fixe o un 900 que em surt gràtis amb Menta, el deixo sortir per la linea de Menta (Zap/1), li afegeixo un 067 al davan per a que oculte el CallerID. Amb la T permetem que l'usuari que truca pugui fer transfer de la trucada, i amb L(1800000:1790000) limitem la trucada a 1800000 ms (30 minuts), avisant a l'usuari amb un missatge que diu "you have 30 minutes for this call" quan falten 1790000 ms (30 minuts menys 10 segons, es a dir, al principi de la trucada) per a que li tallem la trucada.

Si l'usuari intentés trucar a un número que no coincidís amb la expressió que hem definit al principi, li fem un Hangup, això ho aconseguim incloent el context [fromfwdOUT-catchall] al final del context [fromfwdOUT]. Aquest context logueja amb un NoOp l'intent de trucada i la finalitza.

Ara veurem el cas de Voipuser, aquí tinc dos contextos molt semblants, un per l'Esteve i l'altre per a mi, ja que els dos tenim un compte de Voipuser.

[incoming_voipuser-pof]
exten => 448449862541,1,NoOp(--- ${CALLERID} calling on pof-VoIPUser (${EXTEN}) ---)
exten => 448449862541,2,Dial(SIP/200,20)
exten => 448449862541,3,Answer
exten => 448449862541,4,Wait,1
exten => 448449862541,5,Voicemail(u200)
exten => 448449862541,6,HangUp

[incoming_voipuser-esteve]
exten => 448449862188,1,NoOp(--- ${CALLERID} calling on esteve-VoIPUser (${EXTEN}) ---)
exten => 448449862188,2,Dial(SIP/201,20)
exten => 448449862188,3,Answer
exten => 448449862188,4,Wait,1
exten => 448449862188,5,Voicemail(u201)
exten => 448449862188,6,HangUp

El que fem és loguejar la trucada amb l'ajuda de la comanda NoOp, trucar al usuari (200 en el meu cas, 201 en el del esteve). Si l'usuari contesta el Dial finalitzarà el flux d'execució (no s'executaran més comandes del context), en cas contrari l'Asterisk contestarà al cap de 20 segons, esperarà 1 segon i enviarà la trucada al Voicemail del usuari amb el missatge de unanswered.

Contextos d’usuaris per separar privilegis

Finalment, anem a veure qui pot fer què?... això ho definim creant un context específic per a cada usuari i incloent-hi els contextos ---que hem definit prèviament--- als que li volem donar accés.

;--------------------------------------------
; contextos per separar privilegis
;--------------------------------------------
[usuaris] include =\> default include =\> sip

Primer creem un context `[usuaris]`, on només incloem el context `[default]` on entren les trucades, i les extensions que hem definit per a cada usuari (context `[sip]`). D'aquesta manera una trucada que entra per la PSTN de Menta pot arribar a la extensió d'un usuari, (jo al 200, l'esteve al 201, el diego al 203...) i li podem contestar o ens pot deixar un missatge al voicemail si no tenim cap telèfon SIP connectat.

```
[pofhq] include =\> usuaris include =\> iaxfwd include =\> spain-free include =\> tollfree include =\> menta-out include =\> movistar-out include =\> adamvoip include =\> fwdout-out include =\> outgoing\_voipuser-pof include =\> voipjet-pau-out include =\> voipbuster-pau-out include =\> callout-pau include =\> fromiaxfwd include =\> incoming\_voipuser-pof
```

El context `[pofhq]` que teniu a sobre d'aquestes línies és el que utilitzo jo, i per tant és el que té més privilegis i accés a la resta de contextos que hem definit. Fixeu-vos que és molt important l'ordre en que afegim els contextos, per a que no s'enrute una trucada per un lloc que no toca.

Bàsicament tinc accés al context d'usuaris (per poder trucar al telèfon SIP de l'Esteve per exemple), puc trucar amb FWD (prefix 057), puc arribar al context `[spain-free]`, que enruta les trucades a fixes d'espanya primer per menta i si estigués ocupat per VoipUser, puc usar els números _toll-free_ (amb FWD i FWDOUT i menta per als 900), puc sortir per la línia de Menta (prefix 055) per trucar a fixes i a mòbils, puc trucar a números de Adam (prefix 061), puc trucar amb FWDOUT (prefix 056) i Voipuser (prefix 058) a números fixes de qualsevol país, puc trucar per VoipJet (prefix 011), puc trucar amb VoipBuster (prefix 012) i puc fer que les trucades s'enruten _automàgicament_ sense marcar prefix (amb el context `[callout-pau]`). Finalment, també puc rebre trucades als meu número de FWD i de Voipuser.

A continuació teniu els contextos de l'Esteve i el Diego, que si heu entès el meu no us costaran molt de desxifrar...

```
[esteve] include =\> usuaris include =\> iaxfwd include =\> spain-free include =\> tollfree include =\> menta-out include =\> outgoing\_voipuser-esteve include =\> voipjet-esteve-out include =\> callout-esteve include =\> incoming\_voipuser-esteve [diego] include =\> usuaris include =\> iaxfwd include =\> spain-free include =\> tollfree include =\> menta-out include =\> outgoing\_voipuser-esteve include =\> voipjet-diego-out include =\> callout-diego
```

I això és tot el dialplan que tinc configurat al Asterisk de casa, hi ha algunes cosetes més que me les guardo per propers posts perquè encara les estic implementant. Com sempre, espero que això pugui ser útil per algú, i les correccions de possibles errors o suggeriments son benvingudes en els comentaris :D.

PD: Talibans ortogràfics, perdoneu-me però no soc Cervantes i ara mateix no tinc cap corrector ortogràfic a mà! :P