Не секрет, что есть условно бесплатные (3000 минут) SIM-карты и если превысить их лимит, оператор может узнать, что используется gsm-шлюз. Представленный скрипт распределяет нагрузку и не звонит при превышении лимита по транку. Список разрешенных кодов задается в файле в /usr/share/asterisk/agi-bin/cods.txt#!/usr/bin/perl
# load module
use Asterisk::AGI;
use DBI;
#use date::Format;# connect
my $dbh = DBI->connect("DBI:Pg:dbname=asterisk;host=127.0.0.1", "asterisk_user", "passwd", {'RaiseError' => 1});
my %trunks=("name1" => "SIP/994",
"name2" => "SIP/993",
"name3" => "SIP/992",
"name4" => "SIP/991"); #89839my %trunks_id=("name1" => "994",
"name2" => "993",
"name3" => "992",
"name4" => "991");my $Default_trunk="SIP/63762xx";
my $Default_trunk_id="63762xx";my %calls=();
my @calls_order=();my $LIMIT=2000*60;
my $min=$LIMIT;
my $min_trunk="name1";foreach $trunk (keys(%trunks)){
my $sth = $dbh->prepare("SELECT sum(billsec) AS calltime FROM cdr WHERE
date_trunc('month',calldate) = date_trunc('month',now()) AND dstchannel LIKE '$trunks{$trunk}-%' ;");
$sth->execute();while(my $ref = $sth->fetchrow_hashref()) {
if($ref->{'calltime'} < $LIMIT){
$calls{$trunk}=$ref->{'calltime'};
if ($min > $ref->{'calltime'} ){
$min=$ref->{'calltime'};
$min_trunk=$trunk;
}
}
if(not $ref){
$calls{$trunk}=0;
}
}#end while
}$dbh->disconnect();
#@calls_order = sort { $calls{$b} cmp $calls{$a} } keys %calls;
@calls_order = sort { $calls{$a} <=> $calls{$b} } keys %calls;
#foreach $trunk (@calls_order){
# print "$trunk = $calls{$trunk}\n";
# $AGI->verbose("$trunk = $calls{$trunk}\n",3);
#}
#print "min $min_trunk\n";
#$AGI->verbose("min $min_trunk\n",3);
$|=1;
my $AGI = new Asterisk::AGI;
$AGI->setcallback(\&mycallback);
my %input = $AGI->ReadParse();
sleep(1);
my $num = $input{'extension'};
my $caller_id = $input{'callerid'};
if (!$num) {
exit;
}
my $num1 = substr($num,1,6);
my $syscmd1=`perl -ne "print if m/$num1/" /usr/share/asterisk/agi-bin/cods.txt`;
chomp($syscmd1);
if($syscmd1==0){
$AGI->exec('Playback', "/var/lib/asterisk/sounds/record/blocked_call");
exit;
}
my $use_default=1;
#$AGI->stream_file("/var/lib/asterisk/sounds/record/limit_call","*");
$AGI->exec('Playback', "/var/lib/asterisk/sounds/record/limit_call");$AGI->verbose("Executing Dial $num $num1 $caller_id $syscmd1 \n",3);
foreach $trunk (@calls_order){
$AGI->set_callerid($trunks_id{$trunk});
my $syscmd=`asterisk -r -x "core show channels" | grep "$trunks{$trunk}"| wc -l`;
chomp($syscmd);
if($syscmd==0){
#$AGI->verbose("????? Status $trunks{$trunk} '$ret' '$status'\n",3);
# my $ret=$AGI->exec('Dial', "$trunks{$trunk}/$num");my $ret=$AGI->exec('Dial', "$trunks{$trunk}/$num|120|L(191664)");
my $status=$AGI->channel_status();
if( ($status==0 || $status==1) && $ret!=1 ){
$AGI->verbose("????? OK! $caller_id $num ret=$ret status=$status syscmd=$syscmd\n",3);
$use_default=0;
last;
}else{
$AGI->verbose("????????? error $caller_id $num $trunks{$trunk}/$num '$ret' status=$status syscmd=$syscmd \n",3);
}
}
}if($use_default==1){
$AGI->set_callerid($Default_trunk_id);
my $ret=$AGI->exec('Dial', "$Default_trunk/$num");
$AGI->verbose("????????? error_Default_trunk $caller_id $num $Default_trunk/$num ret=$ret \n",3);
}sleep(1);
exit;sub mycallback {
my ($returncode) = @_;
&log("CALLBACK");
&cleanup;
#print STDERR "User Disconnected ($returncode)\n";
$AGI->verbose("!!!!!!!!!! ($returncode)\n");
exit($returncode);
}URL: http://ink-08.blogspot.com/2010/07/asterisk.html
Обсуждается: http://www.opennet.me/tips/info/2414.shtml
полезно, спасибо
обычно при привышении лимита просто оплата появляется(в Украине). Но скрипт действительно полезен. спасибо.
Может кому пригодится мое простенькое решение для asterisk+freepbx, которое выключает транк при превышении заданного порога минут и включает его в новом месяце:1. делаем скрипт /usr/local/bin/watch-trunk.sh (не забываем заменить ИМЯ_ТРАНКА, ИД_ТРАНКА и КОЛ-ВО_МИНУТ):
#!/bin/bash
USER=`cat /etc/asterisk/cdr_mysql.conf | grep -Pi "^user *=" | cut -d = -f 2 | sed 's# ##g'`
PASSWD=`cat /etc/asterisk/cdr_mysql.conf | grep -Pi "^password *=" | cut -d = -f 2 | sed 's# ##g'`
HOST=`cat /etc/asterisk/cdr_mysql.conf | grep -Pi "^hostname *=" | cut -d = -f 2 | sed 's# ##g'`
DB=`cat /etc/asterisk/cdr_mysql.conf | grep -Pi "^dbname *=" | cut -d = -f 2 | sed 's# ##g'`COUNT=`mysql -h${HOST} -u${USER} -p${PASSWD} ${DB} -N -B -e \
"select round(sum(duration/60)) from cdr where dstchannel like '%ИМЯ_ТРАНКА%' and calldate > date_format(now(),'%Y-%m')"`if [ "${COUNT}" = 'NULL' ] ; then COUNT=0 ; fi
if [ "${COUNT}" -gt КОЛ-ВО_МИНУТ ] ; then
/usr/sbin/rasterisk -x "database put TRUNK ИМЯ_ТРАНКА 0" >/dev/null
else
/usr/sbin/rasterisk -x "database put TRUNK ИМЯ_ТРАНКА 1" >/dev/null
fi2. добавляем в /etc/asterisk/extensions_override_freepbx.conf следующий блок:
[macro-dialout-trunk-predial-hook]
exten => s,1,ExecIf($[$["${DB(TRUNK/ИМЯ_ТРАНКА)}" = "0"] & $["${DIAL_TRUNK}" = "ИД_ТРАНКА"]]?Set(PREDIAL_HOOK_RET="BYPASS"))
exten => s,n,MacroExit()3. Добавляем запись в кронтаб:
*/10 * * * * /usr/local/bin/watch-trunk.sh
Могу поделиться своим расширением на эту тему под a2billing
http://www.asterisk2billing.org/cgi-bin/trac.cgi/ticket/869
Абсолютно индивидуально настраивается каждый транк вплоть до количества посекунд тарификации, времени действия, смены и периодичности тарифа, а так же переход к следующему транку по условию. Пожелания приветствуются на e-mail.
Новая ссылка https://github.com/nixonch/a2billing/downloads