Incoming calls don't work after upgrade

So, everything was working fine, until I upgraded from 2.3 to 2.4. After doing that, incoming calls would not work anymore. Anytime a caller would connect, it would ring once(on the caller end, not on the receiving) and then say “Goodbye”. I ended up also upgrading it to 2.5, but the problem remained.

I noticed it was going to the default context. I switched it to go to from-pstn. When it ran from from-pstn it would get into some sort of loop. On the caller end it would just keep ringing but never go through. I had the CLI up with verbosity at 5 when it all happened. I could see it go through each line in “from-pstn” and then start back at the first line and loop continuously until I restarted asterisk.

At that point, I took out from-pstn and pointed it towards from-zaptel. Now it doesn’t loop, but it still doesn’t go through. Below are the errors and config files.

I’m sure it’s something simple, but I actually wasn’t the one who set this up. Now I’m in charge of it, but don’t know much about it.
Thanks for any help!

Current log entry:

Nov 2 12:14:43] VERBOSE[17448] logger.c: -- Starting simple switch on 'Zap/1-1'
[Nov 2 12:14:44] NOTICE[17448] callerid.c: Caller*ID failed checksum
[Nov 2 12:14:47] NOTICE[17448] chan_zap.c: Got event 18 (Ring Begin)...
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:1] NoOp("Zap/1-1", "Entering from-zaptel with DID == ") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:2] Ringing("Zap/1-1", "") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:3] Set("Zap/1-1", "DID=s") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:4] NoOp("Zap/1-1", "DID is now s") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:5] GotoIf("Zap/1-1", "1?zapok:notzap") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Goto (from-zaptel,s,8)
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:8] NoOp("Zap/1-1", "Is a Zaptel Channel") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:9] Set("Zap/1-1", "CHAN=1-1") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:10] Set("Zap/1-1", "CHAN=1") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:11] Macro("Zap/1-1", "from-zaptel-1|s|1") in new stack
[Nov 2 12:14:47] WARNING[17448] app_macro.c: No such context 'macro-from-zaptel-1' for macro 'from-zaptel-1'
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:12] NoOp("Zap/1-1", "Returned from Macro from-zaptel-1") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Executing [s@from-zaptel:13] Goto("Zap/1-1", "from-pstn|s|1") in new stack
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Goto (from-pstn,s,1)
[Nov 2 12:14:47] WARNING[17448] pbx.c: Channel 'Zap/1-1' sent into invalid extension 's' in context 'from-pstn', but no invalid handler
[Nov 2 12:14:47] VERBOSE[17448] logger.c: -- Hungup 'Zap/1-1'

Current extensions.conf

;--------------------------------------------------------------------------------;
; Do NOT edit this file as it is auto-generated by FreePBX. All modifications to ;
; this file must be done via the web gui. There are alternative files to make    ;
; custom modifications, details at: http://freepbx.org/configuration_files       ;
;--------------------------------------------------------------------------------;
;

; FreePBX
; Copyright (C) 2004 Coalescent Systems Inc (Canada)
; Copyright (C) 2006 Why Pay More 4 Less Pty Ltd (Australia)
; Copyright (C) 2007 Astrogen LLC (USA)
; Released under the GNU GPL Licence version 2.

; dialparties.agi (http://www.sprackett.com/asterisk/)
; Asterisk::AGI (http://asterisk.gnuinter.net/)
; gsm (http://www.ibiblio.org/pub/Linux/utils/compress/!INDEX.short.html)
; loligo sounds (http://www.loligo.com/asterisk/sounds/)
; mpg123 (http://voip-info.org/wiki-Asterisk+config+musiconhold.conf)

;**************************  -WARNING-  ****************************************
;                                                                              *
; This include file is to be used with extreme caution. In almost all cases    *
; any custom dialplan SHOULD be put in extensions_custom.conf which will       *
; not hurt a FreePBX generated dialplan. In some very rare and custom          *
; situations users may have a need to override what freepbx automatically      *
; generates. If so anything in this file will do that.  If you come up with a  *
; situation where you need to modify the existing dialplan or macro, please    *
; put it here and also notify the FreePBX development team so they can take it *
; into account in the future.                                                  *
;                                                                              *
#include extensions_override_freepbx.conf
;                                                                              *
;**************************  -WARNING-  ****************************************

; include extension contexts generated from AMP
#include extensions_additional.conf

; Customizations to this dialplan should be made in extensions_custom.conf
; See extensions_custom.conf.sample for an example.
; If you need to use [macro-dialout-trunk-predial-hook], [ext-did-custom], or 
; [from-internal-custom] for example, place these in this file or they will get overwritten.
;
#include extensions_custom.conf

[from-trunk]							; just an alias since VoIP shouldn't be called PSTN
include => from-pstn

exten => _X.,1,Set(DID=${EXTEN})

exten => _X.,n,Goto(s,1)

exten => s,1,NoOp(Entering from-zaptel with DID == ${DID})

; Some trunks _require_ a RINGING be sent before an Answer.

exten => s,n,Ringing()

; If ($did == "") { $did = "s"; }

exten => s,n,Set(DID=${IF($["${DID}"= ""]?s:${DID})})

exten => s,n,NoOp(DID is now ${DID})

exten => s,n,GotoIf($["${CHANNEL:0:3}"="Zap"]?zapok:notzap)

exten => s,n(notzap),Goto(from-pstn,${DID},1)

; If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup.

exten => s,n,Macro(hangup)

exten => s,n(zapok),NoOp(Is a Zaptel Channel)

exten => s,n,Set(CHAN=${CHANNEL:4})

exten => s,n,Set(CHAN=${CUT(CHAN,-,1)})

exten => s,n,Macro(from-zaptel-${CHAN},${DID},1)

; If nothing there, then treat it as a DID

exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN})

exten => s,n,Goto(from-pstn,${DID},1)

exten => fax,1,Goto(ext-fax,in_fax,1)

 

; MODIFICATION (PL) 
;
; Required to assure that direct dids go to personal ring group before local extension.
; This could be auto-generated however I it is prefered to be put here and hard coded
; so that it can be modified if ext-local should take precedence in certain situations.
; will have to decide what to do later.
;
[from-did-direct]
include => ext-findmefollow
include => ext-local



; ############################################################################
; Macros [macro]
; ############################################################################

; Rings one or more extensions.  Handles things like call forwarding and DND
; We don't call dial directly for anything internal anymore.
; ARGS: $TIMER, $OPTIONS, $EXT1, $EXT2, $EXT3, ...
; Use a Macro call such as the following: 
;  Macro(dial,$DIAL_TIMER,$DIAL_OPTIONS,$EXT1,$EXT2,$EXT3,...)
[macro-dial]
exten => s,1,GotoIf($["${MOHCLASS}" = ""]?dial)
exten => s,n,SetMusicOnHold(${MOHCLASS})
exten => s,n(dial),AGI(dialparties.agi)
exten => s,n,NoOp(Returned from dialparties with no extensions to call and DIALSTATUS: ${DIALSTATUS})

exten => s,n+2(normdial),Dial(${ds})                               ; dialparties will set the priority to 10 if $ds is not null
exten => s,n,Set(DIALSTATUS=${IF($["${DIALSTATUS_CW}"!="" ]?${DIALSTATUS_CW}:${DIALSTATUS})})
exten => s,n,GosubIf($["${SCREEN}" != ""]?${DIALSTATUS},1)

exten => s,20(huntdial),NoOp(Returned from dialparties with hunt groups to dial )
exten => s,n,Set(HuntLoop=0)
exten => s,n(a22),GotoIf($[${HuntMembers} >= 1]?a30)  ; if this is from rg-group, don't strip prefix
exten => s,n,NoOp(Returning there are no members left in the hunt group to ring)

; dialparties.agi has setup the dialstring for each hunt member in a variable labeled HuntMember0, HuntMember1 etc for each iteration
; and The total number in HuntMembers. So for each iteration, we will update the CALLTRACE Data.
;
exten => s,n+2(a30),Set(HuntMember=HuntMember${HuntLoop})
exten => s,n,GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "hunt" ]]?a32:a35)
exten => s,n(a32),Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${HuntLoop} + 1])})
exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})
exten => s,n,Goto(s,a42)

