(MORE SOLVED) Combining Queues with Parking

Hi All,
I am about try and setup a Queue that will place calls into a single parking lot.
I had a quick test and it seemed to work for the first call, but a second call heard the no parking slots available message and then was terminated
Parking does not seem to give an optional destination if the lot is full.

I have not thought of what happens at the end of the parking lot timeout yet, perhaps push them back to the queue or hit another ring group.

Before I find some convoluted method to achieve this I wondered if someone had devised a simple plan already.

I am hoping the end result will allow me a single BLF button to advise of the next call in the que.

The thought process was:

  • Incomming call,
  • Agent Answers,
  • Agent can divert to queue 0 by “##0#”,
  • if the parking lot is empty then the queue will pass it to the parking slot 1 and make the BLF button flash.
  • if the parking lot is already full then the call simply remains in the queue until the timeout or the parking slot becomes available.

Oh I did notice in my various attempts and number changing that that Queues did not like 0,0 in the static agents list. it was happy with 1,0

Hv.

Ahh found the (some) source for call parking.
Not sure if it is current but it explains the process.
http://doxygen.asterisk.org/asterisk1.6.2/features_8c-source.html#l00739

Looks like the call rejection and no slots announcement is hard coded.

Anyone fancy a challenge or is it going to be me.?

Hv.

Hum I feel a little alone on this topic !!

Well I crafted a Parking slot State query so to speak that works in the respect of showing busy if the slot is in use.

exten => s,n,Noop(*** HIDDENVISION PARKING STATE TEST ***)
exten => s,n,ExecIf($[ ${DEVICE_STATE(park:11@parkedcalls)} = INUSE ]?Busy)

I have been trying to find a logical place to put it to pre-process any attempt to park a call either manually from an extension or directly from a Queue.

Tried in “extensions_custom.conf” file
but it would appear this may be processed after the original plan so I put some bits in just after the start of macro-parked-call of “extensions-additional”.
But I only see these when I go to pickup the parked call by dialing 11.
May be something in the naming !

This was in the “extensions_additional.conf”

[macro-parked-call]
include => macro-parked-call-custom
exten => s,1,Macro(user-callerid,)
exten => s,n,Noop(*** HIDDENVISION PARKING STATE TEST ***)
exten => s,n,ExecIf($[ ${DEVICE_STATE(park:11@parkedcalls)} = INUSE ]?Busy)
Plus all the normal stuff.!
In this position it shows busy when I try to pickup the parked call.

With that I get

  • pbx.c: – Executing [s@macro-parked-call:2] NoOp( “*** HIDDENVISION parked-call-macro ***”)
  • pbx.c: – Executing [s@macro-parked-call:3] ExecIf(“1?Busy”)
  • app_macro.c: == Spawn extension (macro-parked-call, s, 3) exited non-zero in macro ‘parked-call’
  • pbx.c: == Spawn extension (from-internal, 11, 1) exited non-zero
  • pbx.c: – Executing [h@from-internal:1] Hangup()

Trimmed for clarity

I am doing it manually, on an off line box, placing those check state lines in various parts of the extensions_additional.conf but still have not found the entry point for 10@from-internal.
Not sure if the context will change if same call placed from a Queue.
This is the log of placing a call to the full parking lot from an extension(6201).

pbx.c: – Executing [10@from-internal:1] Park(“SIP/6201-0000002d”, “”)
features.c: No more parking spaces in default
file.c: – <SIP/6201-0000002d> Playing 'pbx-parkingfailed.ulaw’
pbx.c: – Executing [10@from-internal:2] NoCDR(“SIP/6201-0000002d”, “”)

then goes off to hangup or play unable to connect (I forget)
Again trimmed for easy reading but that is the full flow to the point of failure…

This was a log from the attempt from the Queue.
Cool, different context.!

