Call pickup su Asterisk 1.6

La funzione di call pickup su Asterisk 1.6 (la versione di Debian) e` soggetta a un bug molesto. Vediamo come configurarla.

Il concetto di pickup

Il call pickup e` l'azione di rispondere da un telefono ad una chiamata che sta squillando su un telefono diverso. In pratica, io posso rispondere alla chiamata che sta facendo suonare il telefono del mio collega il quale per qualche motivo non puo` rispondere.

Pickup a mezzo di una funzione specifica nel dialplan

E` possibile fare il pickup di una chiamata usando una specifica funzione nel dialplan. I comandi disponibili per il pickup sono due: una e` Pickup e l'altra e` PickupChan. La prima fa un pickup di qualsiasi tipo di canale basandosi sulla extension e sul context. La seconda consente di fare il pickup di un canale basandosi sul tipo di canale.

Il comando Pickup

Questo e` il pickup che si basa sulla extension e sul context. Se voglio fare il pickup di un interno nel context in cui mi trovo posso fare:

exten => _**XX,1,Pickup(${EXTEN:2})

Il suo limite e` che se non specifico il context, come ho fatto qui, il pickup funziona solo se il comando pickup viene eseguito nello stesso context nel quale si trova il canale che voglio pickuppare. Se il context del canale che sta suonando e` diverso, devo specificarlo nel comando. E puo` non essere ovvio conoscere a priori il context dal quale devo fare il pickup, soprattutto se ci sono diversi context nei quali le chiamate possono essere gestite. Per esempio, e` comune che ci sia un context per gli interni che hanno diritto di chiamare fuori, uno per gli interni che NON hanno diritto di chiamare fuori, uno nel quale sono inclusi i primi due, e uno nel quale entrano le chiamate da fuori. Per facilitare il compito (ma non abbastanza, a dire il vero) esiste una variabile speciale che si chiama PICKUPMARK che consente di eseguire una ricerca del canale da pickuppare anche al di fuori del proprio context. Vediamo come funziona.

Prima di tutto, occorre impostare la variabile PICKUPMARK in ogni occasione prima di eseguire un comando Dial. Per fare si` che questa venga ereditata lungo il percorso della chiamata, e` opportuno farla precedere da un underscore. Questo e` un esempio di un comando di Dial preceduto dalla suddetta impostazione.

exten => 30,1,Set(_PICKUPMARK=${EXTEN})
exten => 30,n,Dial(SIP/30)

Cosi` facendo, prima di chiamare l'interno 30 imposto la variabile PICKUPMARK al valore "30".

Ora, quando faccio il pickup, lo faccio cosi`:

exten => _**XX,1,Pickup(${EXTEN:2}@PICKUPMARK)

Notate che la parola "pickupmark" in questa riga non e` una variabile (niente "$") ma proprio un semplice testo. Il fatto che ci sia scritto pickupmark in maiuscolo fa si` che Asterisk faccia una ricerca per un canale che sta suonando con il numero 30 (per esempio) in tutti i context. Quando ne trova uno, fa il pickup di quello. E` chiaro che nell'ipotesi in cui ci possano essere piu` canali con lo stesso numero che stanno suonando assieme in diversi context, questo sistema diventa non prevedibile.

Il comando ``PickupChan``

Questo si basa sul canale, quindi e` indipendente dal context (il canale SIP/30, per esempio, e` sempre SIP/30 indipendentemente dal context) ma e` dipendente dalla tecnologia usata (SIP/30 e` diverso da IAX/30, per dire). Quindi nelle situazioni nelle quali non e` possibile essere sicuri che il canale che vogliamo prendere sia sempre dello stesso tipo, occorrera` prevedere un qualche trucco. Supponiamo di avere alcuni interni in SIP e altri in IAX. Se io voglio fare il pickup e tutto quello che ho e` il numero del telefono (diciamo "30") e non ho modo di sapere se e` in tecnologia SIP o IAX, posso semplicemente usare un trucco: tentare tutti e due i pickup in sequenza. Infatti se uno dei due non funziona l'esecuzione del dialplan continua in modo trasparente, fino a che non riesce a farne uno con successo.

exten => _**XX,n,PickupChan(SIP/${EXTEN:2})
exten => _**XX,n,PickupChan(IAX/${EXTEN:2})

Il problema del pickup nativo in SIP

Nella versione 1.6 di Asterisk esiste un comando nel file sip.conf che consente di gestire il pickup direttamente a mezzo di un comando del protocollo SIP, senza bisogno di dover creare appositi comandi nel dialplan come abbiamo fatto prima. Di fatto questo fa si` che nelle informazioni di presenza (BLF) inviate ad un telefono che abbia eseguito un subscribe all' hint relativo ad un altro telefono vengano inviate informazioni che in pratica "spiegano" al telefono come fare un pickup della chiamata che sta squillando.

Il comportamento e` spiegato nel sip.conf di default, nei commenti. Cito:

;notifycid = yes                ; Control whether caller ID information is sent along with
                                ; dialog-info+xml notifications (supported by snom phones).
                                ; Note that this feature will only work properly when the
                                ; incoming call is using the same extension and context that
                                ; is being used as the hint for the called extension.  This means
                                ; that it won't work when using subscribecontext for your sip
                                ; user or peer (if subscribecontext is different than context).
                                ; This is also limited to a single caller, meaning that if an
                                ; extension is ringing because multiple calls are incoming,
                                ; only one will be used as the source of caller ID.  Specify
                                ; 'ignore-context' to ignore the called context when looking
                                ; for the caller's channel.  The default value is 'no.' Setting
                                ; notifycid to 'ignore-context' also causes call-pickups attempted
                                ; via SNOM's NOTIFY mechanism to set the context for the call pickup
                                ; to PICKUPMARK.