;Set Call Trace for each hunt member we are going to call "Memory groups have multiple members to set CALL TRACE For hence the loop
;
exten => s,n(a35),GotoIf($[$["${CALLTRACE_HUNT}" != "" ] & $["${RingGroupMethod}" = "memoryhunt" ]]?a36:a50)  
exten => s,n(a36),Set(CTLoop=0)
exten => s,n(a37),GotoIf($[${CTLoop} > ${HuntLoop}]?a42)  ; if this is from rg-group, don't strip prefix
exten => s,n,Set(CT_EXTEN=${CUT(FILTERED_DIAL,,$[${CTLoop} + 1])})
exten => s,n,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})
exten => s,n,Set(CTLoop=$[1 + ${CTLoop}])
exten => s,n,Goto(s,a37)
        
exten => s,n(a42),Dial(${${HuntMember}}${ds})
exten => s,n,Set(HuntLoop=$[1 + ${HuntLoop}])
exten => s,n,GotoIf($[$[$["foo${RingGroupMethod}" != "foofirstavailable"] & $["foo${RingGroupMethod}" != "foofirstnotonphone"]] | $["foo${DialStatus}" = "fooBUSY"]]?a46)
exten => s,n,Set(HuntMembers=0)
exten => s,n(a46),Set(HuntMembers=$[${HuntMembers} - 1])
exten => s,n,Goto(s,a22)

exten => s,n(a50),DBdel(CALLTRACE/${CT_EXTEN})
exten => s,n,Goto(s,a42)

; For call screening
exten => NOANSWER,1,Macro(vm,${SCREEN_EXTEN},BUSY,${IVR_RETVM})
exten => NOANSWER,n,GotoIf($["${IVR_RETVM}" != "RETURN" | "${IVR_CONTEXT}" = ""]?bye)
exten => NOANSWER,n,Return
exten => NOANSWER,n(bye),Macro(hangupcall)
exten => TORTURE,1,Goto(app-blackhole,musiconhold,1)
exten => TORTURE,n,Macro(hangupcall)
exten => DONTCALL,1,Answer
exten => DONTCALL,n,Wait(1)
exten => DONTCALL,n,Zapateller()
exten => DONTCALL,n,Playback(ss-noservice)
exten => DONTCALL,n,Macro(hangupcall)

; make sure hungup calls go here so that proper cleanup occurs from call confirmed calls and the like
;
exten => h,1,Macro(hangupcall)

; Ring an extension, if the extension is busy or there is no answer send it
; to voicemail
; ARGS: $VMBOX, $EXT
[macro-exten-vm]
exten => s,1,Macro(user-callerid)

exten => s,n,Set(RingGroupMethod=none)
exten => s,n,Set(VMBOX=${ARG1})
exten => s,n,Set(EXTTOCALL=${ARG2})
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})})
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})})
exten => s,n,Set(RT=${IF($[$["${VMBOX}"!="novm"] | $["foo${CFUEXT}"!="foo"]]?${RINGTIMER}:"")})
exten => s,n,Macro(record-enable,${EXTTOCALL},IN)
exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL})
exten => s,n,GotoIf($[ $["${VMBOX}" != "novm"] & $["${SCREEN}" != ""] & $["${DIALSTATUS}" = "NOANSWER"] ]?exit,return)
exten => s,n,Set(SV_DIALSTATUS=${DIALSTATUS})
exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="NOANSWER"] & $["${CFUEXT}"!=""] & $["${SCREEN}" = ""]]?docfu,1) ; check for CFU in use on no answer
exten => s,n,GosubIf($[$["${SV_DIALSTATUS}"="BUSY"] & $["${CFBEXT}"!=""]]?docfb,1) ; check for CFB in use on busy
exten => s,n,Set(DIALSTATUS=${SV_DIALSTATUS})
exten => s,n,NoOp(Voicemail is '${VMBOX}')
exten => s,n,GotoIf($["${VMBOX}" = "novm"]?s-${DIALSTATUS},1) ; no voicemail in use for this extension
exten => s,n,NoOp(Sending to Voicemail box ${EXTTOCALL})
exten => s,n,Macro(vm,${VMBOX},${DIALSTATUS},${IVR_RETVM})