[29195] pbx.c: – Executing [10@from-queue:1] Set(“Local/10@from-queue-00000004;2”, “QAGENT=10”)
[29195] pbx.c: – Executing [10@from-queue:2] Goto(“Local/10@from-queue-00000004;2”, “1,1”)
[29195] pbx.c: – Goto (from-queue,1,1)
[29195] pbx.c: – Executing [1@from-queue:1] Goto(“Local/10@from-queue-00000004;2”, “from-internal,10,1”)
[29195] pbx.c: – Goto (from-internal,10,1)
[29195] pbx.c: – Executing [10@from-internal:1] Park(“Local/10@from-queue-00000004;2”, “”)
[29194] app_queue.c: – Local/10@from-queue-00000004;1 answered SIP/6201-00000034
[29194] file.c: – <Local/10@from-queue-00000004;1> Playing ‘queue-reporthold.ulaw’ (language ‘en’)
[29194] res_musiconhold.c: – Stopped music on hold on SIP/6201-00000034
[29195] features.c: No more parking spaces in default
[29195] file.c: – <Local/10@from-queue-00000004;2> Playing ‘pbx-parkingfailed.ulaw’ (language ‘en’)
[29195] pbx.c: – Executing [10@from-internal:2] NoCDR(“Local/10@from-queue-00000004;2”, “”)
[29195] pbx.c: – Executing [10@from-internal:3] Progress(“Local/10@from-queue-00000004;2”, “”)
[29195] pbx.c: – Executing [10@from-internal:4] Wait(“Local/10@from-queue-00000004;2”, “1”)
[29195] pbx.c: – Executing [10@from-internal:5] Progress(“Local/10@from-queue-00000004;2”, “”)
[29195] pbx.c: – Executing [10@from-internal:6] Playback(“Local/10@from-queue-00000004;2”, “silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer”)
[29195] file.c: – <Local/10@from-queue-00000004;2> Playing ‘silence/1.ulaw’ (language ‘en’)
[29195] file.c: – <Local/10@from-queue-00000004;2> Playing ‘cannot-complete-as-dialed.ulaw’ (language ‘en’)
[29195] file.c: – <Local/10@from-queue-00000004;2> Playing ‘check-number-dial-again.ulaw’ (language ‘en’)
[29195] pbx.c: – Executing [10@from-internal:7] Wait(“Local/10@from-queue-00000004;2”, “1”)
[29195] pbx.c: – Executing [10@from-internal:8] Congestion(“Local/10@from-queue-00000004;2”, “20”)
[29194] pbx.c: – Executing [h@from-internal:1] Hangup(“SIP/6201-00000034”, “”)
[29194] features.c: == Spawn extension (from-internal, h, 1) exited non-zero on ‘SIP/6201-00000034’
[29195] pbx.c: == Spawn extension (from-internal, 10, 8) exited non-zero on ‘Local/10@from-queue-00000004;2’
[29195] pbx.c: – Executing [h@from-internal:1] Hangup(“Local/10@from-queue-00000004;2”, “”)
[29195] pbx.c: == Spawn extension (from-internal, h, 1) exited non-zero on ‘Local/10@from-queue-00000004;2’
[29194] pbx.c: == Spawn extension (from-internal, 1, 40) exited non-zero on ‘SIP/6201-00000034’

I am only showing the failure not much point in the working logs.
Any call put in the queue when the parking lot is empty gets pushed to parking as expected but fails if the parking is FULL.

I am thinking this is perhaps one thing I should find for myself but not able to find it so far. Could any kind folk advise where I may stick it.?

Hv.

Ok that seemed to hit the spot.
Found the from-queue section instead.

[from-queue]
include => from-queue-custom
exten => 1,1,Noop(*** HIDDENVISION From Queue )
exten => 1,n,Noop(
${EXTEN} ${QAGENT} )
exten => 1,n,GotoIf($["${QAGENT}" = “10”]?checkpark)
exten => 1,n,Goto(from-internal,${QAGENT},1)
exten => 1,n(checkpark),Noop(
HIDDENVISION CHECKING ***)
exten => 1,n,ExecIf($[ ${DEVICE_STATE(park:11@parkedcalls)} = INUSE ]?Busy)
exten => 1,n,Goto(from-internal,${QAGENT},1)

