Сопряжение BG-биллинга и Городской цифровой АТС MC240 и Цифрового шлюза SMG-1016M производства Элтекс

Материал из BiTel WiKi

Перейти к: навигация, поиск

Нами в 2010 году была приобретена городская цифровая АТС MC-240 производства Eltex. Данная АТС удовлетворяет всем нормам законодательства в области связи, имеет все сертификаты, и даже что не мало важно СОРМ! Стандартно АТС ведёт логи в бинарном виде на свей флешке и никак иначе, что кстати с моей точки зрения большая проблема. Разработчик предусмотрел возможность для доступа к АТС через telnet. Поэтому нами были написаны скрипт на perl'е export.pl который забирает со станции файл с бинарным CDR по протоколу tftp, скармливает его бинарному конвертору bin2bg, полученный результат зипуется (zip) и ложится куда нужно биллингу. Разработчиком был нам предоставлен штатный бинарный конвертер который мы модифицировали (bin2bg), что бы вывод был нужного для биллинга формата. Нужно отдельно отметить одну не маловажную особенность и очень не приятную кстати: так как команда на скачивание файлов передаётся через телнет, важно чтобы на станции в этот момент не было активных админских телнет сессий, так как телнет сессия открывается всего одна, и если сессия всёаки кем то открыта, скрипт доступа к станции не получит! Содержимое export.pl

  1. !/usr/bin/perl

use Socket;

  1. use strict;
  2. use warnings;

use Cwd;

  1. version 1.0.0
  1. ========================Настройки==========================

our $subject="WARNING!!! ATS CONVERTATION LOG ERROR!!!"; our $mail_address='admin@sp-com.ru';

our $host="10.9.0.6"; our $port="23"; our $password="telemetry";

our $converter="/usr/local/BGBillingServer/scripts/bin2bg"; our $redirect="/usr/local/BGBillingServer/scripts/redirect.db"; our $export_dir="/usr/local/BGBillingServer/Phone"; our $input_dir="/usr/local/BGBillingServer/tftp/billing"; our $zip="/usr/local/bin/zip"; our $unzip="/usr/local/bin/unzip"; our $rm="/bin/rm"; our $cp="/bin/cp"; our $tmpfile="/tmp/export.tm"; our $log_file="/usr/local/logs/export.log"; our $ats_delay=10;

  1. ======================основная программа===================

$SIG{PIPE}="epipe_handler"; socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')); my $ipaddr=inet_aton($host); my $paddr=sockaddr_in($port,$ipaddr); my @data;

  1. if ($#ARGV < 1){
  2. print "Too few arg\n";
  3. print "Usage: export.pl input_dir export_dir\n";
  4. exit 0;
  5. }
  1. Соединяемся

connect(SOCK,$paddr) || send_alarm ("Connect ERROR-1\n"); send(SOCK,"\r\n",0);

  1. Вводим пароль

send(SOCK,"$password\r\n",0); send(SOCK,"trace off\r\n",0);

  1. Проверяем наличие billing.bak

send(SOCK,"ls \r\n",0); send(SOCK,"logout\r\n",0);

@data=<SOCK>; close (SOCK);

my $file_present=0; foreach my $lin (@data){

  if ($lin =~ /.*billing\.bak.*/){
     $file_present=1;
  }

}

  1. Если файл найден, то оскачиваем его

if ($file_present){

  print "Старый файл лога billing.bak найден\n";
  socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
  connect(SOCK,$paddr) || send_alarm("Connect ERROR-2\n");
  send(SOCK,"\r\n",0);
  #Вводим пароль
  send(SOCK,"$password\r\n",0);
  send(SOCK,"mv billing.bak $mday-$mon-$hour.bak\r\n",0);
  send(SOCK,"tftp p $mday-$mon-$hour.bak /billing/billing.bak\r\n",0);
  #Задержка перед отправкой logout
  sleep($ats_delay);
  send(SOCK,"trace ss7isup\r\n",0);
  send(SOCK,"trace call l30\r\n",0);
  send(SOCK,"logout\r\n",0);
  @data=<SOCK>;
  close (SOCK);
  #print @data;
  #Ищем признак успешной отправки файла
  my $send_OK=0;
  foreach my $lin (@data){
          if ($lin =~ /^\[TFTP\] Uploaded/){
               $send_OK=1;
          }
          #Если файл был пустой
          if ($lin =~ /^\[TFTP\] Client stop, code 0, err 0/){
                  $send_OK=1;
          }
  }
 #При успешной отправке  удаляем файл журнала
 if ($send_OK){
    remove_and_process();
 }
 #При НЕ успешной отправке выводим лог общения с сервером
 else {
     send_alarm("File send ERROR-3\n");
     print "File send ERROR-3 !!\n";
     print "Log:\n";
     print @data;
     exit -1;
 }

}

  1. Формируем и скачиваем новый файл

socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp')); connect(SOCK,$paddr) || send_alarm("Connect ERROR-4\n"); send(SOCK,"\r\n",0);

  1. Вводим пароль