; Try the Call Forward on No Answer / Unavailable number
exten => docfu,1,Set(RTCFU=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")})
exten => docfu,n,Dial(Local/${CFUEXT}@from-internal/n,${RTCFU},${DIAL_OPTIONS})
exten => docfu,n,Return

; Try the Call Forward on Busy number
exten => docfb,1,Set(RTCFB=${IF($["${VMBOX}"!="novm"]?${RINGTIMER}:"")})
exten => docfb,n,Dial(Local/${CFBEXT}@from-internal/n,${RTCFB},${DIAL_OPTIONS})
exten => docfb,n,Return

; Extensions with no Voicemail box reporting BUSY come here
exten => s-BUSY,1,NoOp(Extension is reporting BUSY and not passing to Voicemail)
exten => s-BUSY,n,GotoIf($["${IVR_RETVM}" = "RETURN" & "${IVR_CONTEXT}" != ""]?exit,1)
exten => s-BUSY,n,Playtones(busy)
exten => s-BUSY,n,Busy(20)

; Anything but BUSY comes here
exten => _s-.,1,Noop(IVR_RETVM: ${IVR_RETVM} IVR_CONTEXT: ${IVR_CONTEXT})
exten => _s-.,n,GotoIf($["${IVR_RETVM}" = "RETURN" & "${IVR_CONTEXT}" != ""]?exit,1)
exten => _s-.,n,Playtones(congestion)
exten => _s-.,n,Congestion(10)

; Short burst of tones then return
exten => exit,1,Playback(beep&line-busy-transfer-menu&silence/1)
exten => exit,n(return),MacroExit()

;------------------------------------------------------------------------
; [macro-vm]
;------------------------------------------------------------------------
; CONTEXT:      macro-vm
; PURPOSE:      call voicemail system and extend with personal ivr
;
; Under normal use, this macro will call the voicemail system with the extension and
; desired greeting mode of busy, unavailable or as specified with direct voicemail
; calls (usually unavailable) when entered from destinations.
;
; The voicemail system's two greetings have been 'hijacked' as follows to extend the
; system by giving the option of a private 'ivr' for each voicemail user. The following
; applies to both the busy and unavailable modes of voicemail and can be applied to one
; or both, and differently.
;
; Global Defaults:
;
; The following are default values, used in both busy and unavail modes if no specific
; values are specified.
;
; VMX_REPEAT
;					The number of times to repeat the users message if no option is pressed.
; VMX_TIMEOUT
;					The timeout to wait after playing message before repeating or giving up.
; VMX_LOOPS
;					The number of times it should replay the message and check for an option when
;					an invalid option is pressed.
;
; VMX_OPTS_DOVM
;					Default voicemail option to use if vm is chosen as an option. No options will
;					cause Allison's generic message, 's' will go straight to beep.
; VMX_OPTS_TIMEOUT
;					Default voicemail option to use if it times out with no options. No options will
;					cause Allison's generic message, 's' will go straight to beep.
;					IF THE USER PRESSES # - it will look like a timeout as well since no option will
;					be presented. If the user wishes to enable a mode where a caller can press #
;					during their message and it goes straight to voicemail with only a 'beep' then
;					this should be set to 's'.
; VMX_OPTS_LOOPS
;					Default voicemail option to use if to many wrong options occur. No options will
;					cause Allison's generic message, 's' will go straight to beep.
;
; VMX_CONTEXT
;					Default context for user destinations if not supplied in the user's settings
; VMX_PRI
;					Default priority for user destinations if not supplied in the user's settings
;
; VMX_TIMEDEST_CONTEXT
;					Default context for timeout destination if not supplied in the user's settings
; VMX_TIMEDEST_EXT
;					Default extension for timeout destination if not supplied in the user's settings
; VMX_TIMEDEST_PRI
;					Default priority for timeout destination if not supplied in the user's settings
;
; VMX_LOOPDEST_CONTEXT
;					Default context for loops  destination if not supplied in the user's settings
; VMX_LOOPDEST_EXT
;					Default extension for loops  destination if not supplied in the user's settings
; VMX_LOOPDEST_PRI
;					Default priority for loops  destination if not supplied in the user's settings
;
;
; The AMPUSER database variable has been extended with a 'vmx' tree (vm-extension). A
; duplicate set is included for both unavail and busy. You could choose for to have an
; ivr when unavail is taken, but not with busy - or a different once with busy.
; The full list is below, each specific entry is futher described:
;
; state:		Whether teh current mode is enabled or disabled. Anything but 'enabled' is
;						treated as disabled.
; repeat:		This is the number of times that the users message should be played after the
;						timeout if the user has not entered anything. It is just a variable to the
;						Read() function which will do the repeating.
; timeout:	This is how long to wait after the message has been read for a response from
;						the user. A caller can enter a digit any time during the playback.
; loops:		This is the number of loops that the system will allow a caller to retry if
;						they enter a bad menu choice, before going to the loop failover destination
; vmxopts:	This is the vm options to send to the voicemail command used when a specific
;						voicemail destination is chosen (inidcated by 'dovm' in the ext field). This is
;						typically either set to 's' or left blank. When set to 's' there will be no
;						message played when entering the voicemail, just a beep. When blank, you will
;						have Allison's generic message played. It is not typical to play the greetings
;						since they have been 'hijacked' for these IVR's and from a caller's perspecitive
;						this system appears interconnected with the voicemail so instructions can be
;						left there.
; timedest: The three variables: ext, context and pri are the goto destination if the caller
;						enters no options and it timesout. None have to be set and a system default
;						will be used. If just ext is set, then defaults will be used for context and
;						pri, etc.
; loopdest:	This is identical to timedest but used if the caller exceeds the maximum invalid
;						menu choices.
; [0-9*]:		The user can specify up to 11 ivr options, all as single digits from 0-9 or *. The
;						# key can not be used since it is used as a terminator key for the Read command
;						and will never be returned. A minimum of the ext must be specified for each valid
;						option and as above, the context and priority can also be specified if the default
;						is not to be used.
;						Option '0' takes on a special meaning. Since a user is able to break out of the
;						voicemail command once entering it with a 0, if specified, the 0 destination will
;						be used.
;						Option '*' can also be used to breakout. It is undecided at this point whether
;						providing that option will be used as well. (probably should).
;
;
; /AMPUSER/<ext>/vmx/[busy|unavail]/state:								enabled|disabled
; /AMPUSER/<ext>/vmx/[busy|unavail]/repeat:								n (times to repeat message)
; /AMPUSER/<ext>/vmx/[busy|unavail]/timeout:							n (timeout to wait for digit)
; /AMPUSER/<ext>/vmx/[busy|unavail]/loops:								n (loop returies for invalid entries)
; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/dovm:					vmoptions (if ext is dovm)
; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/timeout:			vmoptions (if timeout)
; /AMPUSER/<ext>/vmx/[busy|unavail]/vmxopts/loops:				vmoptions (if loops)
; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/ext:					extension (if timeout)
; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/context:			context (if timeout)
; /AMPUSER/<ext>/vmx/[busy|unavail]/timedest/pri:					priority (if timeout)
; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/ext:					extension (if too many failures)
; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/context:			context (if too many failures)
; /AMPUSER/<ext>/vmx/[busy|unavail]/loopdest/pri:					priority (if too many failures)
; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/ext:						extension (dovm for vm access)
; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/context:				context 
; /AMPUSER/<ext>/vmx/[busy|unavail]/[0-9*]/pri:						priority 
;------------------------------------------------------------------------
[macro-vm]
; ARG1 - extension
; ARG2 - DIRECTDIAL/BUSY
; ARG3 - RETURN makes macro return, otherwise hangup
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}/temp)
exten => vmx,n,GotoIf($["${SYSTEMSTATUS}" = "SUCCESS"]?tmpgreet)
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)
exten => vmx,n(tmpgreet),Noop(Temporary Greeting Detected, 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},s${VM_OPTS}${VMGAIN})
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/s@from-pstn)
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,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => adef,n,Hangup

exten => exit-FAILED,1,Playback(im-sorry&an-error-has-occured)
exten => exit-FAILED,n,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => exit-FAILED,n,Hangup()

exten => exit-SUCCESS,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => exit-SUCCESS,n,Playback(goodbye)
exten => exit-SUCCESS,n,Hangup()

exten => exit-USEREXIT,1,GotoIf($["${ARG3}" = "RETURN"]?exit-RETURN,1)
exten => exit-USEREXIT,n,Playback(goodbye)
exten => exit-USEREXIT,n,Hangup()

exten => exit-RETURN,1,Noop(Returning From Voicemail because macro)

exten => t,1,Hangup()
;------------------------------------------------------------------------

;------------------------------------------------------------------------
; [macro-simple-dial]
;------------------------------------------------------------------------
; This macro was derived from macro-exten-vm, which is what is normally used to
; ring an extension. It has been simplified and designed to never go to voicemail
; and always return regardless of the DIALSTATUS for any incomplete call.
;
; It's current primary purpose is to allow findmefollow ring an extension prior
; to trying the follow-me ringgroup that is provided.
;
; Ring an extension, if the extension is busy or there is no answer, return
; ARGS: $EXTENSION, $RINGTIME
;------------------------------------------------------------------------
[macro-simple-dial]
exten => s,1,Set(EXTTOCALL=${ARG1})
exten => s,n,Set(RT=${ARG2})
exten => s,n,Set(CFUEXT=${DB(CFU/${EXTTOCALL})})
exten => s,n,Set(CFBEXT=${DB(CFB/${EXTTOCALL})})

exten => s,n,Macro(dial,${RT},${DIAL_OPTIONS},${EXTTOCALL})

exten => s,n,Set(PR_DIALSTATUS=${DIALSTATUS})

; if we return, thus no answer, and they have a CFU setting, then  we try that next
;
exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="NOANSWER"] & $["foo${CFUEXT}"!="foo"]]?docfu,1) ; check for CFU in use on no answer
exten => s,n,GosubIf($[$["${PR_DIALSTATUS}"="BUSY"] & $["foo${CFBEXT}"!="foo"]]?docfb,1) ; check for CFB in use on busy
exten => s,n,Set(DIALSTATUS=${PR_DIALSTATUS})

