Was this page helpful?

DP: 語音留言通知功能

    內容表格
    1. 1. 相關討論串

    繼前些日子發表的 [Asterisk]語音信箱的應用~重要留言不遺漏  的文章以後,關於重要的留言,此篇將介紹另一個主動通知的功能。

    功能介紹:

    • 當分機有留言時,系統將主動撥指定的手機號碼通知你,當你接起電話後,即自動進入你的語音信箱,之後並可依留言信箱的操作功能,聽取新留言或刪除留言。
    • 以分機操作選擇啟動此功能或關閉,啟動過程需輸入要通知的手機號碼。

    適合版本: Asterisk 1.4.15(PBXinaFlash),如使用的是 Asterisk 1.2.x 請參考原文連結。

    筆者所作的改善:

    • 原作者的設計僅適用於 Asterisk 1.2.x 版,經筆者修改後可在 Asterisk 1.4.15 運作,但此修改版不可在 1.2.x 運行。
    • 發通知的電話號碼可為 outbound Trunk 或內部分機。
    • 修正原作版的小 bug:功能設定的操作時,語音播完時系統未等候即斷線,造成無法輸入功能鍵。

    成果說明:筆者實際以台灣大哥大的手機門號作為留言通知的號碼,手機型號為  Nokia 6120  Classic ,轉接手機的系統供應商是 CCNET,在接收到留言通知的電話後,以按鍵操作留言信箱的功能,均沒問題。

    原作連結: http://www.trixbox.org/forums/trixbo...our-cell-phone

    開始設定囉!

    第一步:開啟檔案 /etc/asterisk/extensions_custom.conf
    在 [from-internal-custom] 下方輸入

    ; Added a feature(*26) - VM Notify
    include => custom-vm-notify

    然後在最下方,貼上這一長串

    ; ************* VM Notify - Start *************
    ; This scenarios is written by BobH from the link
    ; http://www.trixbox.org/forums/trixbox-forums/trixbox-projects/vm-notify-have-voicemail-call-your-cell-phone
    ;
    [custom-vm-notify]
    
    ; Dial *26 to enable or disable Voicemail Out-calling
    exten => *26,1,Answer()
    exten => *26,2,Playback(please-enter-your&extension)
    exten => *26,3,Read(vmextension,then-press-pound)
    exten => *26,4,Set(phonenumber=${DB(vmnotify/${vmextension})})
    exten => *26,5,Gotoif($["foo${phonenumber}" = "foo"]?20:10)
    
    exten => *26,10,Playback(enabled&telephone-number&is-set-to)
    exten => *26,11,SayDigits(${phonenumber})
    exten => *26,12,Background(to-enter-a-diff-number&press-1&or)
    exten => *26,13,Background(press-2&for&disabled)
    exten => *26,14,WaitExten(,)
    
    exten => *26,20,Playback(disabled)
    exten => *26,21,Background(press-1&for&enabled)
    exten => *26,22,WaitExten(,)
    
    exten => 1,1,Playback(enter-phone-number10)
    exten => 1,2,Read(phonenumber,then-press-pound)
    exten => 1,3,Set(DB(vmnotify/${vmextension})=${phonenumber})
    exten => 1,4,Playback(enabled&telephone-number&is-set-to)
    exten => 1,5,SayDigits(${phonenumber})
    exten => 1,6,Hangup()
    
    exten => 2,1,DBdel(vmnotify/${vmextension})
    exten => 2,2,Playback(disabled)
    exten => 2,3,Hangup()
    
    exten => t,1,Hangup()
    
    [macro-vm-notify]
    
    exten => s,1,Set(phonenumber=${DB(vmnotify/${ARG1})})
    exten => s,2,Gotoif($["foo${phonenumber}" = "foo"]?:10) ;see if this vmbox has out-calling enabled
    
    ;check for new voicemails first
    exten => s,10,Set(count=${VMCOUNT(${ARG1}))
    exten => s,11,GotoIf($[ ${count} = 0 ]?:s,111)
    
    ;now build a .call file and then move it into the spool
    exten => s,111,Set(spooldir=/var/spool/asterisk)
    exten => s,n,System(echo "Channel: Local/"${phonenumber}"@from-internal" > ${spooldir}/${ARG1}.call)
    exten => s,n,System(echo "MaxRetries: 1" >> ${spooldir}/${ARG1}.call)
    exten => s,n,System(echo "RetryTime: 60" >> ${spooldir}/${ARG1}.call)
    exten => s,n,System(echo "WaitTime: 30" >> ${spooldir}/${ARG1}.call)
    exten => s,n,System(echo "Context: macro-vm-notify" >> ${spooldir}/${ARG1}.call)
    exten => s,n,System(echo "Extension: vmcall" >> ${spooldir}/${ARG1}.call)
    exten => s,n,System(echo "Priority: 1" >> ${spooldir}/${ARG1}.call)
    exten => s,n,System(echo "Setvar: vmext="${ARG1} >> ${spooldir}/${ARG1}.call)
    exten => s,n,System(mv ${spooldir}/${ARG1}.call ${spooldir}/outgoing/)
    
    ;This is where the .call file starts from
    exten => vmcall,1,Answer
    exten => vmcall,n,NoOp( Waiting for Answer )
    exten => vmcall,n,WaitForSilence(2000)
    exten => vmcall,n,NoOp( Hello )
    exten => vmcall,n,Goto(talk,1)
    
    ;Somebody answered or we timed out let them know it's a voicemail
    exten => talk,1,Wait(1)
    exten => talk,n,Background(this-is-the-voice-mail-system)
    exten => talk,n,Background(to-log-in-to-voice-mail)
    exten => talk,n,Background(press-1)
    exten => talk,n,Background(or)
    exten => talk,n,Background(to-hang-up)
    exten => talk,n,Background(press-2)
    ;Wait a little bit then repeat the message
    exten => talk,n,Wait(3)
    exten => talk,n,Background(this-is-the-voice-mail-system)
    exten => talk,n,Background(to-log-in-to-voice-mail)
    exten => talk,n,Background(press-1)
    exten => talk,n,Background(or)
    exten => talk,n,Background(to-hang-up)
    exten => talk,n,Background(press-2)
    
    ;drop them into the voicemail system
    exten => 1,1,Wait(1)
    exten => 1,n,VoiceMailMain(${vmext}@default)
    
    ;they don't want to talk to us
    exten => 2,1,Wait(1)
    exten => 2,n,Playback(vm-goodbye)
    exten => 2,n,Hangup
    
    ;They must be ignoring us
    exten => t,1,Hangup
    
    ; copied macro-vm from extensions.conf so we could add the h extension to start the notify
    ;
    [macro-vm]
    ; ARG1 - extension
    ; ARG2 - DIRECTDIAL/BUSY
    exten => s,1,Macro(user-callerid,SKIPTTL)
    exten => s,n,Set(VMGAIN=${IF($["foo${VM_GAIN}"!="foo"]?"g(${VM_GAIN})":"")})
    ;
    ; If BLKVM_OVERRIDE is set, then someone told us to block calls from going to
    ; voicemail. This variable is reset by the answering channel so subsequent
    ; transfers will properly function.
    ;
    exten => s,n,GotoIf($["foo${DB(${BLKVM_OVERRIDE})}" != "fooTRUE"]?vmx,1)
    ;
    ; we didn't branch so block this from voicemail
    ;
    exten => s,n,Noop(CAME FROM: ${NODEST} - Blocking VM cause of key: ${DB(BLKVM_OVERRIDE)})
    
    
    ; If vmx not enabled for the current mode,then jump to normal voicemail behavior
    ; also - if not message (no-msg) is requested, straight to voicemail
    ;
    exten => vmx,1,GotoIf($["${ARG2}"="NOMESSAGE"]?s-${ARG2},1)
    exten => vmx,n,Set(MODE=${IF($["${ARG2}"="BUSY"]?busy:unavail)})
    exten => vmx,n,GotoIf($["${ARG2}" != "DIRECTDIAL"]?notdirect)
    exten => vmx,n,Set(MODE=${IF($["${REGEX("[b]" ${VM_DDTYPE})}" = "1"]?busy:${MODE})})
    exten => vmx,n(notdirect),Noop(Checking if ext ${ARG1} is enabled: ${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)})
    exten => vmx,n,GotoIf($["${DB(AMPUSER/${ARG1}/vmx/${MODE}/state)}" != "enabled"]?s-${ARG2},1)
    
    ; If the required voicemail file does not exist, then abort and go to normal voicemail behavior
    ;
    ; TODO: there have been errors using System() with jump to 101 where asterisk works fine at the begining and
    ;       then starts to jump to 101 even on success. This new mode is being tried with the SYSTEM Status which
    ;       returns SUCCESS when the command returned succcessfully with a 0 app return code.
    ;
    exten => vmx,n,Macro(get-vmcontext,${ARG1})
    ;exten => vmx,n,TrySystem(/bin/ls ${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE}.[wW][aA][vV])
    exten => vmx,n,AGI(checksound.agi,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE})
    exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" != "SUCCESS"]?nofile)
    
    ; Get the repeat, timeout and loop times to use if they are overriden form the global settings
    ;
    exten => vmx,n,Set(LOOPCOUNT=0)
    exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/repeat)}" = "0"]?vmxtime)
    exten => vmx,n,Set(VMX_REPEAT=${DB_RESULT})
    exten => vmx,n(vmxtime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timeout)}" = "0"]?vmxloops)
    exten => vmx,n,Set(VMX_TIMEOUT=${DB_RESULT})
    exten => vmx,n(vmxloops),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loops)}" = "0"]?vmxanswer)
    exten => vmx,n,Set(VMX_LOOPS=${DB_RESULT})
    exten => vmx,n(vmxanswer),Answer()
    
    ; Now play the users voicemail recording as the basis for their ivr, the Read command will repeat as needed and if it timesout
    ; then we go to the timeout. Otherwise handle invalid options by looping until the limit until a valid option is played.
    ;
    exten => vmx,n(loopstart),Read(ACTION,${ASTSPOOLDIR}/voicemail/${VMCONTEXT}/${ARG1}/${MODE},1,skip,${VMX_REPEAT},${VMX_TIMEOUT})
    exten => vmx,n,GotoIf($["${EXISTS(${ACTION})}" = "1"]?checkopt)
    
    ; If we are here we timed out, go to the required destination
    ;
    exten => vmx,n(noopt),Noop(Timeout: going to timeout dest)
    exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_TIMEOUT})
    exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/timeout)}" = "0"]?chktime)
    exten => vmx,n,Set(VMX_OPTS=${DB_RESULT})
    exten => vmx,n(chktime),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/ext)}" = "0"]?dotime)
    exten => vmx,n,Set(VMX_TIMEDEST_EXT=${DB_RESULT})
    exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/context)}" = "0"]?timepri)
    exten => vmx,n,Set(VMX_TIMEDEST_CONTEXT=${DB_RESULT})
    exten => vmx,n(timepri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/timedest/pri)}" = "0"]?dotime)
    exten => vmx,n,Set(VMX_TIMEDEST_PRI=${DB_RESULT})
    exten => vmx,n(dotime),Goto(${VMX_TIMEDEST_CONTEXT},${VMX_TIMEDEST_EXT},${VMX_TIMEDEST_PRI})
    
    ; We got an option, check if the option is defined, or one of the system defaults
    ;
    exten => vmx,n(checkopt),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/ext)}" = "1"]?doopt)
    exten => vmx,n,GotoIf($["${ACTION}" = "0"]?o,1)
    exten => vmx,n,GotoIf($["${ACTION}" = "*"]?adef,1)
    
    ; Got invalid option loop until the max
    ;
    exten => vmx,n,Set(LOOPCOUNT=$[${LOOPCOUNT} + 1])
    exten => vmx,n,GotoIf($[${LOOPCOUNT} > ${VMX_LOOPS}]?toomany)
    exten => vmx,n,Playback(pm-invalid-option&please-try-again)
    exten => vmx,n,Goto(loopstart)
    
    ; tomany: to many invalid options, go to the specified destination
    ;
    exten => vmx,n(toomany),Noop(Too Many invalid entries, got to invalid dest)
    exten => vmx,n,Set(VMX_OPTS=${VMX_OPTS_LOOPS})
    exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/loops)}" = "0"]?chkloop)
    exten => vmx,n,Set(VMX_OPTS=${DB_RESULT})
    exten => vmx,n(chkloop),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/ext)}" = "0"]?doloop)
    exten => vmx,n,Set(VMX_LOOPDEST_EXT=${DB_RESULT})
    exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/context)}" = "0"]?looppri)
    exten => vmx,n,Set(VMX_LOOPDEST_CONTEXT=${DB_RESULT}) ;TODO make configurable per above
    exten => vmx,n(looppri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/loopdest/pri)}" = "0"]?doloop)
    exten => vmx,n,Set(VMX_LOOPDEST_PRI=${DB_RESULT}) ;TODO make configurable per above
    exten => vmx,n(doloop),Goto(${VMX_LOOPDEST_CONTEXT},${VMX_LOOPDEST_EXT},${VMX_LOOPDEST_PRI})
    
    ; doopt: execute the valid option that was chosen
    ;
    exten => vmx,n(doopt),Noop(Got a valid option: ${DB_RESULT})
    exten => vmx,n,Set(VMX_EXT=${DB_RESULT})
    ;
    ; Special case, if this option was to go to voicemail, set options and go
    ;
    exten => vmx,n,GotoIf($["${VMX_EXT}" != "dovm"]?getdest)
    exten => vmx,n(vmxopts),Set(VMX_OPTS=${VMX_OPTS_DOVM})
    exten => vmx,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/vmxopts/dovm)}" = "0"]?vmxdovm)
    exten => vmx,n(vmxopts),Set(VMX_OPTS=${DB_RESULT})
    exten => vmx,n(vmxdovm),goto(dovm,1)
    ;
    ; General case, setup the goto destination and go there (no error checking, its up to the GUI's to assure
    ; reasonable values
    ;
    exten => vmx,n(getdest),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/context)}" = "0"]?vmxpri)
    exten => vmx,n,Set(VMX_CONTEXT=${DB_RESULT})
    exten => vmx,n(vmxpri),GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/${ACTION}/pri)}" = "0"]?vmxgoto)
    exten => vmx,n,Set(VMX_PRI=${DB_RESULT})
    exten => vmx,n(vmxgoto),Goto(${VMX_CONTEXT},${VMX_EXT},${VMX_PRI})
    
    ; If the required voicemail file is not present, then revert to normal voicemail
    ; behavior treating as if it was not set
    ;
    exten => vmx,n(nofile),Noop(File for mode: ${MODE} does not exist, SYSTEMSTATUS: ${SYSTEMSTATUS}, going to normal voicemail)
    exten => vmx,n,Goto(s-${ARG2},1)
    
    ; Drop into voicemail either as a direct destination (in which case VMX_OPTS might be set to something) or
    ; if the user timed out or broke out of the loop then VMX_OPTS is always cleared such that an Allison
    ; message is played and the caller know's what is going on.
    ;
    exten => dovm,1,Noop(VMX Timeout - go to voicemail)
    exten => dovm,n,Voicemail(${ARG1}@${VMCONTEXT},${VMX_OPTS}${VMGAIN}) ; no flags, so allison plays please leave ...
    exten => dovm,n,Goto(exit-${VMSTATUS},1)
    
    exten => s-BUSY,1,NoOp(BUSY voicemail)
    exten => s-BUSY,n,Macro(get-vmcontext,${ARG1})
    exten => s-BUSY,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}b${VMGAIN})   ; Voicemail Busy message
    exten => s-BUSY,n,Goto(exit-${VMSTATUS},1)
    
    exten => s-NOMESSAGE,1,NoOp(NOMESSAGE (beeb only) voicemail)
    exten => s-NOMESSAGE,n,Macro(get-vmcontext,${ARG1})
    exten => s-NOMESSAGE,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VMGAIN})   ; Voicemail Busy message
    exten => s-NOMESSAGE,n,Goto(exit-${VMSTATUS},1)
    
    exten => s-DIRECTDIAL,1,NoOp(DIRECTDIAL voicemail)
    exten => s-DIRECTDIAL,n,Macro(get-vmcontext,${ARG1})
    exten => s-DIRECTDIAL,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}${VM_DDTYPE}${VMGAIN})
    exten => s-DIRECTDIAL,n,Goto(exit-${VMSTATUS},1)
    
    exten => _s-.,1,Macro(get-vmcontext,${ARG1})
    exten => _s-.,n,Voicemail(${ARG1}@${VMCONTEXT},${VM_OPTS}u${VMGAIN})     ; Voicemail Unavailable message
    exten => _s-.,n,Goto(exit-${VMSTATUS},1)
    
    ; If the user has a 0 option defined, use that for operator zero-out from within voicemail
    ; as well to keep it consistant with the menu structure
    ;
    exten => o,1,Background(one-moment-please)      ; 0 during vm message will hangup
    exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/ext)}" = "0"]?doopdef)
    
    exten => o,n,Set(VMX_OPDEST_EXT=${DB_RESULT})
    exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/context)}" = "1"]?opcontext)
    exten => o,n,Set(DB_RESULT=${VMX_CONTEXT})
    exten => o,n(opcontext),Set(VMX_OPDEST_CONTEXT=${DB_RESULT})
    exten => o,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/0/pri)}" = "1"]?oppri)
    exten => o,n,Set(DB_RESULT=${VMX_PRI})
    exten => o,n(oppri),Set(VMX_OPDEST_PRI=${DB_RESULT})
    
    exten => o,n,Goto(${VMX_OPDEST_CONTEXT},${VMX_OPDEST_EXT},${VMX_OPDEST_PRI})
    exten => o,n(doopdef),GotoIf($["x${OPERATOR_XTN}"="x"]?nooper:from-internal,${OPERATOR_XTN},1)
    exten => o,n(nooper),GotoIf($["x${FROM_DID}"="x"]?nodid)
    exten => o,n,Dial(Local/${FROM_DID)@from-pstn)
    exten => o,n,Macro(hangup)
    exten => o,n(nodid),Dial(Local/[email protected])
    exten => o,n,Macro(hangup)
    
    ; If the user has a * option defined, use that for the * out from within voicemail
    ; as well to keep it consistant with the menu structure
    ;
    exten => a,1,Macro(get-vmcontext,${ARG1})
    exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/ext)}" = "0"]?adef,1)
    
    exten => a,n,Set(VMX_ADEST_EXT=${DB_RESULT})
    exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/context)}" = "1"]?acontext)
    exten => a,n,Set(DB_RESULT=${VMX_CONTEXT})
    exten => a,n(acontext),Set(VMX_ADEST_CONTEXT=${DB_RESULT})
    exten => a,n,GotoIf($["${DB_EXISTS(AMPUSER/${ARG1}/vmx/${MODE}/*/pri)}" = "1"]?apri)
    exten => a,n,Set(DB_RESULT=${VMX_PRI})
    exten => a,n(apri),Set(VMX_ADEST_PRI=${DB_RESULT})
    exten => a,n,Goto(${VMX_ADEST_CONTEXT},${VMX_ADEST_EXT},${VMX_ADEST_PRI})
    
    exten => adef,1,VoiceMailMain(${ARG1}@${VMCONTEXT})
    exten => adef,n,Hangup
    
    exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured)
    exten => exit-FAILED,n,Hangup()
    
    exten => exit-SUCCESS,1,Playback(goodbye)
    exten => exit-SUCCESS,n,Hangup()
    
    exten => exit-USEREXIT,1,Playback(goodbye)
    exten => exit-USEREXIT,n,Hangup()
    
    exten => t,1,Hangup()
    
    exten => h,1,Macro(vm-notify,${ARG1}) ; this will start the vm-notification macro when the call is done
    
    ; get the voicemail context for the user in ARG1
    ; ************* VM Notify - End *************
    

    第二步:重啟 Asterisk

    #Asterisk -rx "restart now"

    完成囉!

    功能操作方式:

    開啟> 以分機的電話輸入 *26 -> 輸入欲設定留言通知的分機號碼,完成請按# -> 目前是關閉模式,按 1  開啟此功能 -> 輸入手機號碼,完成請按# -> 已設定為開啟模式,設定的號碼為xxxxxxxxx。

    關閉> 以分機的電話輸入*26 -> 輸入欲設定留言通知的分機號碼,完成請按# -> 目前是開啟模式,設定的手機號碼為xxxxxxxxxx,按 1 變更號碼設定,按 2 關閉此功能。

    Was this page helpful?
    標籤 (Edit tags)
    • No tags
    您必須 登入 才能發佈評論。
    Powered by MindTouch Core