nice, now to try an put it somewhere that will tolerate reloads.
But it does appear that is a very dis-interesting topic I guess.

Hv.

Ok I have added some other bits to get rid of the parking lot anouncment.
The two sections look like this:

;##############################
IN extensions_additional.conf
;##############################
[from-queue]
include => from-queue-custom
exten => 0,1,Noop(*** HIDDENVISION From Queue ***)
exten => 0,n,Noop(***"${QAGENT}"***)
exten => 0,n(gocall),Macro(from-queue-custom,)
exten => 0,n,Goto(from-internal,${QAGENT},1)
;##############################

;##############################
IN extensions_custom.conf
;##############################
[macro-from-queue-custom]
exten => s,1,Noop(*** HIDDENVISION FROM QUEUE BLIND )
exten => s,n,Noop(***"${QAGENT}"***)
exten => s,n,GotoIf($["${QAGENT}" != “10”]?letsgo)
exten => s,n,Noop(
HIDDENVISION CHECKING LOT )
exten => s,n,ExecIf($[ ${DEVICE_STATE(park:11@parkedcalls)} = INUSE ]?Busy)
exten => s,n(doparkit),Noop(
HIDDENVISION PARKING SEEMS FREE ***)
exten => s,n,Set(BLINDTRANSFER=1)
exten => s,n(letsgo),MacroExit()
;exten => s,n,Goto(from-internal,${QAGENT},1)

Trouble is I cannot quite work out how to survive a reload.
the custom stuff stays in place but any stuff in additional.conf is replaced.
I thought I could just have a section like [from-queue-custom], rather than the macro but it is never called/included and yet the call to the macro works.

This is a typical case of not being able to find the right section in the documents.
believe me I have tried but I just cannot figure this include stuff. Must be a brain block.!

I think I have done all the hard stuff just need to understand the placement better.
Any help, ANYONE.?

Hv.

Maybe you could start at

Hey Dicko,

Humm, interesting read although I have done all the creating I need.
I am just having trouble understanding how the files are used and perhaps more importantly in what order things are processed in the dial-plan.

The bit that confuses me is this, if you don’t mind me waffleing on.!
Example section from extensions_additional.conf

[from-queue]
include => from-queue-custom
exten => 0,n,Goto(from-internal,${QAGENT},1)

I look at that and think that anything I place in a section [from-queue-custom]
within my extensions_custom.conf file should be called before the default line.

With this in my extensions_custom.conf

[from-queue-custom]
exten => 0,1,Noop(*** HIDDENVISION FROM QUEUE BLIND )
exten => 0,n,Noop("${QAGENT}")
exten => 0,n,GotoIf($["${QAGENT}" != “10”]?letsgo)
exten => 0,n,Noop(
HIDDENVISION CHECKING LOT )
exten => 0,n,ExecIf($[ ${DEVICE_STATE(park:11@parkedcalls)} = INUSE ]?Busy)
exten => 0,n(doparkit),Noop(
HIDDENVISION PARKING SEEMS FREE )
exten => 0,n,Set(BLINDTRANSFER=1)
exten => 0,n(letsgo),Noop(
HIDDENVISION PARKING WERE LEAVING ***)

(EDIT:) oops left in the s,n from the macro version.
but this is from file not the pbx, the pbx had 0,n correctly.!

I still find the section is not even entered from what I see,
or don’t see in the logs.

And yet,
if I remove the line
exten => 0,n,Goto(from-internal,${QAGENT},1)
from additional.conf then my custom section kicks in.

Leading me to think that the custom section is processed after the regular parts.

Or have I just got my head on backwards today.?

Hv.

I’m sure you’ll get there but parking lots are not something I have ever had much of a need for, I would try the alternate code as suggested just in case though.

Good luck though.

Humm,
The downside with the blind transfer approach to silence the lot number announcement is that when the parking timeout kicks off the call is terminated rather than sent back to the preferred destination.

Park([timeout,[return_context,[return_exten,[return_priority,[options,[parking_lot_name]]]]]])