; Nothing yet, then go to the end (which will just return, but in case we decide to do something with certain
; return situations, this is left in.
;
exten => s,n,Goto(s-${DIALSTATUS},1)

; Try the Call Forward on No Answer / Unavailable number.
; We want to try CFU if set, but we want the same ring timer as was set to our call (or do we want the
; system ringtimer? - probably not). Then if no answer there (assuming it doesn't drop into their vm or
; something we return, which will have the net effect of returning to the followme setup.)
;
; want to avoid going to other follow-me settings here. So check if the CFUEXT is a user and if it is
; then direct it straight to ext-local (to avoid getting intercepted by findmefollow) otherwise send it
; to from-internal since it may be an outside line.
;
exten => docfu,1,GotoIf( $[ "foo${DB(AMPUSER/${CFUEXT}/device)}" = "foo" ]?chlocal)
exten => docfu,n,Dial(Local/${CFUEXT}@ext-local,${RT},${DIAL_OPTIONS})
exten => docfu,n,Return
exten => docfu,n(chlocal),Dial(Local/${CFUEXT}@from-internal/n,${RT},${DIAL_OPTIONS})
exten => docfu,n,Return

; Try the Call Forward on Busy number
exten => docfb,1,GotoIf( $[ "foo${DB(AMPUSER/${CFBEXT}/device)}" = "foo" ]?chlocal)
exten => docfb,n,Dial(Local/${CFBEXT}@ext-local,${RT},${DIAL_OPTIONS})
exten => docfb,n,Return
exten => docfb,n(chlocal),Dial(Local/${CFBEXT}@from-internal/n,${RT},${DIAL_OPTIONS})
exten => docfb,n,Return

; In all cases of no connection, come here and simply return, since the calling dialplan will
; decide what to do next
exten => _s-.,1,NoOp(Extension is reporting ${EXTEN})
;------------------------------------------------------------------------


; get the voicemail context for the user in ARG1
[macro-get-vmcontext]
exten => s,1,Set(VMCONTEXT=${DB(AMPUSER/${ARG1}/voicemail)})
exten => s,2,GotoIf($["foo${VMCONTEXT}" = "foo"]?200:300)
exten => s,200,Set(VMCONTEXT=default)
exten => s,300,NoOp()

; For some reason, if I don't run setCIDname, CALLERID(name) will be blank in my AGI
; ARGS: none
[macro-fixcid]
exten => s,1,Set(CALLERID(name)=${CALLERID(name)})

; Ring groups of phones
; ARGS: comma separated extension list
; 1 - Ring Group Strategy
; 2 - ringtimer
; 3 - prefix
; 4 - extension list
[macro-rg-group]
exten => s,1,Macro(user-callerid,SKIPTTL) ; already called from ringgroup
exten => s,2,GotoIf($["${CALLERID(name):0:${LEN(${RGPREFIX})}}" != "${RGPREFIX}"]?4:3)  ; check for old prefix
exten => s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off old prefix
exten => s,4,Set(RGPREFIX=${ARG3})  ; set new prefix
exten => s,5,Set(CALLERID(name)=${RGPREFIX}${CALLERID(name)})  ; add prefix to callerid name
exten => s,6,Set(RecordMethod=Group)  ; set new prefix
exten => s,7,Macro(record-enable,${MACRO_EXTEN},${RecordMethod})
exten => s,8,Set(RingGroupMethod=${ARG1})     ;
exten => s,9,Macro(dial,${ARG2},${DIAL_OPTIONS},${ARG4})
exten => s,10,Set(RingGroupMethod='')     ;


;
; Outgoing channel(s) are busy ... inform the client
; but use noanswer features like ringgroups don't break by being answered
; just to play the message.
;
[macro-outisbusy]
exten => s,1,Playback(all-circuits-busy-now,noanswer)
exten => s,n,Playback(pls-try-call-later,noanswer)
exten => s,n,Macro(hangupcall)

; What to do on hangup.                                         
[macro-hangupcall]
exten => s,1,ResetCDR(w)
exten => s,n,NoCDR()
 
; Cleanup any remaining RG flag
;
exten => s,n,GotoIf($[ "x${USE_CONFIRMATION}" = "x" | "x${RINGGROUP_INDEX}" = "x" | "${CHANNEL}" != "${UNIQCHAN}"]?skiprg)
exten => s,n,Noop(Cleaning Up Confirmation Flag: RG/${RINGGROUP_INDEX}/${CHANNEL})
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL})

; Cleanup any remaining BLKVM flag
;
exten => s,n(skiprg),GotoIf($[ "x${BLKVM_BASE}" = "x" | "BLKVM/${BLKVM_BASE}/${CHANNEL}" != "${BLKVM_OVERRIDE}" ]?skipblkvm)
exten => s,n,Noop(Cleaning Up Block VM Flag: ${BLKVM_OVERRIDE})
exten => s,n,DBDel(${BLKVM_OVERRIDE})

; Cleanup any remaining FollowMe DND flags
;
exten => s,n(skipblkvm),GotoIf($[ "x${FMGRP}" = "x" | "x${FMUNIQUE}" = "x" | "${CHANNEL}" != "${FMUNIQUE}" ]?theend)
exten => s,n,DBDel(FM/DND/${FMGRP}/${CHANNEL})

exten => s,n(theend),Hangup

[macro-faxreceive]
exten => s,1,Set(FAXFILE=${ASTSPOOLDIR}/fax/${UNIQUEID}.tif)
exten => s,2,Set(EMAILADDR=${FAX_RX_EMAIL})
exten => s,3,rxfax(${FAXFILE})
exten => s,103,Set(EMAILADDR=${FAX_RX_EMAIL})
exten => s,104,Goto(3)

; dialout and strip the prefix
[macro-dialout]
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,2,GotoIf($["${ECID${CALLERID(number)}}" = ""]?5) 	;check for CID override for exten
exten => s,3,Set(CALLERID(all)=${ECID${CALLERID(number)}})
exten => s,4,Goto(7)
exten => s,5,GotoIf($["${OUTCID_${ARG1}}" = ""]?7) 		;check for CID override for trunk
exten => s,6,Set(CALLERID(all)=${OUTCID_${ARG1}})
exten => s,7,Set(length=${LEN(${DIAL_OUT_${ARG1}})})
exten => s,8,Dial(${OUT_${ARG1}}/${ARG2:${length}})
exten => s,9,Playtones(congestion)
exten => s,10,Congestion(5)
exten => s,109,Macro(outisbusy)


; dialout using default OUT trunk - no prefix
[macro-dialout-default]
exten => s,1,Macro(user-callerid,SKIPTTL)
exten => s,2,Macro(record-enable,${CALLERID(number)},OUT)
exten => s,3,Macro(outbound-callerid,${ARG1})
exten => s,4,Dial(${OUT}/${ARG1})
exten => s,5,Playtones(congestion)
exten => s,6,Congestion(5)
exten => s,105,Macro(outisbusy)

[macro-dialout-trunk-predial-hook]
; this macro intentially left blank so it may be safely overwritten for any custom
; requirements that an installation may have.
;
; MACRO RETURN CODE: ${PREDIAL_HOOK_RET}
;                    if set to "BYPASS" then this trunk will be skipped
;
exten => s,1,MacroExit()

; This macro is for dev purposes and just dumps channel/app variables.  Useful when designing new contexts. 
[macro-dumpvars]
exten => s,1,Noop(ACCOUNTCODE=${ACCOUNTCODE})
exten => s,2,Noop(ANSWEREDTIME=${ANSWEREDTIME})
exten => s,3,Noop(BLINDTRANSFER=${BLINDTRANSFER})
exten => s,4,Noop(CALLERID=${CALLERID(all)})
exten => s,5,Noop(CALLERID(name)=${CALLERID(name)})
exten => s,6,Noop(CALLERID(number)=${CALLERID(number)})
exten => s,7,Noop(CALLINGPRES=${CALLINGPRES})
exten => s,8,Noop(CHANNEL=${CHANNEL})
exten => s,9,Noop(CONTEXT=${CONTEXT})
exten => s,10,Noop(DATETIME=${DATETIME})
exten => s,11,Noop(DIALEDPEERNAME=${DIALEDPEERNAME})
exten => s,12,Noop(DIALEDPEERNUMBER=${DIALEDPEERNUMBER})
exten => s,13,Noop(DIALEDTIME=${DIALEDTIME})
exten => s,14,Noop(DIALSTATUS=${DIALSTATUS})
exten => s,15,Noop(DNID=${DNID})
exten => s,16,Noop(EPOCH=${EPOCH})
exten => s,17,Noop(EXTEN=${EXTEN})
exten => s,18,Noop(HANGUPCAUSE=${HANGUPCAUSE})
exten => s,19,Noop(INVALID_EXTEN=${INVALID_EXTEN})
exten => s,20,Noop(LANGUAGE=${LANGUAGE})
exten => s,21,Noop(MEETMESECS=${MEETMESECS})
exten => s,22,Noop(PRIORITY=${PRIORITY})
exten => s,23,Noop(RDNIS=${RDNIS})
exten => s,24,Noop(SIPDOMAIN=${SIPDOMAIN})
exten => s,25,Noop(SIP_CODEC=${SIP_CODEC})
exten => s,26,Noop(SIPCALLID=${SIPCALLID})
exten => s,27,Noop(SIPUSERAGENT=${SIPUSERAGENT})
exten => s,29,Noop(TXTCIDNAME=${TXTCIDNAME})
exten => s,30,Noop(UNIQUEID=${UNIQUEID})
exten => s,31,Noop(TOUCH_MONITOR=${TOUCH_MONITOR})
exten => s,32,Noop(MACRO_CONTEXT=${MACRO_CONTEXT})
exten => s,33,Noop(MACRO_EXTEN=${MACRO_EXTEN})
exten => s,34,Noop(MACRO_PRIORITY=${MACRO_PRIORITY})

