Создаём веб-форму для отправки факсов через Asterisk

Занимаясь развитием и эксплуатацией VoIP сети в одном из провайдеров неминуемо приходится сталкиваться со множеством проблем. Наверно, одними из самых неприятных и трудозатратных были и остаются проблемы, связанные с факсами, которые зачастую возникают при подключении к новому оператору или неожиданно всплывают у существующих.

Чтобы как-то автоматизировать процесс проверки прохождения факсов для нашей техподдержки реализовал веб интерфейс, позволяющий осуществить отправку факса на нужного оператора.
Статья предполагает наличие установленного Астериска с работающим модулем Fax for Asterisk. Астериск будет делать вызовы на некий софтсвич, который в свою очередь направит звонок на нужного оператора.

Как работает логика отправки?
Необходимым условием является наличие принимающей факс-машины, работающей в автоматическом режиме, иначе Астериск не сможет детектировать на принимающей стороне факс-аппарат и инициализировать сессию отправки по протоколу t38. Использование протокола t.38 позволяет получить высокую вероятность прохождения факсов в сетях ip.

Итак, наш скрипт будет создавать для Астериска файл вызова, ответственный за дозвон на номер факс-машины. Скрипт будет также знать, через какого оператора осуществить вызов.
Может возникнуть ситуация, когда факс-машина, находится на заранее известном внутреннем номере. В этом случае мы можем заставить Астериск осуществить его донабор и уже затем инициировать отправку факса.
Html форма для отправки имеет вид

Код html формы следующий

	<title>Форма для отправки факсов</title>
	<body>
	<h2>Форма для отправки факсов</h2>
	Через какого оператора звоним?
	<form name="forma1" method=post action="/cgi-bin/callback-fax.pl">
	<p>
	<SELECT NAME="operator">
	<OPTION VALUE ="operator-1">operator-1
	<OPTION VALUE ="operator-2">operator-2
	<OPTION VALUE ="operator-3">operator-3
	<OPTION VALUE ="operator-4">operator-4
	<OPTION VALUE ="operator-5">operator-5
	<OPTION VALUE ="operator-6">operator-6
	</SELECT>
	<p>
	На какой номер отправляем факс?	<INPUT NAME="number" VALUE ="" SIZE=15 MAXLENGTH=15>
	<p><b>Начать отправку сразу без донабора внутрненнего номера?</b><INPUT TYPE="CHECKBOX" NAME="direct_dial" CHECKED="1" VALUE ="1">
	<br>через     <INPUT NAME="direct_dial_timeout" VALUE ="2" SIZE=2 MAXLENGTH=2>секунд
	<p>Если не выбрана отправка сразу, можно донабрать на внутренний номер(укажите внутренний номер)	<INPUT NAME="disa_number" VALUE ="" SIZE=4 MAXLENGTH=4> через указанное число секунд после прослушивания приветствия	<INPUT NAME="disa_timeout" VALUE ="" SIZE=2 MAXLENGTH=2>
	<br>На какую почту сообщить статус отправки?	<INPUT NAME="mailbox" VALUE ="" SIZE=20 MAXLENGTH=50>
	<p><input type="submit" name="submit" value="Отправить Факс!">
	</form>
	</body>
	

При активации из формы отправки факса инициализируется скрипт callback-fax.pl, который разбирает переданные ему параметры, создаёт файл вызова(callfile)
Важным здесь является подстановка нужного префикса к номеру в зависимости от выбранного в html форме оператора.
В зависимости от того, нужен ли донабор на факс-машину или нет, скрипт вызывает нужную логику из диалплана Астериска(Extension 100 или Extension 200)

	#!/usr/bin/perl
	use strict;
	use warnings;
	use CGI qw(:standard);

	my $operator = param('operator');
	my $original_number = param('number');
	my $send_fax_now = param('direct_dial');
	my $send_fax_now_timeout = param('direct_dial_timeout');
	my $send_fax_disa_number = param('disa_number');
	my $send_fax_disa_timeout = param('disa_number');
	my $mailbox = param('mailbox');

	my %operator_prefix = (
	                        operator-1 => '01',
	                        operator-2 => '02',
	                        operator-3 => '03',
	                        operator-4 => '04',
	                        operator-5 => '05',
	                        operator-6 => '06'
	                        );

	my $number = $operator_prefix{$operator} . $original_number;
	print "Content-type: text/html\n\n";
	print "Sending fax... you will be e-mailed at <b>$mailbox</b><br>\n";
	if ($send_fax_now == 1){
	        open (F, ">/var/spool/asterisk/outgoing/$number");
	        print F "Channel: SIP/";
	        print F "$number";
	        print F "\@softswitch\n";
	        print F "Callerid: 7495XXXXXXX\n";
	        print F "Context: send_fax\n";
	        print F "Extension: 100\n";
	        print F "MaxRetries: 1\n";
	        print F "Retrytime: 5\n";
	        print F "WaitTime: 60\n";
	        print F "Priority: 1\n";
	        print F "SetVar: operator=$operator\n";
	        print F "SetVar: original_number=$original_number\n";
	        print F "SetVar: email=$mailbox\n";
	        print F "SetVar: send_fax_now_timeout=$send_fax_now_timeout";
	close F;
	}
	else {
	        open (F, ">/var/spool/asterisk/outgoing/$number");
	        print F "Channel: SIP/";
	        print F "$number";
	        print F "\@softswitch\n";
	        print F "Callerid: 7495XXXXXXX\n";
	        print F "Context: send_fax\n";
	        print F "Extension: 200\n";
	        print F "MaxRetries: 1\n";
	        print F "Retrytime: 5\n";
	        print F "WaitTime: 60\n";
	        print F "Priority: 1\n";
	        print F "SetVar: operator=$operator\n";
	        print F "SetVar: original_number=$original_number\n";
	        print F "SetVar: email=$mailbox\n";
	        print F "SetVar: send_fax_disa_number=$send_fax_disa_number\n";
	        print F "SetVar: send_fax_disa_timeout=$send_fax_disa_timeout";
	        close F;
	}
	open (LOGFILE, ">>/var/log/faxsend.log");
	my $date = localtime;
	print LOGFILE "$date:$original_number:$operator\n";
	close LOGFILE;
	

