Basic Expressions

Asterisk 에서 모든 표현식(수식)은 $ [ ] 표시된다.

$[expression]

그리고 다음과 같이 사용할 수 있다.

$[${COUNT} + 1]$[${COUNT} / 2]

Asterisk Dialplan 내에서 표현식이 있다면 해당 구문은 먼저 모든 표현식이 계산된 이후에 진행된다.
다음의 예제를 생각해보자.

exten => 204,1,Noop()
        same => n,Answer()
        same => n,Set(COUNT=3)
        same => n,Set(NEWCOUNT=$[${COUNT} + 1])
        same => n,SayNumber(${NEWCOUNT})

2번째 priority 에서 COUNT 변수에 3을 입력했다.
그리고 3번째 priority 에서 하나의 Set appilication 만이 사용됐는데, 사실은 3가지 일이 벌어졌다.

1. ${COUNT} 를 3으로 대치한다. 즉, 표현식은 다음과 같이 변경된다.
same => n,Set(NEWCOUNT=$[3 + 1])

2. 표현식을 계산한다. 즉, 3과 1을 더한다. 결과값 4가 나온다.
same => n,Set(NEWCOUNT=4)

3. Set() Application이 NEWCOUNT 에 4를 입력한다.

Operators

Boolean operators

expr1 | expr2
or 연산자. expr1 혹은 expr2 둘 중 하나라도 참이라면 참.

expr1 & expr2
and 연산자. expr1 혹은 expr2 둘 중 하나라도 거짓이면 거짓.

expr1 {=, >, >=, <, <=, !=} expr2비교 연산자. expr1, expr2 각 숫자라면 숫자 비교를 하고, 아니라면 문자열 비교를 한다.

Mathematical operators

expr1 {+, -} expr2
더하기, 빼기.

expr1 {*, /, %} expr2
곱하기, 나누기, 나머지.

Regular expression operators

expr1 : expr2
정규 표현식 내용 참조.

expr1 =~ expr2
정규 표현식 내용 참조.

String
exten => 234,1,Set(NEWTEST=blah${TEST})

Dialplan Functions

Dialplan Function 들은 많은 기능들을 가지고 있다. 문자열 길이 계산, 시간 및 날짜 계산, MD5 체크섬 오류 확인 등등의 기능을 제공한다.

Syntax

Dialplan Function 은 다음과 같은 기본 Syntax 구조를 가진다.

FUNCTION_NAME(argument)

그리고 다음과 같이 Function 자체가 다른 Function 의 Argument 로 사용되는 것도 가능하다.

${FUNCTION_NAME(${FUNCTION_NAME(argument)})}

Conditional Branching

Asterisk 에서 제공하는 함수들을 이용하면 여러가지 조건에 따라 분기를 생성할 수 있다. 이를 Conditional Branching 이라고 한다.

The GotoIf() Application

Conditional Branching 의 핵심은 GotoIf() Application 이다. GotoIf() Application 은 입력된 조건 식의 참/거짓 여부에 따라 해당 콜을 다른 곳으로 분배시키는 역할을 한다.

GotoIf(expression?destination1:destination2)

만약 expression 이 참이면 destination1로, 거짓이면 destination2 로 해당 콜을 넘겨준다. 그렇다면 무엇이 참이고 거짓일까? 표현식의 결과값이 공백 String 이거나 0이면 거짓이고 그 외의 것들은 모두 참으로 판별한다.
destination 은 다음중 한가지로 지정할 수 있다.

– weasels 와 같이  동일한 extension 내의 priority label- 123,wesels 와 같이 동일한 context 내의 다른 extension 과 priority label
– incoming,123,weasels 와 같이 다른 context, 다른 extension, 다른 priority label

입력되는 destination 중 하나는 생략이 가능하다. 즉, 하나의 destination 만 입력을 해도 괜찮다는 뜻이다. 하지만 이는 역으로 반드시 하나는 입력해야 된다는 뜻이다. 입력되지 않은 destination 의 경우, 그냥 다음 priority 구문을 진행한다.

exten => 207,1,NoOp()
        same => n,Set(TEST=1)
        same => n,GotoIf($[${TEST} = 1]?weasels:iguanas)
        same => n(weasels),Playback(weasels-eaten-phonesys)
        same => n,Hangup()
        same => n(iguanas),Playback(office-iguanas)
        same => n,Hangup()

기능은 정상적으로 작동하지만 뭔가 알아보기 힘들다. 다음과 같이 작성해보자.

exten => 208,1,NoOp()
        same => n,Answer()
        same => n,Set(TEST=1)
        same => n,GotoIf($[${TEST} = 1]?weasels,1:iguanas,1)    ; now we're going to extension,priority
exten => weasels,1,NoOp()
        same => n,Playback(weasels-eaten-phonesys)      ; this is NOT a label. It is different extension
        same => n,Hangup()
exten => iguanas,1,NoOp()
        same => n,Playback(office-iguanas)
        same => n,Hangup()

다음은 10부터 0까지 카운트 다운을 하는 Dialplan 이다.

exten => 209,1,NoOp()
        same => n,Answer()
        same => n,Set(COUNT=10)
        same => n(start),GotoIf($[${COUNT} > 0]?:goodbye)
        same => n,SayNumber(${COUNT})
        same => n,Set(COUNT=$[${COUNT} - 1])
        same => n,Goto(start)
        same => n(goodbye),Hangup()

 Time-Based Conditional Branching with GotoIfTime()

GotoIf() Application 이 표현식에 따른 분기였다면, GotoIfTime() Application 은 system time 에 따른 분기라고 말할 수 있다.

GotoIfTime(times,days_of_week,days_of_month,months?label)

짧게 말해서, GotoIfTime() 은 지정된 시간에 콜을 지정된 label 로 보내는 Application 이라고 할 수 있다.