[macro-user-logon]
; check device type
;
exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})
exten => s,n,Answer()
exten => s,n,Wait(1)
exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1)
; get user's extension
;
exten => s,n,Set(AMPUSER=${ARG1})
exten => s,n,GotoIf($["${AMPUSER}" != ""]?gotpass)
exten => s,n(playagain),Read(AMPUSER,please-enter-your-extension-then-press-pound,,,4)
; get user's password and authenticate
;
exten => s,n,GotoIf($["${AMPUSER}" = ""]?s-MAXATTEMPTS,1)
exten => s,n(gotpass),GotoIf($["${DB_EXISTS(AMPUSER/${AMPUSER}/password)}" = "0"]?s-NOUSER,1)
exten => s,n,Set(AMPUSERPASS=${DB_RESULT})
exten => s,n,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-NOPASSWORD,1)
; do not continue if the user has already logged onto this device
;
exten => s,n,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)})
exten => s,n,GotoIf($["${DEVICEUSER}" = "${AMPUSER}"]?s-ALREADYLOGGEDON,1)
exten => s,n,Authenticate(${AMPUSERPASS})
exten => s,n,DeadAGI(user_login_out.agi,login,${CALLERID(number)},${AMPUSER})
exten => s,n,Playback(vm-goodbye)

exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged into)
exten => s-FIXED,n,Playback(ha/phone)
exten => s-FIXED,n,SayDigits(${CALLERID(number)})
exten => s-FIXED,n,Playback(is-curntly-unavail&vm-goodbye)
exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into 

exten => s-ALREADYLOGGEDON,1,NoOp(This device has already been logged into by this user)
exten => s-ALREADYLOGGEDON,n,Playback(vm-goodbye)
exten => s-ALREADYLOGGEDON,n,Hangup ;TODO should play msg indicated device is already logged into 

exten => s-NOPASSWORD,1,NoOp(This extension does not exist or no password is set)
exten => s-NOPASSWORD,n,Playback(pbx-invalid)
exten => s-NOPASSWORD,n,Goto(s,playagain)

exten => s-MAXATTEMPTS,1,NoOp(Too many login attempts)
exten => s-MAXATTEMPTS,n,Playback(vm-goodbye)
exten => s-MAXATTEMPTS,n,Hangup

exten => s-NOUSER,1,NoOp(Invalid extension ${AMPUSER} entered)
exten => s-NOUSER,n,Playback(pbx-invalid)
exten => s-NOUSER,n,Goto(s,playagain)

[macro-user-logoff]
; check device type
;
exten => s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})
exten => s,n,GotoIf($["${DEVICETYPE}" = "fixed"]?s-FIXED,1)
exten => s,n,DeadAGI(user_login_out.agi,logout,${CALLERID(number)})
exten => s,n(done),Playback(vm-goodbye)

exten => s-FIXED,1,NoOp(Device is FIXED and cannot be logged out of)
exten => s-FIXED,n,Playback(an-error-has-occured&vm-goodbye)
exten => s-FIXED,n,Hangup ;TODO should play msg indicated device cannot be logged into 



; Privacy Manager Macro makes sure that any calls that don't pass the privacy manager are presented
; with congestion since there have been observed cases of the call continuing if not stopped with a 
; congestion, and this provides a slightly more friendly 'sorry' message in case the user is
; legitamately trying to be cooperative. 
;
; Note: the following options are configurable in privacy.conf:
;
;	maxretries = 3 ; default value, number of retries before failing
;	minlength = 10 ; default value, number of digits to be accepted as valid CID
;
[macro-privacy-mgr]
exten => s,1,Set(KEEPCID=${CALLERID(num)})
exten => s,n,GotoIf($["foo${CALLERID(num):0:1}"="foo+"]?CIDTEST2:CIDTEST1)
exten => s,n(CIDTEST1),Set(TESTCID=${MATH(1+${CALLERID(num)})})
exten => s,n,Goto(TESTRESULT)
exten => s,n(CIDTEST2),Set(TESTCID=${MATH(1+${CALLERID(num):1})})
exten => s,n(TESTRESULT),GotoIf($["foo${TESTCID}"="foo"]?CLEARCID:PRIVMGR)
exten => s,n(CLEARCID),Set(CALLERID(num)=)
exten => s,n(PRIVMGR),PrivacyManager()
exten => s,n,GotoIf($["${PRIVACYMGRSTATUS}"="FAILED"]?fail)
exten => s,n,SetCallerPres(allowed_passed_screen); stop gap until app_privacy.c clears unavailble bit
exten => s,PRIVMGR+101(fail),Noop(STATUS: ${PRIVACYMGRSTATUS} CID: ${CALLERID(num)} ${CALLERID(name)} CALLPRES: ${CALLLINGPRES})
exten => s,n,Playback(sorry-youre-having-problems)
exten => s,n,Playback(goodbye)
exten => s,n,Playtones(congestion)
exten => s,n,Congestion(5)



; Text-To-Speech related macros
; These all follow common actions.  First try to playback a file "tts/custom-md5" 
; where "md5" is the md5() of whatever is going to be played. If that doesn't exist,
; try to playback using macro-tts-sayXXXXX (where XXXXX is text/digits/etc, same as
; the macro below). If that macro exits with MACRO_OFFSET=100, then it's done, 
; therwise, fallback to the default asterisk method. 
;
; say text is purely for text-to-speech, there is no fallback
[macro-saytext]
exten => s,1,Noop(Trying custom SayText playback for "${ARG1}")
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done)
; call tts-saytext. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-saytext,${ARG1},${ARG2},${ARG3})
exten => s,n,Noop(No text-to-speech handler for SayText, cannot say "${ARG1}")
exten => s,n,Goto(done)
exten => s,tts+101,Noop(tts handled saytext)

; say name is for saying names typically, but fallsback to using SayAlpha
; (saying the word letter-by-letter)
[macro-sayname]
exten => s,1,Noop(Trying custom SayName playback for "${ARG1}")
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done)
; call tts-sayalpha. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-sayalpha,${ARG1},${ARG2},${ARG3})
exten => s,n,SayAlpha(${ARG1})
exten => s,n,Goto(done)
exten => s,tts+101,Noop(tts handled sayname)

; Say number is for saying numbers (eg "one thousand forty six") 
[macro-saynumber]
exten => s,1,Noop(Trying custom SayNumber playback for "${ARG1}")
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done)
; call tts-saynumber. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-saynumber,${ARG1},${ARG2},${ARG3})
exten => s,n,SayNumber(${ARG1})
exten => s,n,Goto(done)
exten => s,tts+101,Noop(tts handled saynumber)

