I've spent some time the last couple days working on a way to get presence to 
work with vanilla Asterisk (10.1.2) and a func_odbc hotdesking deployment.  
Given the lack of much results of anything on Google for this type of 
deployment, I thought I'd share my dialplan magic in case anyone else needs to 
find the same solution in the future.

And if someone sees something I'm doing that can/should be improved, I'd be 
happy to know that too...

My dialplan setup is based heavily on the example in the Relational Database 
Integration chapter of the most recent verison of Asterisk: The Definitive 
Guide (http://ofps.oreilly.com/titles/9780596517342/asterisk-DB.html).  I'm 
also using queues (subscribing the SIP phone itself and grabbing the Caller ID 
name of the logged in user for the agent label), so there's some extra 
excitement related to all that.

Basically, the premise is...

-          When an internal user dials a call, set a GROUP(activecalls) 
variable on their channel to their extension, and set their custom device state 
to INUSE.

-          When an internal user is dialed, set their custom device state to 
either RINGINUSE or RINGING, depending on if their extension is or isn't 
involved in another call.

-          When an internal user answers a dialed call, set a 
GROUP(activecalls) variable to their extension and set their custom device 
state to INUSE.

-          When an agent answers a queue call, set a GROUP(activecalls) 
variable to their extension and set their custom device state to INUSE.

-          When any call hangs up, do the following:

o   Check to see if the call was a queue call (MEMBERINTERFACE will be set).  
If it was, figure out which extension answered it, and check to see how many 
GROUP(activecalls) they're on.  If it's equal to 1, that means the call they're 
finishing is the only call they're on, so set the custom device state to 
NOT_INUSE.  Otherwise set (should really wind up effectively being "leave") the 
device state to INUSE, since they've got at least 1 other call in progress.

o   Check to see if the call was a call dialed by an internal user (WHO will be 
set).  If it was, check to see how many GROUP(activecalls) the WHO user is on.  
If it's equal to 1, that means the call they're finishing is the only call 
they're on, so set the custom device state to NOT_INUSE.  Otherwise set (should 
really wind up effectively being "leave") the device state to INUSE, since 
they've got at least 1 other call in progress.

o   Check to see if the call was a call directly dialed to an internal user (E 
will be set).  If it was, check to see how many GROUP(activecalls) the E user 
is on.  If it's equal to 1, that means the call they're finishing is the only 
call they're on, so set the custom device state to NOT_INUSE.  Otherwise set 
(should really wind up effectively being "leave") the device state to INUSE, 
since they've got at least 1 other call in progress.

Still haven't figured out how to get FOP2 to work with my Custom devices, 
working on that.  A known limitation of this approach is that my custom devices 
won't show ringing while a queue call is ringing them.

This depends on "setinterfacevar=yes" being applied to all of my queues in 
queues.conf

The relevant portions of my dialplan are:
[hints]
exten => <my extension pattern match>,hint,Custom:${EXTEN}

[hotdesk_outbound]
includes (via cascade) internal-calls

exten => .X,1,NoOp()
...snip do stuff to determine who's calling, set their extension number to 
WHO...
same => n,Set(GROUP(activecalls)=${WHO})
same => n,Set(DEVICE_STATE(Custom:${WHO})=INUSE)
...snip make the call...

exten => h,1,NoOp()
same => n,Goto(cleanup-devicestate,s,1)

[internal-calls]
...snip set the called extension to E and look up what device to dial...
same => n,NoOp(Who: ${WHO} Calls: ${GROUP_COUNT(${WHO}@activecalls)})
same => n,NoOp(Exten: ${E} Calls: ${GROUP_COUNT(${E}@activecalls)})
same => 
n,ExecIf($[${GROUP_COUNT(${E}@activecalls)}>0]?Set(DEVICE_STATE(Custom:${E})=RINGINUSE):Set(DEVICE_STATE(Custom:${E})=RINGING))
same => n,Dial(SIP/${USER_LOCATION},20,wWU(answered^${E}))

