Least Busy Trunk Hunting

I would like to be able to select the least busy outgoing trunk from a group of outgoing trunks for each outgoing call. Reason for this is I can buy individual trunks each with a bundle of outgoing minutes from my Telco so I need to be able to spread my outgoing calling as evenly as possible over the entire group rather than having the first trunk take most of the load.

Any ideas please?

I found this post:


It works fine. I am working on enhancing it by accessing from macro-dialout-trunk-predial-hook rather than in the way described here. That way I should be able to use the Dial Patterns in Outbound Routes rather than having to hard code them.

It would be really nice to be able to select selection sequence in Outbound Route setup rather than having to add code like this.

I was already using the macro-dialout-trunk-predial-hook to jump out of
macro-dialout-trunk and insert a Progress Announcement on calls being routed out on GSM Cellphone Trunks, so I decided to try and add the Trunk Rotary Hunting facility by using the same route.

I used gbrook’s code posted in the Trixbox forum as the nuts and bolts and came up with the following macro which so far seems to be performing exactly as I want it to:

; This macro does two things (1) recognises Portech GSM Gateway trunks and inserts a call progress
; announcement (2) recognises calls to trunk groups where each trunk has a separate pool of free
; minutes and alternates outbound calls between trunks to approximately equalize usage across
; all the trunks in the group.
; To insert the Progress Announcement edit line 1 to accommodate the trunk name and for Alternating
; Trunk Selection edit line 2 to accommodate the base name of the trunk group and it is necessary
; to setup trunks in the Web GUI bearing the trunk group base name plus sequential line numbers like
; XXXXXXXXXX_1, XXXXXXXXXX_2 etc. It is necessary to edit the variable NUMBER_TRUNKS to the
; actual number of trunks in the group. Access to the trunk group is through an Outbound Route
; set up in the Web GUI.
exten => s,1,Gotoif($["${OUT_${DIAL_TRUNK}:0:7}" = “SIP/700”]?callprogress)
exten => s,n,Set(TRUNK_GROUP=${OUT_${DIAL_TRUNK}:0:15})
exten => s,n,Gotoif($["${TRUNK_GROUP}" = “IAX2/XXXXXXXXXX”]?rotaryhunting)
exten => s,n,MacroExit()
exten => s,n,NoOp(Start Call Progress - Using trunk: ${OUT_${DIAL_TRUNK}} Caller: ${REALCALLERIDNUM})
exten => s,n(callprogress),NoOp(Playing Progress Announcement)
exten => s,n,Playback(custom/cell-phone-please-wait,noanswer)
exten => s,n,MacroExit()
exten => s,n(rotaryhunting),NoOp(Start Alternating Hunt - Using group: ${TRUNK_GROUP} Caller: ${REALCALLERIDNUM})
exten => s,n,Set(NUMBER_TRUNKS=2)
exten => s,n(loop),SetGlobalVar(NEXTLINE=$[${NEXTLINE} + 1])
exten => s,n,Gotoif($[${NEXTLINE} <= ${NUMBER_TRUNKS}]?noreset)
exten => s,n,SetGlobalVar(NEXTLINE=1)
exten => s,n(noreset),Dial(${TRUNK_GROUP}_${NEXTLINE}/${OUTNUM},300,${DIAL_TRUNK_OPTIONS})
exten => s,n,NoOp(Trunk busy retrying)
exten => s,n,Set(NUMBER_TRUNKS=$[${NUMBER_TRUNKS} - 1])
exten => s,n,NoOp(Tries left: ${NUMBER_TRUNKS})
exten => s,n,GotoIf($[${NUMBER_TRUNKS} > 0]?loop)
exten => s,n,NoOp(Run out of trunks)
exten => s,n,Playback(all-circuits-busy-now,noanswer)
exten => s,n,NoOp(Exiting Alternating Hunt)
exten => s,n,Macro(hangupcall,)
exten => h,1,Macro(hangupcall,)
; end macro-dialout-trunk-predial-hook

Hope this may be of help. As an aside I have posted a feature request to add outgoing trunk hunting methods to the Outbound Route module.