; Say digits is for saying digits one-by-one (eg, "one zero four six")
[macro-saydigits]
exten => s,1,Noop(Trying custom SayDigits playback for "${ARG1}")
exten => s,n,Playback(tts/custom-${MD5(${ARG1})})
exten => s,n,GotoIf($["${PLAYBACKSTATUS}"="SUCCESS"]?done)
; call tts-saydigits. This should set MACRO_OFFSET=101 if it was successful
exten => s,n(tts),Macro(tts-saydigits,${ARG1},${ARG2},${ARG3})
exten => s,n,SayDigits(${ARG1})
exten => s,n,Goto(done)


;
; ############################################################################
; Inbound Contexts [from]
; ############################################################################

[from-sip-external]
;give external sip users congestion and hangup
; Yes. This is _really_ meant to be _. - I know asterisk whinges about it, but 
; I do know what I'm doing. This is correct.
exten => _.,1,NoOp(Received incoming SIP connection from unknown peer to ${EXTEN})
exten => _.,n,Set(DID=${IF($["${EXTEN:1:2}"=""]?s:${EXTEN})})
exten => _.,n,Goto(s,1)
exten => s,1,GotoIf($["${ALLOW_SIP_ANON}"="yes"]?from-trunk,${DID},1)
exten => s,n,Set(TIMEOUT(absolute)=15)
exten => s,n,Answer
exten => s,n,Wait(2)
exten => s,n,Playback(ss-noservice)
exten => s,n,Playtones(congestion)
exten => s,n,Congestion(5)
exten => h,1,NoOp(Hangup)
exten => i,1,NoOp(Invalid)
exten => t,1,NoOp(Timeout)

[from-internal-xfer]
; applications are now mostly all found in from-internal-additional in _custom.conf
include => parkedcalls
include => from-internal-custom
;allow phones to dial other extensions
include => ext-fax
;allow phones to access generated contexts
;
; MODIFIED (PL)
;
; Currently the include for findmefollow is being auto-generated before ext-local which is the desired behavior.
; However, I haven't been able to do anything that I know of to force this. We need to determine if it should
; be hardcoded into here to make sure it doesn't change with some configuration. For now I will leave it out
; until we can discuss this.
;
include => ext-local-confirm
include => findmefollow-ringallv2
include => from-internal-additional
; This causes grief with '#' transfers, commenting out for the moment.
; include => bad-number
exten => s,1,Macro(hangupcall)
exten => h,1,Macro(hangupcall)

[from-internal]
include => from-internal-xfer
include => bad-number

;------------------------------------------------------------------------
; [macro-setmusic]
;------------------------------------------------------------------------
; CONTEXT:      macro-setmusic
; PURPOSE:      to turn off moh on routes where it is not desired
;
;------------------------------------------------------------------------
[macro-setmusic]
exten => s,1,NoOp(Setting Outbound Route MoH To: ${ARG1})
exten => s,2,SetMusicOnHold(${ARG1})
;------------------------------------------------------------------------

; ##########################################
; ## Ring Groups with Confirmation macros ##
; ##########################################
; Used by followme and ringgroups

;------------------------------------------------------------------------
; [macro-dial-confirm]
;------------------------------------------------------------------------
; This has now been incorporated into dialparties. It still only works with ringall
; and ringall-prim strategies. Have not investigated why it doesn't work with
; hunt and memory hunt.
;
;------------------------------------------------------------------------
[macro-dial-confirm]
; This was written to make it easy to use macro-dial-confirm instead of macro-dial in generated dialplans.
; This takes the same paramaters, with an additional paramater of the ring group Number
; ARG1 is the timeout
; ARG2 is the DIAL_OPTIONS
; ARG3 is a list of xtns to call - 203-222-240-123123123#-211
; ARG4 is the ring group number

; This sets a unique value to indicate that the channel is ringing. This is used for warning slow
; users that the call has already been picked up.
;
exten => s,1,Set(DB(RG/${ARG4}/${CHANNEL})=RINGING)

; We need to keep that channel variable, because it'll change when we do this dial, so set it to
; fallthrough to every sibling.
;
exten => s,n,Set(__UNIQCHAN=${CHANNEL})

; The calling ringgroup should have set RingGroupMethod appropriately. We need to set two
; additional parameters:
;
; USE_CONFIRMATION, RINGGROUP_INDEX
;
; Thse are passed to inform dialparties to place external calls through the [grps] context
;
exten => s,n,Set(USE_CONFIRMATION=TRUE)
exten => s,n,Set(RINGGROUP_INDEX=${ARG4})
exten => s,n,Set(ARG4=) ; otherwise it gets passed to dialparties.agi which processes it (prob bug) 

exten => s,n,Macro(dial,${ARG1},${ARG2},${ARG3})

; delete the variable, if we are here, we are done trying to dial and it may have been left around
;
exten => s,n,DBDel(RG/${RINGGROUP_INDEX}/${CHANNEL})
exten => s,n,Set(USE_CONFIRMATION=)
exten => s,n,Set(RINGGROUP_INDEX=)
;------------------------------------------------------------------------


;------------------------------------------------------------------------
; [ext-local-confirm]
;------------------------------------------------------------------------
; If call confirm is being used in a ringgroup, then calls that do not require confirmation are sent
; to this extension instead of straight to the device.
;
; The sole purpose of sending them here is to make sure we run Macro(auto-confirm) if this
; extension answers the line. This takes care of clearing the database key that is used to inform
; other potential late comers that the extension has been answered by someone else.
;
; ALERT_INFO is deprecated in Asterisk 1.4 but still used throughout the FreePBX dialplan and
; usually set by dialparties.agi. This allows ineritance. Since no dialparties.agi here, set the
; header if it is set.
;
;------------------------------------------------------------------------
[ext-local-confirm]
exten => _LC-.,1,Noop(IN ext-local-confirm with - RT: ${RT}, RG_IDX: ${RG_IDX})
exten => _LC-.,n,GotoIf($["x${ALERT_INFO}"="x"]?godial)
exten => _LC-.,n,SIPAddHeader(Alert-Info: ${ALERT_INFO})
exten => _LC-.,n(godial),dial(${DB(DEVICE/${EXTEN:3}/dial)},${RT},M(auto-confirm^${RG_IDX})${DIAL_OPTIONS})

;------------------------------------------------------------------------
; [findmefollow-ringallv2]
;------------------------------------------------------------------------
; This context, to be included in from-internal, implements the PreRing part of findmefollow
; as well as the GroupRing part. It also communicates between the two so that if DND is set
; on the primary extension, and mastermode is enabled, then the other extensions will not ring
;
;------------------------------------------------------------------------
[findmefollow-ringallv2]
exten => _FMPR-.,1,Noop(In FMPR ${FMGRP} with ${EXTEN:5})
exten => _FMPR-.,n,Set(RingGroupMethod=)
exten => _FMPR-.,n,Set(USE_CONFIRMATION=)
exten => _FMPR-.,n,Set(RINGGROUP_INDEX=)
exten => _FMPR-.,n,Macro(simple-dial,${EXTEN:5},${FMREALPRERING})
exten => _FMPR-.,n,GotoIf($["${DIALSTATUS}" != "BUSY"]?nodnd)
exten => _FMPR-.,n,Set(DB(FM/DND/${FMGRP}/${FMUNIQUE})=DND)
exten => _FMPR-.,n(nodnd),Noop(Ending FMPR ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS})
exten => _FMPR-.,n,Hangup()