[incoming]
...snip call menu eventually puts callers into something like...
same => n,Queue(<myqueuename>,<options>,,,<timeout>,,,answered-queue)
same => n,NoOp(Who: ${WHO} Calls: ${GROUP_COUNT(${WHO}@activecalls)})
same => n,NoOp(Exten: ${E} Calls: ${GROUP_COUNT(${E}@activecalls)})
same => 
n,ExecIf($[${GROUP_COUNT(${E}@activecalls)}>0]?Set(DEVICE_STATE(Custom:${E})=RINGINUSE):Set(DEVICE_STATE(Custom:${E})=RINGING))
same => n,Dial(SIP/${USER_LOCATION},20,wWU(answered^${E}))

...snip dial my internal extensions directly - set the dialed extension to E 
and look up the device to dial...
same => 
n,ExecIf($[${GROUP_COUNT(${E}@activecalls)}>0]?Set(DEVICE_STATE(Custom:${E})=RINGINUSE):Set(DEVICE_STATE(Custom:${E})=RINGING))
same => n,Dial(SIP/${USER_LOCATION},20,wWU(answered^${E}))

exten => h,1,NoOp()
same => n,Goto(cleanup-devicestate,s,1)

[answered]
exten => s,1,NoOp(${ARG1})
same => n,Set(GROUP(activecalls)=${ARG1})
same => n,NoOp(Exten: ${ARG1} Calls: ${GROUP_COUNT(${ARG1}@activecalls)})
same => n,Set(DEVICE_STATE(Custom:${ARG1})=INUSE)
same => n,Return()

[answered-queue]
exten => s,1,NoOp()
same => n,Set(AGENT=${HOTDESK_PHONE_STATUS(${CUT(MEMBERINTERFACE,/,2)})})
same => n,NoOp(Agent ${AGENT}) ; for my troubleshooting to see what it's doing
same => n,Set(GROUP(activecalls)=${AGENT})
same => n,Return()

[cleanup-devicestate]
exten => s,1,NoOp()
same => n,NoOp(Who: ${WHO} Calls: ${GROUP_COUNT(${WHO}@activecalls)})
same => n,NoOp(Exten: ${E} Calls: ${GROUP_COUNT(${E}@activecalls)})
same => n,GotoIf($[${ISNULL(${MEMBERINTERFACE})}]?internal)
same => n,Set(DEVICE=${CUT(MEMBERINTERFACE,/,2)})
same => n,Set(AGENT=${HOTDESK_PHONE_STATUS(${DEVICE})})
same => n,NoOp(Agent: ${AGENT} Calls: ${GROUP_COUNT(${AGENT}@activecalls)})
same => 
n,ExecIf($[${GROUP_COUNT(${AGENT}@activecalls)}>1]?Set(DEVICE_STATE(Custom:${AGENT})=INUSE):Set(DEVICE_STATE(Custom:${AGENT})=NOT_INUSE))
same => 
n(internal),ExecIf(${ISNULL(${WHO})}?NoOp(${HOTDESK_INFO(location,${WHO})}):ExecIf($[${GROUP_COUNT(${WHO}@activecalls)}>1]?Set(DEVICE_STATE(Custom:${WHO})=INUSE):Set(DEVICE_STATE(Custom:${WHO})=NOT_INUSE)))
same => 
n,ExecIf(${ISNULL(${E})}?NoOp(${HOTDESK_INFO(location,${E})}):ExecIf($[${GROUP_COUNT(${E}@activecalls)}>1]?Set(DEVICE_STATE(Custom:${E})=INUSE):Set(DEVICE_STATE(Custom:${E})=NOT_INUSE)))


Noah Engelberth
MetaLINK Technologies
System Administration

The message does not contain any threats
AVG for MS Exchange Server (2012.0.1913 - 2114/4827)
--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --
New to Asterisk? Join us for a live introductory webinar every Thurs:
               http://www.asterisk.org/hello

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/asterisk-users

Reply via email to