I would like to try this, however, I am not sure where to add them, do I need to add this inside extensions.conf under the same context [macro-dialout-trunk-predial-hook] or do i have to put it somewhere like extensions_customs.conf or in extensions_override_freepbx.conf? And which lines do I need to edit if I am going to use it to “rotary hunt” the SIP trunks that is on the outbound routes since the code that you made is primarily for Portech GSM gateway? I am using pbxinaflash. Thank you.

I just wanna know if anyone aside of course from stonet, have tried using this? Perhaps you can post your macro-dialout-trunk-predial-hook. I would like to know which part of line1 and line2 that I need to edit so that it will work. Thank you.

I’ve written a Freepbx module to do this. You can have a look here to download it:

It still an alpha release right now, but I have it on two production PBX with Freepbx 2.6 without any problem. The main enhancement for the full release will be focused on a nicer user interface.

Thank you.

I did install the module, however I can’t make it to work like all 4 trunks will received the same number of calls but limited to 90 minutes of call everyday. This is what I did:
I set the ratio of the 4 trunks from 4 to 2, - this one i see that it is working, however when I put the number of minutes which is 90 for each of the four trunks, I can not dial out, all trunks are busy, so I tried to extend the number of minutes to a certain number and it did work. My question now is, how am I going to configure the trunks so that each would received a balance number of outgoing calls but each would only dial out for max of 90 minutes a day? Thank you.

You should create four trunks:
1st one: ratio 4 (will take one out of 4 calls), billing period 1(will reset the counter every 1 day), maximum time 90

2nd one: same as one but with ratio to 3
3rd one: same as one but with ratio to 2
4th: same as one but with no ratio (ie 1)

in your outbound route put these 4 balanced trunks in order, then don’t forget to add some backup trunk in case all the minutes are used.

Thanks very much.

check that you have the 0.3.2 version, as the floating billing period is an option that I added last January, after the 0.3 release.

i’ve written this working (but surely bugged) dialplan in order to realize a trunk balance between 2 sip trunk (portech dual gsm gateway)

exten => s,1,Set(TRUNKNUM1=1)
exten => s,n,Set(TRUNKNUM2=3)
exten => s,n,GotoIf($[$["${DIAL_TRUNK}" != “${TRUNKNUM1}”] & $["${DIAL_TRUNK}" != “${TRUNKNUM2}”]]?skipbal,1)
exten => s,n,GotoIf($[ ${GROUP_COUNT(OUT_${TRUNKNUM1})} >= ${OUTMAXCHANS_${TRUNKNUM1}} ]?set2,1)
exten => s,n,GotoIf($[ ${GROUP_COUNT(OUT_${TRUNKNUM2})} >= ${OUTMAXCHANS_${TRUNKNUM2}} ]?set1,1)
exten => s,n,Set(TRUNKNAME1=SIP/gsm1)
exten => s,n,Set(TRUNKNAME2=SIP/gsm2)
exten => s,n,MYSQL(Connect MYCONNID localhost root passw0rd asteriskcdrdb)
exten => s,n,GotoIf($["${MYCONNID}" = “”]?baldberror,1))=YEAR(calldate)\ AND\ MONTH(CURDATE())=MONTH(calldate))
exten => s,n,MYSQL(Fetch MYFETCHID ${RESULT1} SECST1)
exten => s,n,MYSQL(Clear ${RESULT1}))=YEAR(calldate)\ AND\ MONTH(CURDATE())=MONTH(calldate))
exten => s,n,MYSQL(Fetch MYFETCHID ${RESULT2} SECST2)
exten => s,n,MYSQL(Clear ${RESULT2})
exten => s,n,MYSQL(Disconnect ${MYCONNID})
exten => s,n,Noop(T1=${SECST1} T2=${SECST2})
exten => s,n,GotoIf($[0${SECST1} > 0${SECST2}]?settrunk:skipbal,1)
exten => s,n(settrunk),Set(DIAL_TRUNK=${TRUNKNUM2})
exten => skipbal,1,Noop(Salto il bilanciamento)
exten => skipbal,n,MacroExit()
exten => baldberror,1,Noop(Connessione db fallita)
exten => set1,1,Set(DIAL_TRUNK=${TRUNKNUM1})
exten => set1,n,MacroExit()
exten => set2,1,Set(DIAL_TRUNK=${TRUNKNUM2})
exten => set2,n,MacroExit()