exten => _FMGL-.,1,Noop(In FMGL ${FMGRP} with ${EXTEN:5})
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd)
exten => _FMGL-.,n,Wait(1)
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd)
exten => _FMGL-.,n,Wait(1)
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd)
exten => _FMGL-.,n,Wait(${FMPRERING})
exten => _FMGL-.,n,GotoIf($["${DB(FM/DND/${FMGRP}/${FMUNIQUE})}" = "DND"]?dodnd)
exten => _FMGL-.,n,DBDel(FM/DND/${FMGRP}/${FMUNIQUE})
exten => _FMGL-.,n(dodial),Macro(dial,${FMGRPTIME},${DIAL_OPTIONS},${EXTEN:5})
exten => _FMGL-.,n,Noop(Ending FMGL ${FMGRP} with ${EXTEN:5} and dialstatus ${DIALSTATUS})
exten => _FMGL-.,n,Hangup()
exten => _FMGL-.,n+10(dodnd),DBDel(FM/DND/${FMGRP}/${FMUNIQUE})
exten => _FMGL-.,n,GotoIf($["${FMPRIME}" = "FALSE"]?dodial)
exten => _FMGL-.,n,Noop(Got DND in FMGL ${FMGRP} with ${EXTEN:5} in ${RingGroupMethod} mode, aborting)
exten => _FMGL-.,n,Hangup()

;------------------------------------------------------------------------
; [block-cf]
;------------------------------------------------------------------------
; This context is set as a target with FORWARD_CONTEXT when Call Forwarding is set to be
; ignored in a ringgoup or other features that may take advantage of this. Server side
; CF is done in dialparties.agi but if a client device forwards a call, it will be caught
; and blocked here.
;------------------------------------------------------------------------
[block-cf]
exten => _X.,1,Noop(Blocking callforward to ${EXTEN} because CF is blocked)
exten => _X.,n,Hangup()

;------------------------------------------------------------------------

; ############################################################################
; Extension Contexts [ext]
; ############################################################################



[from-zaptel]
exten => _X.,1,Set(DID=${EXTEN})
exten => _X.,n,Goto(s,1)
exten => s,1,NoOp(Entering from-zaptel with DID == ${DID})
; Some trunks _require_ a RINGING be sent before an Answer.
exten => s,n,Ringing()
; If ($did == "") { $did = "s"; }
exten => s,n,Set(DID=${IF($["${DID}"= ""]?s:${DID})})
exten => s,n,NoOp(DID is now ${DID})
exten => s,n,GotoIf($["${CHANNEL:0:3}"="Zap"]?zapok:notzap)
exten => s,n(notzap),Goto(from-pstn,${DID},1)
; If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup.
exten => s,n,Macro(hangup)
exten => s,n(zapok),NoOp(Is a Zaptel Channel)
exten => s,n,Set(CHAN=${CHANNEL:4})
exten => s,n,Set(CHAN=${CUT(CHAN,-,1)})
exten => s,n,Macro(from-zaptel-${CHAN},${DID},1)
; If nothing there, then treat it as a DID
exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN})
exten => s,n,Goto(from-pstn,${DID},1)
exten => fax,1,Goto(ext-fax,in_fax,1)

[from-pstn]

exten => _X.,1,Set(DID=${EXTEN})
exten => _X.,n,Goto(s,1)
exten => s,1,NoOp(Entering from-zaptel with DID == ${DID})
; Some trunks _require_ a RINGING be sent before an Answer.
exten => s,n,Ringing()
; If ($did == "") { $did = "s"; }
exten => s,n,Set(DID=${IF($["${DID}"= ""]?s:${DID})})
exten => s,n,NoOp(DID is now ${DID})
exten => s,n,GotoIf($["${CHANNEL:0:3}"="Zap"]?zapok:notzap)
exten => s,n(notzap),Goto(from-pstn,${DID},1)
; If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup.
exten => s,n,Macro(hangup)
exten => s,n(zapok),NoOp(Is a Zaptel Channel)
exten => s,n,Set(CHAN=${CHANNEL:4})
exten => s,n,Set(CHAN=${CUT(CHAN,-,1)})
exten => s,n,Macro(from-zaptel-${CHAN},${DID},1)
; If nothing there, then treat it as a DID
exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN})
exten => s,n,Goto(from-pstn,${DID},1)
exten => fax,1,Goto(ext-fax,in_fax,1)


[default]

include => ext-local

exten => s,1,Playback(vm-goodbye)

exten => s,2,Macro(hangupcall)

 

Let me know if you need more information.

if you have analog lines (sounds like it) you need:

  1. from-zaptel for your context
  2. define DIDs for each zaptel channel in “Zap Channel DIDs” tab (e.g. the number people would call for that line, or make up a number)
  3. create a route for that DID

Alternatively, create a ‘catchall route’ (Any DID / Any CID) so that the calls go there.

What every you did during the upgrade was more than upgrading FreePBX - OR - you had some customizations where you had defined a default route, because FreePBX will not touch your zapata.conf during and upgrade (or even during an install).

Yeah, you’re right, it is a single analog line.

I have from-zaptel in the context in zapata.conf, and I did have a catchall route for an inbound route.

One thing I didn’t have was DID’s defined for each channel. I defined a DID for channel one, but still no go. Am I supposed to put the 10-digit number for the DID?

Here’s a sample of the logfile. It appears to be going to from-trunk, and it just rings and loops all this until I restart asterisk.

[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Goto (from-trunk,s,8)
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:8] NoOp("Zap/1-1", "Is a Zaptel Channel") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:9] Set("Zap/1-1", "CHAN=1-1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:10] Set("Zap/1-1", "CHAN=1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:11] Macro("Zap/1-1", "from-zaptel-1|6153720300|1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@macro-from-zaptel-1:1] NoOp("Zap/1-1", "Entering macro-from-zaptel-1 with DID = 6153720300 and setting to: 6153720300") in new stack
[Nov 2 13:30:55] DEBUG[18406] app_macro.c: Executed application: Noop
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@macro-from-zaptel-1:2] Set("Zap/1-1", "__FROM_DID=6153720300") in new stack
[Nov 2 13:30:55] DEBUG[18406] app_macro.c: Executed application: Set
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@macro-from-zaptel-1:3] Goto("Zap/1-1", "from-trunk|6153720300|1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Goto (from-trunk,6153720300,1)
[Nov 2 13:30:55] DEBUG[18406] app_macro.c: Executed application: Goto
[Nov 2 13:30:55] VERBOSE[18406] logger.c: == Channel 'Zap/1-1' jumping out of macro 'from-zaptel-1'
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [6153720300@from-trunk:1] Set("Zap/1-1", "DID=6153720300") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [6153720300@from-trunk:2] Goto("Zap/1-1", "s|1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Goto (from-trunk,s,1)
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:1] NoOp("Zap/1-1", "Entering from-zaptel with DID == 6153720300") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:2] Ringing("Zap/1-1", "") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:3] Set("Zap/1-1", "DID=6153720300") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:4] NoOp("Zap/1-1", "DID is now 6153720300") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:5] GotoIf("Zap/1-1", "1?zapok:notzap") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Goto (from-trunk,s,8)
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:8] NoOp("Zap/1-1", "Is a Zaptel Channel") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:9] Set("Zap/1-1", "CHAN=1-1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:10] Set("Zap/1-1", "CHAN=1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:11] Macro("Zap/1-1", "from-zaptel-1|6153720300|1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@macro-from-zaptel-1:1] NoOp("Zap/1-1", "Entering macro-from-zaptel-1 with DID = 6153720300 and setting to: 6153720300") in new stack
[Nov 2 13:30:55] DEBUG[18406] app_macro.c: Executed application: Noop
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@macro-from-zaptel-1:2] Set("Zap/1-1", "__FROM_DID=6153720300") in new stack
[Nov 2 13:30:55] DEBUG[18406] app_macro.c: Executed application: Set
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@macro-from-zaptel-1:3] Goto("Zap/1-1", "from-trunk|6153720300|1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Goto (from-trunk,6153720300,1)
[Nov 2 13:30:55] DEBUG[18406] app_macro.c: Executed application: Goto
[Nov 2 13:30:55] VERBOSE[18406] logger.c: == Channel 'Zap/1-1' jumping out of macro 'from-zaptel-1'
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [6153720300@from-trunk:1] Set("Zap/1-1", "DID=6153720300") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [6153720300@from-trunk:2] Goto("Zap/1-1", "s|1") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Goto (from-trunk,s,1)
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:1] NoOp("Zap/1-1", "Entering from-zaptel with DID == 6153720300") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:2] Ringing("Zap/1-1", "") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:3] Set("Zap/1-1", "DID=6153720300") in new stack
[Nov 2 13:30:55] VERBOSE[18406] logger.c: -- Executing [s@from-trunk:4] NoOp("Zap/1-1", "DID is now 6153720300") in new stack

