Oggi vedremo cosa sono le macro e a cosa servono. Prima di tutto, come ho già spiegato, in Asterisk abbiamo a disposizione applicazioni e funzioni che possiamo utilizzare nel dialplan. Una di queste applicazioni è proprio la MACRO. Vediamone la sinossi:
entriamo nella console di Asterisk:
asterisk –rvvvvvvvvvvvvvvv
e digitiamo:
CLI> core show application Macro
-= Info about application 'Macro' =-
[Synopsis]
Macro Implementation
[Description]
Macro(macroname,arg1,arg2...): Executes a macro using the context
'macro-<macroname>', jumping to the 's' extension of that context and
executing each step, then returning when the steps end.
The calling extension, context, and priority are stored in ${MACRO_EXTEN},
${MACRO_CONTEXT} and ${MACRO_PRIORITY} respectively. Arguments become
${ARG1}, ${ARG2}, etc in the macro context.
If you Goto out of the Macro context, the Macro will terminate and control
will be returned at the location of the Goto.
If ${MACRO_OFFSET} is set at termination, Macro will attempt to continue
at priority MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.
Extensions: While a macro is being executed, it becomes the current context.
This means that if a hangup occurs, for instance, that the macro
will be searched for an 'h' extension, NOT the context from which
the macro was called. So, make sure to define all appropriate
extensions in your macro! (Note: AEL does not use macros)
WARNING: Because of the way Macro is implemented (it executes the priorities
contained within it via sub-engine), and a fixed per-thread
memory stack allowance, macros are limited to 7 levels
of nesting (macro calling macro calling macro, etc.); It
may be possible that stack-intensive applications in deeply nested macros
could cause asterisk to crash earlier than this limit. It is advised that
if you need to deeply nest macro calls, that you use the Gosub application
(now allows arguments like a Macro) with explict Return() calls instead.
Che si capisce da quanto appare qui sopra?
Macro(nomedellamacro, argomento1, argomento2, argomento3)
ArgomentoN è una un testo o una variabile che possiamo passare alla macro per poi utilizzarla nella stessa.
${MACRO_EXTEN} conterrà il numero che abbiamo marcato
${MACRO_CONTEXT} il contesto da dove abbiamo chiamato la macro
${MACRO_PRIORITY} la priorità da dove abbiamo chiamato la macro
${ARG1}, ${ARG2}, ${ARGN) sono le variabili contenenti gli argomenti che abbiamo inviato alla macro al momento di chiamarla.
Come è facile intuire le macro servono per semplificare il dialplan usandole per ridurre le azioni ripetitive. Facciamo un esempio:
Posso scrivere alcune righe di dialplan in questo modo:
exten => 2100,n,Dial(SIP/${EXTEN},30)
exten => 2100,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten => 2100,n(busy),Voicemail(${EXTEN}@default,b)
exten => 2100,n,hangup
exten => 2100,n(unavail),Voicemail(${EXTEN}@default,u)
exten => 2100,n,hangup
Chiamo l’interno 2100 (dial) per 30 secondi, se è occupato andrò a eseguire la riga con l’etichetta (busy) che non fa altro che inviare il chiamante alla segreteria telefonica personale dell’interno 2100 annunciando che il numero chiamato è occupato; se entro 30 secondi l’interno 2100 non risponde sarà considerato non disponibile (unavail) e la chiamata sarà trasferita alla segreteria che annuncerà che l’interno chiamato non è disponibile.
Voicemail è un’applicazione che ci permette di trasferire la chiamata alla segreteria telefonica.
(${EXTEN}@default,b) ; entreremo nella segreteria telefonica dell’interno 2100 (contenuto nella variabile ${EXTEN}) contesto default (vedremo che nel file di configurazione del voicemail è possibile definire più contesti) la b sta per busy.
Come fa Asterisk a sapere che l’interno è occupato?
Tutto questo è gestito dalla segnalizzazione usata dal protocollo SIP. Asterisk riceverà un messaggio di occupato dal telefono IP o Softphone dell’interno 2100 che immagazzinerà nella variabile ${DIALSTATUS}. Questa è una variabile di canale e viene settata ogni volta che si usa un comando dial. I suoi possibili valori possono essere:
CHANUNAVAIL - CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL
DONTCALL | TORTURE | INVALIDARGS
Torniamo al tema delle Macro. Se abbiamo 200 interni registrati, dover ripetere queste righe per ogni interno diventa una cosa poco ergonomica. Possiamo risolvere con la macro
Riprendiamo il contesto locale del nostro dialplan (come lo abbiamo lasciato nell’ultimo articolo):
[locale]
exten => 100,1, Answer()
exten => 100,2, Playback(demo-echotest)
exten => 100,3, Echo
exten => 100,4, Playback(demo-echodone)
exten => 100,5, Hangup
exten => 97,1,Answer(2)
exten => 97,n,VoiceMail
exten => 97,n,Hangup()
Supponiamo che gli interni configurati nel centralino inizino per 1 o per 2 e siano di quattro cifre, nel nostro dialplan potremo scrivere:
exten => _1XXX,1,Macro(voicemail,SIP/${EXTEN})
exten => _2XXX,1,Macro(voicemail,SIP/${EXTEN})
Come potete vedere la prima linea “cattura” qualsiasi chiamata che sia diretta a un interno che inizi con 1 e sia composto da 4 cifre (Ogni X può essere un numero da 0 a 9), chiama la macro con nome voicemail e gli passa l’argomento SIP/${EXTEN})
La seconda fa esattamente la stessa cosa per interni che iniziano con il numero 2 e sono di 4 cifre.
Adesso vediamo la macro:
[macro-voicemail]
exten => s,n,Wait(1)
exten => s,n,Playback(welcome)
exten => s,n,Dial(${ARG1},30,m)
exten => s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten => s,n(unavail),Voicemail(${MACRO_EXTEN}@default,u)
exten => s,n,Hangup()
exten => s,n(busy),VoiceMail(${MACRO_EXTEN}@default,b)
exten => s,n,Hangup()
Che è più o meno quello che avevamo visto però configurato per un singolo interno.
L’applicacione Wait si usa per creare una pausa (in questo caso un secondo)
L’applicazione Playback per usare i “prompts” cioè le voci preregistrate che trovate in /var/lib/asterisk/sounds
Con l’applicazione DIAL abbiamo configurato oltre al tempo della chiamata (prima che passi alla segreteria telefonica) l’opzione m. L’opzione m significa musica in attesa. Il chiamante invece di ascoltare il semplice squillo, ascolterà musica (vedremo in un prossimo articolo come configurare la musica in attesa).
La variabile ${ARG1} conterrà il valore SIP/${EXTEN} come l’abbiamo passato quando abbiamo chiamato la macro.
Con poche righe di dialplan abbiamo configurato le chiamate per tutti gli interni e la loro segreteria telefonica.
Dopo questo articolo il nostro dialplan è diventato:
[general]
static=yes
writeprotect=no
autofallthrough=yes
extenpatternmatchnew=yes
priorityjumping=yes
clearglobalvars=no
[globals]
luigi=SIP/1000
marco=SIP/1001
[macro-voicemail]
exten => s,n,Wait(1)
exten => s,n,Playback(welcome)
exten => s,n,Dial(${ARG1},30,m)
exten => s,n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
exten => s,n(unavail),Voicemail(${MACRO_EXTEN}@default,u)
exten => s,n,Hangup()
exten => s,n(busy),VoiceMail(${MACRO_EXTEN}@default,b)
exten => s,n,Hangup()
[locale]
exten => 100,1, Answer()
exten => 100,2, Playback(demo-echotest)
exten => 100,3, Echo
exten => 100,4, Playback(demo-echodone)
exten => 100,5, Hangup
exten => 97,1,Answer(2)
exten => 97,n,VoiceMail
exten => 97,n,Hangup()
exten => _1XXX,1,Macro(voicemail,SIP/${EXTEN})
exten => _2XXX,1,Macro(voicemail,SIP/${EXTEN})
[fisso]
exten => _00390.,1,Dial(SIP/provider1/${EXTEN},45)
exten => _00390.,n,Hangup
[cellulare]
exten => _00393.,1,Dial(SIP/provider2/${EXTEN},45)
exten => _00393.,n,Hangup
[gruppoa]
include => locale
[gruppob]
include => local
include => fisso
include => cellulare
Per comodità e chiarezza le macro le inseriamo tutte dopo il blocco [globals]
Per chiarimenti e/o correzioni non esitate a scrivere.
Commenti
ora ho capito
ho scoperto solo ora questo blog e lo sto leggendo tutto, dal primo articolo
ho capito moltissime cose, grazie !
Re: ora ho capito
Di niente...
:)