<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0in;
        margin-right:0in;
        margin-bottom:0in;
        margin-left:.5in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.Section1
        {page:Section1;}
/* List Definitions */
@list l0
        {mso-list-id:2032998451;
        mso-list-type:hybrid;
        mso-list-template-ids:-1151046648 62308202 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:-;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Calibri","sans-serif";
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
-->
</style>
<!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=EN-US link=blue vlink=purple>
<div class=Section1>
<p class=MsoNormal>One of my clients requested that I implement a car hop
feature for their parked calls. I have implemented the functionality
using existing dialplan functions, but I think it could be improved if the Park
implementation was updated to more directly support this sort of feature.
My implementation is as follows:<o:p></o:p></p>
<p class=MsoListParagraph style='text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'>
</span></span><![endif]>Asterisk plays back a recorded message to the parked
caller, and listen for DTMF input from the caller. The specific message
we have recorded is to the effect of “Your representative is still
unavailable. To continue holding, press 1 or remain on the line. To
return to the operator or leave a voice message, press 0.”<o:p></o:p></p>
<p class=MsoListParagraph style='text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'>
</span></span><![endif]>Asterisk then waits a few seconds for input, and puts
the call back into the original parking slot if no input was received (or if a
1 was received). If a 0 was received, the call is sent to my operators
hunt group, and the operator can put the caller into a voice-mail queue if the
caller requests it.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>What I would like to request is that some sort of similar
behavior is directly implemented into Asterisk (in an optional way, so that if
someone doesn’t want it, they don’t get it), and if possible in a
way that the call remains accessible in the parking lot until they push the
button to return to the operator.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>The dialplan code I am using to effect my car hop currently is
as follows:<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>[macro-bryan-parked]<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => s,1,NoOp()<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
s,n,GotoIf($[$[${DEVICE_STATE(park:1071@bryan-parked)}=NOT_INUSE] &
$[!$[${DEVICE_STATE(Custom:park1071)}=INUSE]]]?park1071,1)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
s,n,GotoIf($[$[${DEVICE_STATE(park:1072@bryan-parked)}=NOT_INUSE] &
$[!$[${DEVICE_STATE(Custom:park1072)}=INUSE]]]?park1072,1)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>-snip- continue for my other parking extensions<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
s,n,Playback(all-outgoing-lines-unavailable)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => park1071,1,Set(PARKEDAT=1071)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => park1071,n,Set(PARKINGEXTEN=1071)<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>exten
=> park1071,n,Park(,parkedcallstimeout,s,1)<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => park1072,1,Set(PARKEDAT=1072)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => park1072,n,Set(PARKINGEXTEN=1072)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => park1072,n,Park(,parkedcallstimeout,s,1)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>-snip- continue for my other parking extensions<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>; end [macro-bryan-parked]<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>[parkedcallstimeout]<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => s,1,NoOp("Parked call timed out -
${PARKEDAT} - CID: "${CALLERID(all)})<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
s,n,Set(DEVICE_STATE(Custom:park${PARKEDAT})=INUSE)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
s,n,Background(custom/aol-to-continue-holding)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => s,n,WaitExten(5)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => s,n,Goto(1,1)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => 0,1,Set(CALLERID(name)="Park:
"${CALLERID(name)})<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
0,n,Set(DEVICE_STATE(Custom:park${PARKEDAT})=NOT_INUSE)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => 0,n(dial),Dial(SIP/1010,20,wW)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
0,n,Dial(SIP/1010&SIP/1028&SIP/1016&SIP/1015,20,wW)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => 0,n,Goto(0,dial) ; dial failed - retry<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => 1,1,Set(PARKINGEXTEN=${PARKEDAT})<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten =>
1,n,Set(DEVICE_STATE(Custom:park${PARKEDAT})=NOT_INUSE)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => 1,n,Park(,parkedcallstimeout,s,1,s)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => i,1,Goto(0,1)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => t,1,Goto(1,1)<o:p></o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'><o:p> </o:p></span></p>
<p class=MsoNormal style='text-autospace:none'><span style='font-size:9.0pt;
font-family:"Courier New"'>exten => h,1,Set(DEVICE_STATE(Custom:park${PARKEDAT})=NOT_INUSE)<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>;
end [parkedcallstimeout]</span><o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>So, the changes from the normal logic are as follows:<o:p></o:p></p>
<p class=MsoListParagraph style='text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'>
</span></span><![endif]>My function overrides the default parking slot
selection logic for two reasons. First, if a parked call has timed out
and the caller is still listening to the “would you like to keep waiting?”
message, the parking slot they were in will show as available and could be
chosen by a new parked call. Alternately, if 1071 is in use when a call
is initially parked (thus putting the call on 1072), but then is available
after the call has timed out and automatically re-parks, the default logic
would “move” the call up to 1071 (since the default logic sees the
re-park as a new parked call). As this causes much confusion and
consternation when parked calls move around, I need some way to know which
parking slot a time-out comes from, and I need a way to lock that parking
slot while the timed-out caller is determining whether or not he wants to keep
holding.<o:p></o:p></p>
<p class=MsoListParagraph style='text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'>
</span></span><![endif]>Since I couldn’t find a way to get the parking slot
a timed out call was coming from, I went ahead and set a custom channel variable
(PARKEDAT) prior to parking the call. This variable is then available
when the call times out to tell me where it came from.<o:p></o:p></p>
<p class=MsoListParagraph style='text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'>
</span></span><![endif]>In order to lock the parking slot that the timed out
call is coming from, I set a Custom device state for park1071, park1072, or
whichever slot was timed out. The hangup extension ensures that if the
caller should hang up while listening to the “would you like to keep
waiting?” message, the custom device state gets unlocked, thus preventing
the parking slot from getting stuck closed.<o:p></o:p></p>
<p class=MsoListParagraph style='text-indent:-.25in;mso-list:l0 level1 lfo1'><![if !supportLists]><span
style='mso-list:Ignore'>-<span style='font:7.0pt "Times New Roman"'>
</span></span><![endif]>If the user chooses to return to the operator, I
pre-pend the Park: information to the caller ID name of the call, so that the
operator is able to distinguish the call from a normal incoming call and answer
it appropriately.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>What I would like to see is a way (within features.conf or
something similar) to have Asterisk enter a car hop mode for a timed-out parked
call, so that Asterisk jumps to a specified dialplan priority which would allow
the system admin (me) to configure a message to be played and logic to handle
any input I might expect. There should be a function that allows me to re-park
the call on the same slot (effectively resetting the parked call timeout
timer), and the parked call should remain in the parking slot while the car hop
logic is executing if at all possible, so that if the representative becomes
available while the caller is listening to the “would you like to keep
waiting” message, the representative can pick up the call. If the
car hop must remove the call from the parking lot in order to handle it, it
should at least lock the parking lot to any other calls until the timed out
call has chosen to leave the parking lot (either via hanging up or by using one
of our specified “leave the parking lot” methods).<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>I’d definitely help with the testing, and I’d be
willing to help with the coding if someone can give me an idea where to start
digging; I find the prospect of digging through to find where the parking
features are implemented a little daunting.<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Thank you,<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<p class=MsoNormal>Noah Engelberth<o:p></o:p></p>
<p class=MsoNormal>Direct Link Computer Systems<o:p></o:p></p>
<p class=MsoNormal>noah@directlinkcomputers.com<o:p></o:p></p>
<p class=MsoNormal>419-636-0999 ext 100<o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
</div>
</body>
</html>