I do see that there is option s for silencing but I cannot find anywhere that this park() is called, well one place but that is never used from all my looking.

Is this “hard coded” somewhere away from conf files.?
Guessing if the Asterisk Park() function has the option to be silent then perhaps this is a tick box missing out of the freepbx parking module to give the option.

Hv.

well I got there in my own way.
Could not for the life of budda find a way to include any custom stuff for the from-queue section without editing the additional file that is under FreePbx control.

So a quick cron job later, Finding the offending line in additional.conf and replace it with my own lines and calling my macro that is safe in the custom file.
Not the preferred solution, but hey, what works - works, and I get more sleep…

Just got to figure this muting of the parking number anouncment, or I may just delete the number sound files that are relevant to the lot number!!

Hv.

1 Like

Probably better to do the /etc/asterisk/extensions_override_freepbx.conf thingy, no cron job needed, just a watchful eye if the “base code” changes to impact you modified code.

But as you say pragmatism will always beats dogma when your kharma runs over the other guys dogma :wink: .

Ahh I dropped the whole thought of simply trying to “interfere” with the flow of things.
Could not find the part that is used to park the call by default so I just call the same Park() function setting the return path to some useful values. This shows that the silent option does work without using blindtransfer. I ended up with this as a working solution.

[macro-from-queue-custom]
exten => s,1,Noop(*** HIDDENVISION FROM QUEUE CUSTOM )
exten => s,n,Noop(
PARKING NUMBER “${QAGENT}”)
exten => s,n,GotoIf($[“${QAGENT}” != “10”]?from-internal,${QAGENT},1)
exten => s,n,Noop(
HIDDENVISION CHECK PARKING LOT )
exten => s,n,ExecIf($[ ${DEVICE_STATE(park:11@parkedcalls)} = INUSE ]?Busy)
exten => s,n(doparkit),Noop(
HIDDENVISION PARKING SEEMS FREE )
exten => s,n,Park(,from-internal,6000,s)
exten => s,n(letsgo),Noop(
HIDDENVISION ALL SET NOW ***)
exten => s,n,Hangup
exten => s,n,MacroExit()

6000 being the return ring group,
10 being the parking lot,
11 being the slot.!
That “,s” is silent.

Tie that in with the call to the macro and the cron job to keep freepbx in check an
No anouncments, no default behaviour.!

No doubt some things I have not thought of yet but the process works very well.
Simple auto dropping of calls from a que into a Parking slot to make the BLF lamp flash.
For those with limited BLF buttons this is a handy trick.
No doubt someone is going to come along with a simple *code to do what I need.!

Actually I have noticed that the call is lost at the end of the parking timeout if ALL agents in the timeout destination ring group are busy, going to have to see why it is not pushing to voicemail.

Hv.

Hey Dicko.
Well I had a read of Stop Freepbx from resetting configurations file

Seems harmless enough although I would then have to keep an eye out for other things.
Ahh the Cron does the job as ugly as it seems.

Guessing the people that edit the parking module would not be reading this and consider making the Silent option available and perhaps add in a destination if all slots busy.

Hv.

As always.!
if you are venturing down this path then it will be handy to know the things I noticed.

All working peachy so far with one exception.

Calls that drop out of the parking lot due to timeout should not be pointed towards things that could all show busy or unavailable.

The parking lot will simply terminate the call if it cannot hand the call off to its’ timeout destination.

To resolve this I setup another Queue to take the “parking timeout” calls.
Just replace the 6000 in the Park() function above with the new Queue number.
I then added static agents to that queue.
But guess they could also be Ring groups as static agents.?

The queue is smart enough to hold the call till someone is free,
OR if that finally times out then pass the call off to another destination
or perhaps conference a call to a pitza delivery firm if they have been waiting that long.
Voicemail seemed an option.

I am still tinkering with this script so I may update it here if desired or I shall do it anyway once I finally nail it.

Hv.

Oh, I requested an Improvement, to add the Silent option into the parking module.
On-track for V14 from what I read.
Perhaps the Full and Busy exit destination parts will also be enhanced.

Hv.