After upgrading from 0.3 to 0.3.2, the page of the Trunk Balance module in Freepbx GUI is blank (empty). I did it to 3 servers and both have the same problem after upgrading. For the time being I reverted back to 0.3. Are there any steps that I need to do first before upgrading to 0.3.2? Thank you.
P.S. I tried registering on the site where the project is hosted so that I could post the result of my tests, however until now I still could not log-in.

You are the first one to report a problem with the upgrade.
I’ve tried again on my system and it worked ok.

Could you try to give me more info about what is happening with 3.2. Could you check your httpd log? is there any error? If you look at your folder for 3.0 and 3.2 is there a difference in the files present? There should be the same numbers.

Below are the files and the error log for httpd.
Ver. 0.0.3
drwxr-xr-x 2 asterisk asterisk 4096 Dec 1 2009 agi-bin
-rw-r–r-- 1 asterisk asterisk 4198 Dec 8 2009 functions.inc.php
-rw-r–r-- 1 asterisk asterisk 865 Dec 1 2009 install.php
-rw-r–r-- 1 asterisk asterisk 818 Dec 8 2009 module.xml
-rw-r–r-- 1 asterisk asterisk 8783 Dec 8 2009 page.trunkbalance.php
-rw-r–r-- 1 asterisk asterisk 373 Dec 1 2009 readme.txt
-rw-r–r-- 1 asterisk asterisk 681 Dec 2 2009 uninstall.php

drwxr-xr-x 2 asterisk asterisk 4096 Dec 1 2009 agi-bin
-rw-r–r-- 1 asterisk asterisk 4388 Jan 16 20:13 functions.inc.php
-rw-r–r-- 1 asterisk asterisk 2695 Jan 16 22:02 install.php
-rw-r–r-- 1 asterisk asterisk 872 Jan 16 22:03 module.xml
-rw-r–r-- 1 asterisk asterisk 9349 Jan 16 20:32 page.trunkbalance.php
-rw-r–r-- 1 asterisk asterisk 373 Dec 1 2009 readme.txt
-rw-r–r-- 1 asterisk asterisk 681 Dec 2 2009 uninstall.php

Here is the error log:
[Fri Jul 16 23:48:21 2010] [error] [client] PHP Fatal error: Call to undefined function xml2array() in /var/www/html/admin/modules/trunkbalance/page.trunkbalance.php on line 5, referer:

I commented out line number 5 and it is no more a blank page. I compared it with version 0.0.3, there is no line 5 in the older version. I hope that my thought of removing line number would not defeat the purpose of upgrading to version

Thanks for your debug, I did not have this issue on my systems.
This line is just cosmetic and can be removed without harm.

I’ve uploaded your change as rev

Your request has been coded in version 0.0.4 available now for download and testing at


excellent suggestion. I’ll try to work on it.

For the feedback and request, the best is to go on the http://projects.colsolgrp.net/projects/trunkbalance
website, log in and create a new bug/feature request.


I’m wondering how and where to send a feature request on this project? Anyways I will post it here and hopefully you can redirect me where to a post properly a feature request.
Feature Request:
An option to enable/disable the trunk based on time of the day. For example: A particular trunk would only accept a call every 5PM till 12 PM then at around 4AM to 8 AM everyday. This is especially good for GSM trunk since there are plans that you can only make a unlimited call on a certain time everyday. Thank you.

Any comments on your module for my application is greately appriciated.

We are hoping to have multiple Sip trunks and to be able to dial predefined usage(minutes)on each.
So we can have a even mix of calls on each.
But to also randomly select each sip trunk regardless of outbound routing assignment.
So to add if a sip trunk has reached its limit it moves to the next available
trunk that has capacity.
But if all has reached their limit 503 congestion.