[asterisk-users] Hot desking and presence

Noah Engelberth Noah at directlinkcomputers.com
Thu Feb 23 09:41:25 CST 2012


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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-users/attachments/20120223/64f1dd19/attachment.htm>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: AVG Certification.txt
URL: <http://lists.digium.com/pipermail/asterisk-users/attachments/20120223/64f1dd19/attachment.txt>


More information about the asterisk-users mailing list