Quindi, se "notifycid" e` impostato a "no", Asterisk dovrebbe non mandare alcuna informazione sul pickup ai telefoni che stanno monitorando lo stato di un interno a mezzo di un hint. Se e` impostato a "yes" invece le manda indicando esattamente anche il context, se e` impostato a "ignore-context" di fatto permette di usare la funzione del PICKUPMARK che abbiamo visto prima. Come potete intuire, l'impostazione "yes" sarebbe la migliore, se non fosse che puo` succedere, in configurazioni complesse, che il context della chiamata non coincida con quello passato nelle informazioni di pickup, impedendone il funzionamento. In questo caso la impostazione "ignore-context" ci aiuta.

Se un telefono (Grandstream GXP2020, per esempio, o SNOM) riceve le informazioni di pickup a mezzo di questo sistema, esso esegue il pickup non a mezzo della funzione impostata nella sua configurazione, per esempio chiamando "**30" quando si preme il tasto BLF del telefono che suona, ma lo fa direttamente via SIP. Puo` essere comodo, ma puo` anche essere un problema, perche` in questo modo non si puo` usare una funzione scritta da noi (nel dialplan) per il pickup a mezzo del tasto BLF, ma solo quella integrata e "fissata" in Asterisk.

Purtroppo in Asterisk 1.6.2 di Debian Squeeze c'e` un bug, per cui il comando notifycid=no NON FUNZIONA, ed equivale di fatto a notifycid=yes, impedendomi cosi` di fare uso del mio comando personale nel dialplan per fare il pickup, forzandomi a usare quello integrato in Asterisk. Se per qualche motivo avete problemi di context diversi e il pickup cosi` fatto non funziona, non vi resta che usare un workaround con l' uso di ignore-context e del PICKUPMARK. Quello che segue e` un esempio pratico.

Esempio pratico di configurazione per aggirare il bug

Questo e` un setup con telefoni Grandstream, interni in SIP divisi fra due context (interni_uscenti che possono chiamare fuori, e interni_limitati che non possono), linee ISDN, e tre diversi context. L'inghippo e` che il context nel quale si trovano gli hint non e` quello nel quale i telefoni vengono impostati. Cosi` facendo il pickup fallisce perche` viene tentato nel context "interni" anziche` nel context "interni_uscenti" o in quello "interni_limitati". La soluzione e` quella di usare appunto il PICKUPMARK.

Questi sono i pezzi significativi del sip.conf (e` incompleto, qui ci sono solo le parti salienti):

[general]
notifycid = ignore-context

; un interno che puo` chiamare fuori
[81]
type=friend
context=interni_uscenti
defaultuser=81
secret=password
host=dynamic
dtmfmode=rfc2833
callerid= "Interno XXX" <81>
canreinvite=no
pickupgroup=1
callgroup=1
mailbox=1
call-limit=6
qualify=yes

Questi sono i pezzi significativi del file extensions.conf. Uso estensivamente il trucco di avere autoconfigurazioni, sia per gli interni che per gli hint. Altro trucco fondamentale: qualsiasi chiamata che viene da qualsiasi context (dalla isdn, per esempio) o che sia parte di qualche artificio (il gruppo 80, per esempio, che chiama diversi interni) deve sempre essere fatta a mezzo di un dial a un altro interno, con il comando dial(local/numero@context, fino ovviamente all'unico momento nel quale devo realmente fare suonare il telefono, e li` faro` un dial al protocollo SIP.

; #########################################################
; context dove si registrano gli interni che chiamano
; anche fuori (include interni, servizi, chiamate_uscenti)
; #########################################################

[interni_uscenti]

; Servizi (segreteria, echo test)
include => servizi

; Sistema di call parking
include => parkedcalls

; Provider per le chiamate uscenti
include => chiamate_uscenti

; Interni
include => interni



; #########################################################
; context dove si registrano gli interni che NON chiamano
; anche fuori (include interni, servizi)
; #########################################################

[interni_limitati]

; Servizi (segreteria, echo test)
include => servizi

; Sistema di call parking
include => parkedcalls

; Interni
include => interni



; ##############################
; Il context per i miei interni
; ##############################

[interni]

; hint automatici a 2 cifre. In pratica questa sola riga dovrebbe sostituire tutte quelle degli hint degli interni.
exten => _XX,hint,SIP/${EXTEN}

; Gruppo 80
exten => 80,1,Set(_PICKUPMARK=${EXTEN})
exten => 80,n,Dial(local/81@interni&local/82@interni)


; Una sola configurazione dinamica per tutti gli interni a 2 cifre
exten => _XX,1,Set(_PICKUPMARK=${EXTEN})
exten => _XX,n,Dial(SIP/${EXTEN},90)



; ###########################################
; Chiamate entranti dalla ISDN
; ###########################################

[from-dahdi]

exten=> 05112345,1,SIPAddHeader(Alert-Info:\;info=tre)
exten=> 05112345,n,Macro(Fop2CidLookup)
exten=> 05112345,n,Set(CALLERID(num)=0${CALLERID(num)})
exten=> 05112345,n,Dial(local/51@interni,40)

Asterisk/CallPickUp-16 (last edited 2013-08-08 20:49:40 by Kurgan)