是的,就像程式語言中的自訂函數,或是試算表中的自訂巨集,Asterisk 也可以自訂巨集及函數。
[巨集]
我也不往複雜的說,簡單說 Macro 非常像『簡化版的 Context』,至於 Context 可以回頭找找 Q025。一樣,我們從實例看起:
[macro-voicemail]
exten => s,1,NoOp()
same => n,Dial(${ARG1},10)
same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
same => n(unavail),VoiceMail(${MACRO_EXTEN}@default,u)
same => n,Hangup()
same => n(busy),VoiceMail(${MACRO_EXTEN}@default,b)
same => n,Hangup()
- 名稱一定要以 macro- 開頭
- 因為定義巨集時並不知道分機號碼,這邊採用 s 來代表呼叫者的分機號碼
- 底下介紹四個巨集內可以使用的變數:
${MACRO_CONTEXT} 呼叫者的 Context
${MACRO_EXTEN} 呼叫者的分機號
${MACRO_PRIORITY} 呼叫者所在的權值
${ARGn} 傳入的第 n 個參數,從 1 開始,例如 ${ARG1}, ${ARG2}
exten => 101,1,Macro(voicemail,${JOHN})
exten => 102,1,Macro(voicemail,${JANE})
exten => 103,1,Macro(voicemail,${JACK})
比較一下巨集命名與呼叫時的引用名稱,參數,變數。
在巨集呼叫中的 ARGn, MACRO_EXTEN 會被取代成
101, JOHN
102, JANE
103, JACK
請仔細閱讀這幾個呼叫範例就會明白巨集呼叫時參數用法,以及上面四個變數的用法
上面範例還有一個變形,可以比較用法的差異:
[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)
上例 Goto(s-XXX) 這樣的語法相當容易理解,把它想成字串就好,這樣的寫法應該更容易閱讀(如果沒有就用前一種寫法嘛)。Dial() 的傳回狀態有幾種:
ANSWER, BUSY, NOANSWER, CANCEL, CONGESTION, CHANUNAVAIL, DONTCALL, TORTURE, INVALIDARGS
如果仔細研讀上面的範例,其實可以修改成如下,讀不懂也沒關係喔,戲法人人會變,只要能正確作動,其實沒有什麼美醜好壞之別:
[macro-voicemail]
exten => s,1,NoOp()
same => n,Dial(${ARG1},20)
same => n,VoiceMail(${MACRO_EXTEN}@default,${IF($[${DIALSTATUS}
= BUSY]?b:u)})
這邊沒有說到的內容是,像 Dial() 本身可以相當複雜,也可以引用巨集,有機會再另外說明 Dial() 時再說(應該沒體力寫了)
[函數]
函數看起來很像巨集,一樣直接看範例,就用上面最後一個簡化版本:
[subVoicemail]
exten => start,1,NoOp()
same => n,Dial(${ARG1},20)
same => n,VoiceMail(${ARG2}@default,${IF($[${DIALSTATUS}
= BUSY]?b:u)})
有兩點不一樣:
- [macro-voicemail] 變成 [subVoicemail]
GoSub() 的自訂函數其實沒有像巨集那樣的用法,比較像 Context,後面呼叫會看到,這邊的寫法是讓我們自己濾 - 分機號碼由 s 變成 start
- 巨集變數都不能用,只能取得參數 ${ARGn} 而已
- 不像巨集會自動返回呼叫者,GoSub() 必須自行指定是否返回,否則執行完函數就結束了
呼叫範例:
exten => 101,1,GoSub(subVoicemail,start,1(${JOHN},${EXTEN}))
exten => 102,1,GoSub(subVoicemail,start,1(${JANE},${EXTEN}))
exten => 103,1,GoSub(subVoicemail,start,1(${JACK},${EXTEN}))
為了說明返回,我們以底下的例子來說明:
[subDialer]
exten => start,1,NoOp()
same => n,Dial(${ARG1},${ARG2})
same => n,Return()
[subVoicemail]
exten => start,1,NoOp()
same => n,VoiceMail(${ARG1}@${ARG2},${ARG3})
same => n,Hangup()
呼叫時如下:
exten => 101,1,NoOp()
same => n,GoSub(subDialer,start,1(${JOHN},30))
same => n,GoSub(subVoicemail,start,1(${EXTEN},default,u))
如果自訂函數都沒有寫最後一行的 Return(), 那麼呼叫範例並不會執行最後一行的 GoSub(subVoicemail.....)
不過上例並沒有很好的把 Dial() 狀態傳回,底下是修改版本,而且 [subVoicemail] 以這個例子也不必 Return():
[subDialer]
exten => start,1,NoOp()
same => n,Dial(${ARG1},${ARG2})
same => n,Return(${DIALSTATUS})
[subVoicemail]
exten => start,1,NoOp()
same => n,VoiceMail(${ARG1}@${ARG2},${ARG3})
same => n,Hangup()
呼叫例使用 ${GOSUB_RETVAL} 來取得傳回值:
exten => 101,1,NoOp()
same => n,GoSub(subDialer,start,1(${JOHN},30))
same => n,Set(VoicemailMessage=${IF($[${GOSUB_RETVAL} = BUSY]?b:u)})
same => n,GoSub(subVoicemail,start,1(${EXTEN},default,${VoicemailMessage}))
0 意見:
張貼留言