Теперь переёдм к конфигурации extensions.conf Астериска.
Здесь как ни странно всё просто. На extension 100 отправляем факс сразу, extension 200 шлёт факс после донабора.
По Hangup шлём отчёт в почту об отправке не забывая поставить себя в копию ;)

	[send_fax]

	exten => 100,1,Wait(${send_fax_now_timeout})
	exten => 100,n,NoOp(${TIFF_FILE})
	exten => 100,n,SendFAX(/usr/dumps/test-fax.tiff,d)
	exten => 100,n,NoOp(${FAXSTATUS})
	exten => 100,n,Hangup()

	exten => 200,1,Wait(${send_fax_disa_timeout})
	exten => 200,n,SendDTMF(${send_fax_disa_number})
	exten => 200,n,NoOp(${TIFF_FILE})
	exten => 200,n,SendFAX(/usr/dumps/test-fax.tiff,d)
	exten => 200,n,NoOp(${FAXSTATUS})
	exten => 200,n,Hangup()


	exten => h,1,NoOp(email is ${email}:operator is ${operator}:number is ${original_number})
	exten => h,n,System(/usr/local/bin/sendEmail -f fax@domain.com -t ${email} -bcc makarov@domain.com -u 'Fax message Sent' -m 'operator:${operator}\nnumber:${original_number}\nStatus:${FAXSTATUS}' -s mx.domain.com -l /var/log/fax.log)
	

К скрипту по желанию можно также добавить форму для закачки какой-либо картинки с последующей отправкой, однако нужно не забыть привести её в tiff, с которым может работать Астерисковый SendFax()
Например, tiffinfo в моём случае говорит:
	[root@PBX-CALLBACK dumps]# tiffinfo test-fax.tiff
	TIFF Directory at offset 0x8 (8)
	  Subfile Type: multi-page document (2 = 0x2)
	  Image Width: 1728 Image Length: 1172
	  Resolution: 204, 98 pixels/inch
	  Bits/Sample: 1
	  Compression Scheme: CCITT Group 4
	  Photometric Interpretation: min-is-white
	  FillOrder: msb-to-lsb
	  Orientation: row 0 top, col 0 lhs
	  Samples/Pixel: 1
	  Rows/Strip: 1172
	  Planar Configuration: single image plane
	  Page Number: 0-0
	  Software: GPL Ghostscript 8.70
	  DateTime: 2011:12:23 16:04:13
	  Group 4 Options: (0 = 0x0)
	

Надеюсь в следующих статьях отсветить еще кое-какие интересные аспекты Asterisk и вообще VoIP телефонии
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 7

    0
    А факс у Вас по аналоговой линии идет — какая плата у Вас стоит?
      0
      Не обязательно плата, сип или шлюз могут быть.
      +2
      Хм… ваш вариант не работает в случае, когда надо позвонить и сказать «примите, пожалуйста, факс». У нас это реализовано немного по другому… Если в кратце — то через web интерфейс заливается факс и web-интерфейс возвращает некий четырёхзначный номер.
      После этого оператор сам набирает нужный номер — общается с человеком на той стороне и в момент когда они готовы принять факс — переводит звонок на номер, который сообщил web-интерфейс.
      Дальше астериск уже запускает стандартную процедуру отправки факса из файла.
        +3
        Когда же такие аппараты здохнут :(
          +2
          факс — это вообще пережиток прошлого :))
          по большому счету повсеместное внедрение ЭЦП должно положить конец эпохи факсов…
        0
        На самом астериске нет плат, все вызовы идут по сипу
          0
          Так и есть, об этом мной упомянуто в посте. Большего функционала в общем-то и не требовалось. Ну а вашу реализацию возьму на заметку, если позволите :).

          Only users with full accounts can post comments. Log in, please.