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>