Balancing outgoing calls through a GSM gateway
To make an outgoing call, it is usually used to sort through the sim cards in order, until there is a free one:
exten => _X.,n,Dial(SIP/gsm1/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm2/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm3/${EXTEN},,tT)etc.
In this case, most of the calls go through the first SIM card, and least of all through the last. Therefore, by the middle of the month, the minutes on the first SIM cards end earlier than on the last, and a situation arises when you can call after 4 SIM cards out of 8, since the first four minutes have ended. This is bad, because there are 4 outgoing lines instead of 8.
To avoid this, you need to make calls not in the same order, but in accordance with the remaining minutes on the SIM cards.
Along the way, I write down the remaining minutes, the relevance (what time the leftovers were checked), and when the package was activated in the MySQL database.
You can go to the page and quickly find out the rest:
To check the balances, you need to enable the API on the gateway, for this we go to the SMS section, then to the API settings. Everything is clear there, you need to set a login with a password and an allowed subnet for connection.
We will check the balances every hour, for this we will add a script call to the crowns (I have every 53rd minute of the hour):
53 */1 * * * root php %path-to-script%/getbalance.phpNext, we need to create 8 text files (or how many SIM cards you use) with names from nc2.txt to nc9.txt. These numbers are because the gateway numbers its ports in exactly this way, from 2 to 9.
In each command file, the gateway. Example for nc2.txt:
action: login
username: ******
secret: *******
action: smscommand
command: gsm send ussd 2 *255*0#
action: logoffAn example is given for Tele2. Accordingly, in the file nc3.txt instead of “ussd 2” we write “ussd 3”. The script passes these commands to the gateway, in response we get files with names from nc2out.txt to nc9out.txt.
The answer will be like this (for Tele2):
Asterisk Call Manager/1.1
Response: Success
Message: Authentication accepted
Response: Follows
Privilege: SMSCommand
1:Received USSD success on span: 2
USSD Responses: 2
USSD Code: 64
USSD Len: 85
USSD Message: Ostatok v pakete: 968 min./mes., 5000 SMS/mes., 20480 MB/mes. Parametry' tarifa *107#
--END COMMAND--
Response: Goodbye
Message: Thanks for all the fish.Clarification: you need to switch the operator’s answers to transliteration, otherwise we get the text in an inconvenient encoding.
Then we pull out the number of remaining minutes, sort and write the order of the call into files from out1.txt to out8.txt (this is already for the asterisk, so the numbering is normal). That is, if the call order turned out to be 5, 4, 3, 2, 1, 7, 8, 6, then in the out1.txt file we write the number 5, in the out2.txt file we write 4, etc. It
remains to read these in the dialplan files and make calls in the correct order:
exten => _X.,n,set(SIMNUM1=${SHELL(/usr/bin/php -f %pathtoscript%/getsim1.php)})
exten => _X.,n,set(SIMNUM2=${SHELL(/usr/bin/php -f %pathtoscript%/getsim2.php)})
exten => _X.,n,set(SIMNUM3=${SHELL(/usr/bin/php -f %pathtoscript%/getsim3.php)})
exten => _X.,n,set(SIMNUM4=${SHELL(/usr/bin/php -f %pathtoscript%/getsim4.php)})
exten => _X.,n,set(SIMNUM5=${SHELL(/usr/bin/php -f %pathtoscript%/getsim5.php)})
exten => _X.,n,set(SIMNUM6=${SHELL(/usr/bin/php -f %pathtoscript%/getsim6.php)})
exten => _X.,n,set(SIMNUM7=${SHELL(/usr/bin/php -f %pathtoscript%/getsim7.php)})
exten => _X.,n,set(SIMNUM8=${SHELL(/usr/bin/php -f %pathtoscript%/getsim8.php)})
exten => _X.,n,Dial(SIP/gsm${SIMNUM1}/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm${SIMNUM2}/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm${SIMNUM3}/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm${SIMNUM4}/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm${SIMNUM5}/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm${SIMNUM6}/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm${SIMNUM7}/${EXTEN},,tT)
exten => _X.,n,Dial(SIP/gsm${SIMNUM8}/${EXTEN},,tT)Yes, I almost forgot, getsim1.php file:
Now the main script getbalance.php itself.
Take the IP of the gateway 10.10.1.1.
I know that you need to make a cycle instead of copy-paste, but I am guided by the golden rule of the admin: it works - do not touch :-)
10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc2.txt > %pathtoscript%/nc2out.txt');
$text = file_get_contents('%pathtoscript%/nc2out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text2 = $matches[1]; else goto a2;
$s=0;
a3:
$s++;
if ($s>10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc3.txt > %pathtoscript%/nc3out.txt');
$text = file_get_contents('%pathtoscript%/nc3out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text3 = $matches[1]; else goto a3;
$s=0;
a4:
$s++;
if ($s>10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc4.txt > %pathtoscript%/nc4out.txt');
$text = file_get_contents('%pathtoscript%/nc4out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text4 = $matches[1]; else goto a4;
$s=0;
a5:
$s++;
if ($s>10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc5.txt > %pathtoscript%/nc5out.txt');
$text = file_get_contents('%pathtoscript%/nc5out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text5 = $matches[1]; else goto a5;
$s=0;
a6:
$s++;
if ($s>10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc6.txt > %pathtoscript%/nc6out.txt');
$text = file_get_contents('%pathtoscript%/nc6out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text6 = $matches[1]; else goto a6;
$s=0;
a7:
$s++;
if ($s>10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc7.txt > %pathtoscript%/nc7out.txt');
$text = file_get_contents('%pathtoscript%/nc7out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text7 = $matches[1]; else goto a7;
$s=0;
a8:
$s++;
if ($s>10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc8.txt > %pathtoscript%/nc8out.txt');
$text = file_get_contents('%pathtoscript%/nc8out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text8 = $matches[1]; else goto a8;
$s=0;
a9:
$s++;
if ($s>10) exit;
system('nc 10.10.1.1 5038 < %pathtoscript%/nc9.txt > %pathtoscript%/nc9out.txt');
$text = file_get_contents('%pathtoscript%/nc9out.txt');
if(preg_match('/te:\ (.*)\ min/',$text,$matches)) $text9 = $matches[1]; else goto a9;
$text10 = "0";
system('echo "'.date('l dS F Y h:i:s A').' '.$text2.' '.$text3.' '.$text4.' '.$text5.' '.$text6.' '.$text7.' '.$text8.' '.$text9.'" >>%pathtoscript%/balance.txt');
$row = mysql_query("select minutes from `lines` where clid like '%2636'",$link);
$row1 = mysql_fetch_assoc($row);
$old1 = $row1['minutes']+0;
$new1 = $text2+0;
if ($old1 < $new1) $row = mysql_query("update `lines` set balancedate=NOW()",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text2." where clid like '%2636'",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text3." where clid like '%4036'",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text4." where clid like '%4977'",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text5." where clid like '%2414'",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text6." where clid like '%2451'",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text7." where clid like '%2536'",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text8." where clid like '%2581'",$link);
$row = mysql_query("update `lines` set balance=".$text10.", minutesdate=NOW(), minutes=".$text9." where clid like '%4056'",$link);
$n[1] = $text2+0;
$n[2] = $text3+0;
$n[3] = $text4+0;
$n[4] = $text5+0;
$n[5] = $text6+0;
$n[6] = $text7+0;
$n[7] = $text8+0;
$n[8] = $text9+0;
$p[1] = 1;
$p[2] = 2;
$p[3] = 3;
$p[4] = 4;
$p[5] = 5;
$p[6] = 6;
$p[7] = 7;
$p[8] = 8;
for($i=1;$i<=7;$i++) for($j=$i+1;$j<=8;$j++)
if ($n[$i]<$n[$j])
{
$t = $n[$i];
$n[$i] = $n[$j];
$n[$j] = $t;
$t = $p[$i];
$p[$i] = $p[$j];
$p[$j] = $t;
}
system('echo "'.$p[1].'" >%pathtoscript%/out1.txt');
system('echo "'.$p[2].'" >%pathtoscript%/out2.txt');
system('echo "'.$p[3].'" >%pathtoscript%/out3.txt');
system('echo "'.$p[4].'" >%pathtoscript%/out4.txt');
system('echo "'.$p[5].'" >%pathtoscript%/out5.txt');
system('echo "'.$p[6].'" >%pathtoscript%/out6.txt');
system('echo "'.$p[7].'" >%pathtoscript%/out7.txt');
system('echo "'.$p[8].'" >%pathtoscript%/out8.txt');
system('asterisk -rx "dialplan reload"');
?>
The contents of lib.php (there is a connection to MySQL):
A little more explanation.
On each SIM card, 10 attempts are made to check the balance (this is not always possible), if at least one of them fails, we exit and try in an hour.
Why text10 = "0"? Previously, MTS SIM cards were used, which returned the balance (in rubles). In Tele2, we use a common account, we don’t put money on specific
SIM cards, so there is always 0. Balances are also added to the balance.txt file so that you can see the history and calculate the statistics of expenses.
Who cares how not to lose an incoming call to a SIM card, if they already speak on it, ask in the comments (it doesn’t pull on an article).
Thanks for attention!