send(SOCK,"$password\r\n",0); send(SOCK,"trace off\r\n",0); send(SOCK,"sysrename\r\n",0); print("Rename billing.bin to billing.bak\n"); send(SOCK,"mv billing.bak $mday-$mon-$hour.bak\r\n",0); send(SOCK,"tftp p $mday-$mon-$hour.bak /billing/billing.bak\r\n",0);

  1. Задержка перед отправкой logout

sleep($ats_delay); send(SOCK,"trace call l30\r\n",0); send(SOCK,"trace ss7isup\r\n",0); send(SOCK,"logout\r\n",0); @data=<SOCK>; close (SOCK);

  1. print @data;
  2. Ищем признак успешной отправки файла

my $send_OK=0; foreach my $lin (@data){

  if ($lin =~ /^\[TFTP\] Uploaded/){
     $send_OK=1;
  }
  #Если файл был пустой
  if ($lin =~ /^\[TFTP\] Client stop, code 0, err 0/){
      $send_OK=1;
  }

}

  1. При успешной отправке удаляем файл журнала

if ($send_OK){

  remove_and_process();

}

  1. При НЕ успешной отправке выводим лог общения с сервером

else {

  send_alarm("File send ERROOR-5\n");
  print "File send ERROR-5 !!\n";
  print "Log:\n";
  print @data;
  exit -1;

}

exit 0;


  1. ===========================Функции==================================
  1. Послать письмо с сообщением об ошибке

sub send_alarm{

 my($message)=$_[0];
 print "ERROR: $message\n";
 system ("/bin/echo \"$message\"|/usr/bin/mail -s \"$subject\" $mail_address");
 exit -1;

}

  1. Послать письмо с сообщением об ошибке

sub send_alarm_noexit{

 my($message)=$_[0];
 print "ERROR: $message\n";
 system ("/bin/echo \"$message\"|/usr/bin/mail -s \"$subject\" $mail_address");

}

  1. Удалить billing.bak c АТС сконвертировать и заархивировать его на компе

sub remove_and_process{

  print "TFTP put file  successful\n";
  print "Now remove billing.bak file form ATC\n";
  socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
  connect(SOCK,$paddr) || send_alarm("Connect ERROR-6\n");
  send(SOCK,"\r\n",0);
  #Вводим пароль
  send(SOCK,"$password\r\n",0);
  send(SOCK,"rm $mday-$mon-$hour.bak\r\n",0);
  sleep($ats_delay);
  send(SOCK,"logout\r\n",0);
  @data=<SOCK>;
  close (SOCK);
  #print @data;
  print "Remove billing.bak form ATC successful\n";
  #Получаем текущее время
  $curr_time = time();
  print "Origunal time: $curr_time\n";
  my ($sec,$min,$hour,$mday,$mon,$year,
         $wday,$yday,$isdst) = localtime($curr_time - 3600);
       #Корректировка года и месяца
       $mon+=1;
       $year+=1900;
  if ($hour < 10) { $hour="0".$hour };
       if ($mday < 10) { $mday="0".$mday };
       if ($mon < 10) { $mon="0".$mon };
  print "Archive time: $year/$mon/$mday\_$hour\n";
       #Конвертация
       #Проверяем наличние струтуры каталогов
       #проверка корневого католога с годом
       if (!(-e "$export_dir/$year")){
          #создаём подкаталог
               mkdir ("$export_dir/$year");
       }
       #проверка каталога с месяцом
       if (!(-e "$export_dir/$year/$mon")){
          #создаём подкаталог
               mkdir ("$export_dir/$year/$mon");
       }
  #Проверяем наличие архива
  if(-e "$export_dir/$year/$mon/$mday\_$hour.zip"){
     #Если архив есть, то распаковываем его
     system("$unzip $export_dir/$year/$mon/$mday\_$hour.zip -d $export_dir/$year/$mon/ ");
     #Ударяем архив
     system("$rm -f $export_dir/$year/$mon/$mday\_$hour.zip");
  }
  #Конвертируем c дописыванием
  print "Now convert Log (billing.bak)  file\n";
  if (system("$converter /3 $input_dir/billing.bak  $export_dir/$year/$mon/$mday\_$hour $redirect > $tmpfile")!=0){
          my $alarm_str="File convert ERROR-7\n";
               my $tstr;
          open(TMP,$tmpfile);
          while($tstr=<TMP>){
                          $alarm_str=$alarm_str.$tstr
          }
          send_alarm_noexit($alarm_str);
  }
       #Копируем billing.bin
       system("$cp -f $input_dir/billing.bak  $export_dir/$year/$mon/billing.bak");
  printf("Log convert successful\n");
  #Перемещяемся в нужный каталог
  chdir("$export_dir/$year/$mon");
  #Архивируем
  print "Now compress Log  file\n";
  system "chmod 664 $mday\_$hour.zip";
  system("$zip $mday\_$hour.zip $mday\_$hour billing.bak");
  #Удаляем
  system("$rm -f $mday\_$hour");
  printf("Log  compress successful\n");
  system "chmod 664 $export_dir/$year/$mon/$mday\_$hour.zip";
  return 0;

}

sub epipe_handler{

 send_alarm("Connection close. ATS is BUSY(broken pipe) \n");

}

--Max 17:48, 13 мая 2012 (UTC)

Личные инструменты