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")); } }}}