times:
시간대 범위. 하나 혹은 여러개를 지정할 수 있다. 24-hour 형식을 사용함. 예를 들어 09:00 AM 부터 05:00 PM 까지의 시간대를 지정한다면 09:00-17:00 으로 표시할 수 있다. 하루를 통째로 입력한다면 00:00-23:59 로 표시한다.

days_of_week:
요일 범위. 하나 혹은 여러개를 지정할 수 있다. mon,tue,wed,thu,fri,sat,sun 으로만 표시가 가능하다. 월요일부터 금요일까지를 표시하고자 한다면 mon-fri 로 표시한다. 화요일과 목요일만 표시하고자 한다면 tue&thu 로 표시한다.

days_of_month:
일 범위. 하나 혹은 여러개를 지정할 수 있다. 1 부터 31 까지 지정하고자 하는 날짜를 입력하면 된다. 7일부터 12일까지라면 7-12, 15일과 30일 이틀만 지정하고자 한다면 15&30 으로 표시한다.

month:
달 범위. 하나 혹은 여러개를 지정할 수 있다. jan-apr 과 같이 지정 가능하며 jan&mar&jun 과 같은 지정도 가능하다. 물론 jan-apr&jun&oct-dec 와 같은 지정도 가능하다.

모든 범위:
만약 모든 날짜(1년 내내와 같이..)를 지정하고자 한다면 해당 입력 부분에 * 표시를 입력하면 된다.

label:
같은 extension 부분에 있는 priority. ex) time_has_passed
같은 context 에 있는 다른 extension, priority. ex) 123,time_has_passed
다른 context, extension, priority. ex) incoming,123,time_has_passed

예제를 보자. 매주 월요일부터 금요일까지 오전 9:00 부터 오후 05:59 사이에 오는 콜을 처리하는 Dialplan 이다.

exten => s,1,NoOp()
    same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)

만약 발신자가 해당 시간에 전화를 하게 되면 open context 내의 s extension 의 첫번째 priority 구문을 실행한다.

아래 예제는 참고로 보길 바란다.

exten => 212,1,NoOp()
        same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)

; If it's any hour of the day, on any day of the week,
; during the fourth day of the month, in the month of July,
; we're closed
        same => n,GotoIfTime(*,*,4,jul?closed,s,1)

; During business hours, send calls to the open context
        same => n,GotoIfTime(09:00-17:59,mon-fri,*,*?open,s,1)
        same => n,GotoIfTime(09:00-11:59,sat,*,*?open,s,1)

Macro

만약 여러개의 Dialplan 을 편집해야 한다면? 그 수가 굉장히 많다면? Macro 가 그 해답일 수 있다.

모든 Macro 는 macro- 구문으로 시작한다. 만약 voicemail 을 위한 Macro 를 생성한다면 다음처럼 생성하면 된다.

[macro-voicemail]

다음은 예제로 작성된 voicemail macro 이다.

[macro-voicemail]
exten => s,1,NoOp()
        same => n,Dial(${JOHN},10)
        same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
        same => n(unavail),VoiceMail(101@default,u)
        same => n,Hangup()
        same => n(busy),VoiceMail(101@default,b)
        same => n,Hangup()

Calling Macros from the Dialplan

Dialplan 에서 Macro 를 사용하기 위해서는 Macro() application 이 필요하다. Macro() application 은 Macro 를 호출하고 인자값들을 넘겨주는 역할을 한다.
예를 들어 방금 생성한 voicemail macro 를 호출하기 위해서는 다음과 같이 작성하면 된다.

exten => 213,1,Macro(voicemail)

Macro() application 은 특수 변수들을 가지고 있다.

${MACRO_CONTEXT}
Macro 를 호출한 extension 의 context

${MACRO_EXTEN}Macro 를 호출한 Extension

${MACRO_PRIORITY}
Macro 를 호출한 Priority

${ARG n}
Macro 를 호출하면서 넘겨진 인자 값들. 첫번째 인자값은 ${ARG1}, 두번째 인자값은 ${ARG2} 와 같다.

자, 이제 조금전 생성한 voicemail macro 를 수정해보자. 조금전 생성한 voicemail macro 는 오직 101 extension 에 대해서만 voicemail 을 수행했었다.
이를 호출되는 extension 의 voicemail 로 수정해보자.

[macro-voicemail]
exten => s,1,NoOp()
        same => n,Dial(${ARG1},20)
        same => n,Goto(s-${DIALSTATUS},1)

exten => s-NOANSWER,1,VoiceMail(${MACRO_EXTEN}@default,u)
        same => n,Goto(incoming,s,1)

exten => s-BUSY,1,VoiceMail(${MACRO_EXTEN}@default,b)
        same => n,Goto(incoming,s,1)

exten => _s-.,1,NoOp()
        same => n,Goto(s-NOANSWER,1)

GoSub

GoSub() application 은 Macro() application 과 비슷하다. 하지만 Macro() 와는 달리 별도의 Naming rule 이 필요하지 않다. 하지만 GoSub 루틴임을 알리기 위해 prefix 를 붙이는 것이 관례적이다.
다음은 Subroutine 예제이다.

[subVoicemail]
exten => start,1,NoOp()
        same => n,Dial(${ARG1},10)
        same => n,VoiceMail(${ARG2}@default,${IF($[DIALSTATUS} = BUSY]?b:u)})
        same => n,Hangup()

[LocalSets]
exten => 217,1,GoSub(subVoicemail,start,1(${JOHN},${EXTEN}))
exten => 218,1,GoSub(subVoicemail,start,1(${JANE},${EXTEN}))
exten => 219,1,GoSub(subVoicemail,start,1(${JACK},${EXTEN}))

 

 

Tags: ,

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.