This has been bugging me for a bit as it really leaves some functionality to be desired. If a site has 4 PSTN lines coming into a TDM400, they might want one line to be a 'direct to sales' and the other to be a 'direct to spares' line, but there's no way to do that currently.

My brainwave is, add another match to Inbound Routing: 'Zap Channel Number' and actually check the ${CHANNEL} variable. D'oh! Why didn't I think of that before?

The zaptel context will then need to be 'from-zaptel', and the code will be something like this:

DID 89765432, no CID, zap 3 == ivr-1
no DID, no CID, zap 3 == ivr-2
no DID, no CID, zap 3 == rg-200
no DID, CID 23456789, zap 3 == rg 202
no DID, CID 12345678, zap 3 == rg-201
no DID, CID 23456789, zap 3 == rg-202

Should produce :

$zap = array (
  array (channel = 3, cid = '', did = '8765432', dest='ivr-1'),
  array (channel = 3, cid = '', did = '', dest='ivr-2'),
  array (channel = 3, cid = '23456890', did = '', dest='rg-202'),
  array (channel = 4, cid = '', did = '', dest='rg-200'),
  array (channel = 4, cid = '12345678', did = '', dest='rg-201'),
  array (channel = 4, cid = '23456890', did = '', dest='rg-202'),
)

Dialplan would be:

[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)

Now.. Getting the information out of the array.. We want to end up with:

[macro-from-zaptel-3]
exten => 8765432,1,Goto(ivr-1,s,1)
exten => s,1,NoOp(Entering from-zaptel-3 with DID ${ARG1})
; This will continue on if there's no match.
exten => s,n,Goto(${ARG1})
exten => s,n,GotoIf($[ "CALLERID(number)" = "23456789" ]?rg-202:)
exten => s,n,Goto(ivr-2,s,1)

[macro-from-zaptel-4]
exten => s,1,NoOp(Entering from-zaptel-4 with DID ${ARG1})
; This will continue on if there's no match.
exten => s,n,Goto(${ARG1})
exten => s,n,GotoIf($[ "CALLERID(number)" = "12345678" ]?rg-201:)
exten => s,n,GotoIf($[ "CALLERID(number)" = "23456789" ]?rg-202:)
exten => s,n,Goto(rg-200,s,1)

Notes:

  • I changed the default sip and iax trunk to be 'from-trunk' the other day. This means that we could replace from-pstn with from-zaptel?
  • This actually seems to work. Wow.
  • Except for Goto() returning -1 when a context doesn't exist, and hanging up the channel. Game over. This means that we can't match on DID or CID when matching on a zaptel channel.
    • is this a show stopper? I know you committed something, so i guess not :-)

I have added this to freepbx, I think it will do what is desired. There is simply an additional yes/no field under DID Number to indicate if the DID should be interpreted as a zap channel. You could then put in a 2 or 3 digit DID. Example 112 would be Zap/1-12 or 11 would be Zap/1-1. I think this would work but I don't have any zap cards to acutally test it. Here is an example of the generated dial plan:

[ext-did]
include => ext-did-custom
; other stuff from normal DID routing
exten => s,1,GotoIf($[ (${CHANNEL:0:3} = Zap) & (zap${CHANNEL:4:1}${CHANNEL:6} = zap21) ]?zap21,1)
exten => s,n,GotoIf($[ (${CHANNEL:0:3} = Zap) & (zap${CHANNEL:4:1}${CHANNEL:6} = zap122) ]?zap122,1)
exten => s,n,GotoIf($[ (${CHANNEL:0:3} = Zap) & (zap${CHANNEL:4:1}${CHANNEL:6} = zap116) ]?zap116,1)
exten => s,n,GotoIf($[ (${CHANNEL:0:3} = Zap) & (zap${CHANNEL:4:1}${CHANNEL:6} = zap212) ]?zap212,1)
exten => zap21,1,Set(FROM_DID=zap21)
exten => zap21,n,Goto(aa_1,s,1)
exten => zap122,1,Set(FROM_DID=zap122)
exten => zap122,n,Set(FAX_RX_EMAIL=me@company.com)
exten => zap122,n,Answer
exten => zap122,n,Wait(1)
exten => zap122,n,Goto(timeconditions,1,1)
exten => zap116,1,Set(FROM_DID=zap116)
exten => zap116,n,Set(_ALERT_INFO=Bellcore-r1)
exten => zap116,n,Goto(timeconditions,1,1)
exten => zap212,1,Set(FROM_DID=zap212)
exten => zap212,n,Answer
exten => zap212,n,Wait(0)
exten => zap212,n,Goto(ext-group,2,1)

; end of [ext-did]

The guts of the code is fairly straight forward, it requires a new field in the incoming table and I've added some code in the page.did.php to show which of the channels are zap routing in the table off on the right. I think this will work, thoughts. (I'm ready to check it and a bunch of other functionality in once I get access.)

if ($item['usezapchannel'] == "1") {
    $exten = 'zap'.$exten;
    ext->add('ext-did', "s", '', new ext_gotoif('$[ (${CHANNEL:0:3} = Zap) & (zap${CHANNEL:4:1}${CHANNEL:6} = '.$exten.') ]',$exten.",1"));
}