Does anyone have any idea? I don’t mean to sound pushy, but I still don’t have it and my boss is really getting onto me about it. He needs the phones back up asap and I’m still blindly testing out different things.
Please help!

Ok, so I think I figured it out, although I don’t completely understand it.

Here’s what my old from-zaptel looked like. I saw it referencing from-pstn and didn’t want it to go there, but couldn’t figure out the right syntax, etc.

[from-zaptel]
exten => _X.,1,Set(DID=${EXTEN})
exten => _X.,n,Goto(s,1)
exten => s,1,NoOp(Entering from-zaptel with DID == ${DID})
; Some trunks _require_ a RINGING be sent before an Answer.
exten => s,n,Ringing()
; If ($did == "") { $did = "s"; }
exten => s,n,Set(DID=${IF($["${DID}"= ""]?s:${DID})})
exten => s,n,NoOp(DID is now ${DID})
exten => s,n,GotoIf($["${CHANNEL:0:3}"="Zap"]?zapok:notzap)
exten => s,n(notzap),Goto(from-pstn,${DID},1)
; If there's no ext-did,s,1, that means there's not a no did/no cid route. Hangup.
exten => s,n,Macro(hangup)
exten => s,n(zapok),NoOp(Is a Zaptel Channel)
exten => s,n,Set(CHAN=${CHANNEL:4})
exten => s,n,Set(CHAN=${CUT(CHAN,-,1)})
exten => s,n,Macro(from-zaptel-${CHAN},${DID},1)
; If nothing there, then treat it as a DID
exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN})
exten => s,n,Goto(from-pstn,${DID},1)
exten => fax,1,Goto(ext-fax,in_fax,1)

Since I never saw the working config of anything, I didn’t know how it was supposed to look and didn’t have anything to use as reference. I searched google and found this: http://www.freepbx.org/trac/wiki/ZapInboundRouting .
I copied and pasted the from-zaptel part and it worked! The current config is below.

[from-zaptel]
exten => _X.,1,Set(DID=${EXTEN})
exten => _X.,n,Goto(s,1)
exten => s,1,NoOp(Entering from-zaptel with DID == ${DID})
; If ($did == "") { $did = "s"; }
exten => s,n,Set(DID=${IF($[ "${DID}" = ""]?s:${DID))})
exten => s,n,NoOp(DID is now ${DID})
exten => s,n,GotoIf($[ "${CHANNEL:0:3}" = "Zap" ]?zapok:notzap)
exten => s,n(notzap),Goto(ext-did,${DID},1)
; If there's no ext-did,s,1, it'll hang up by itself. No need for a hangup.
exten => s,n(zapok),NoOp(Is a Zaptel Channel)
exten => s,n,Set(CHAN=${CHANNEL:4})
; Zaptel channel Format "Zap/Chan-Bearer" - Bearer is pretty much always 1, I think?
exten => s,n,Set(CHAN=${CUT(CHAN,-,1)})
exten => s,n,Macro(from-zaptel-${CHAN},${DID},1)
; If it returns, then there was no match, so continue on 
exten => s,n,NoOp(Returned from Macro from-zaptel-${CHAN} - No match)
exten => s,n,Goto(ext-did,${DID},1)

I had to copy that into extensions.conf and extensions_additional.conf.
Now that is working, so I don’t have to freak out anymore, but there are a few problems and questions I have.

  1. Is there a good tutorial/reference that would help me learn how to decipher the code in the from-zaptel context? I hate getting something to work but not understanding why.

  2. Whenever I make a change to the IVR, it puts the old from-zaptel config back into extensions_additional.conf. I don’t know where it is pulling it from, but it puts it back there and causes it not to work again. The from-zaptel context in the main extensions.conf stays the same, but I guess the one that matters is in the additional file, since that appears to be where it is reading from.
    It doesn’t do it when I just reload the configs, but it does when I change the IVR and then reload.
    Ideas?

  3. The IVR works fine and when you press 0, it goes to our receptionist. The only problem is that whenever you dial any other option on the IVR(For example, I have 205 set to go to ext. 205), it goes straight to that extensions voicemail without ringing. So, the only option that works is 0(which forwards to ext. 200).
    Any reason why that would happen?

Thanks!

carrothospital

Ok you have a issue here and your way of fixing it by editing some of the files is wrong. First off editing extensions.conf and extensions_additional.conf are not a solution as they are owned by FreePBX (as they are marked and say so at the top of each file). See http://freepbx.org/configuration_files for further information. You’ll end up loosing those changes when you make another change in the GUI as extensions_additional.conf is re-generated each and every time there is a change.

If you really want to learn about dial plans the place to start is here: Asterisk: The Future of Telephony 2nd Edition (ISBN 0-596-51048-9) — Order yours at http://www.oreilly.com/catalog/9780596510480/ — Free downloadable PDF http://downloads.oreilly.com/books/9780596510480.pdf — HTML at http://tfot.leifmadsen.com

But running around and “hacking” files is not the proper way to do things.

It is possible that your system worked in the beginning because the files were hacked together in a way that just happened to work. But since the upgrade those hacks which should not have been placed where they were have now been removed and thus the problem.

In reality you need some professional services to take a look at your setup and determine what is really going on. If you’ve gone around editing files without paying attention to the notices in them all kinds of things can now be screwed up.

I’d recommend either clicking on the left hand side and ordering some support services or contact a local support person if possible.

I can tell you that I’ve upgraded from FreePBX 2.0 up through 2.4 and never had the issues you are having which means there is a really a deeper issue going on that will be hard to determine without a expert.

Thanks for the reply.

I did see that those conf files were not supposed to be manually edited, but I didn’t think I had much of a choice.

My boss and another guy(who doesn’t work here anymore) set it up and just threw it to me. My boss told me that he had to go in and manually fix some files for it to work originally. That would explain the loss of functionality after the upgrade.
I had to opt for the quickest resolution possible for now, because the phones needed to be back up asap, even if it’s a temporary fix that included hacking at the conf files.

The problem with the extensions turned out to be an issue with the soft phones, not freepbx. We only have one actual IP phone on the network and that was working fine.
For some reason, X-lite was screwing up. I tried Zoiper and it worked. Then I reinstalled X-lite and it works.

My only issue now is how to keep those changes from getting overwritten. Since it get’s rewritten every time a change is made in the GUI, I guess I’ll have to find a way to make the equivalent of those changes there, if that’s possible.
Any tips on that?

Thanks for the book link, I’ll look into that and I’m sure it will help clear a few things up.

I’d learn to build the system correctly instead of hacking it. Next time it will probably be even worse as the default dialplan changes over time and the old hacks don’t always work going forward.

Nothing you have described for functionality is something that can’t be done the correct way. So if it is done the correct way it will then work going forward which is really the important part.

Ok, so, I couldn’t ever find a straight answer or example of creating a custom inbound context from the gui, so here’s what I did.

I just took the from-zaptel section that worked and put it in extensions_custom.conf as from-zaptel-custom.
Then in the my zapata conf files I put the context as from-zaptel-custom. Now everything works and it doesn’t get overwritten.

Is this the right way to do it? I know you mentioned that you could create everything you need from the GUI, but I couldn’t find where or how to do it right, or anywhere that had clear instructions on it.

Thanks.