Asterisk conditional call routing


I have Asterisk running with an X100P and a SIP account with a provider.
My PSTN provider gives me some “free” minutes for outgoing calls every month, but after i’m out of those, they charge me quite a lot for calls.
What I’d like is to setup Asterisk so that it keeps track of total outgoing call time on Zap channel, and after I reach the “free minutes” limit it routes all calls through SIP channel.
Is this even remotely possible? Any ideas appreciated.


You can store CDR in database.
When You make a call, first run AGI script that will
count duration of calls in current month on zap line,
then choose desired channel.

Since I’ve been asked if I found a solution to this problem, and I did :smile:, I thought I may post it here, in case somebody else is looking for something similar.

It is not 100% accurate since it doesn’t take some free numbers into account. Also, Polish Telecom does not send 16kHz signals on consumer phone lines, nor does it invert polarity, so asterisk does not know when the call is answered, and billing starts straight after dialing. Nevertheless, it does the job reasonably good. I haven’t had time to work on it more, but i’m sure it can be improved.

What I did was a simple perl script that queries the database and prints one of two strings into standard out:

#!/usr/bin/perl -w

use Mysql;
use strict;

my $host = “localhost”;
my $db = “asteriskcdrdb”;
my $user = “xxxxxx”;
my $pw = “xxxxxxx”;

my $mins_used;
my $free_mins = 70;

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
my $month = sprintf ("%02d", $mon+1);

my $connect = Mysql->connect($host, $db, $user, $pw);

THIS is the query that actually does the job of counting used minutes in current month:

my $myquery = “select sum(billsec) from cdr where dstchannel like 'Zap%'
and calldate like '%-”.$month."-%’ and dst not like '0800%'
and dst not like ‘0800%’";

my $execute = $connect->query($myquery);

SINCE billed time in database is in seconds, it has to be rounded to minutes:

while (my @results = $execute->fetchrow()) {
$mins_used = int ($results[0]/60+0.5);

START printing command for asterisk

print "SET PRIORITY ";

if ($mins_used < $free_mins) {

print 11;

} else {

print 21;


In extensions.conf I put something like this:

exten => _0ZXZXXXXXX,1,Agi(above_script)
exten => _0ZXZXXXXXX,11,Dial(Zap/1/${EXTEN})
exten => _0ZXZXXXXXX,21,Dial(SIP/${EXTEN}@ipfon)

So if I used less than 70 minutes, asterisk jumps to priority 11 and connects the call using analog phoneline,
else it jumps to priority 21 and connects via my sip provider.

You may have to rethink the way of counting minutes in current billing month - my task was easy because billing month starts exactly on the 1st day of calendar month.

I know it’s not a clean solution, but I hope it may help someone.