📜 ⬆️ ⬇️

Corporate PBX based on Asterisk

Prerequisites

In the life of any large developing company, sooner or later the question arises of expanding the capabilities of a telephone exchange and the transition from classical telephony to IP.

In the far spring of 2011 and in front of our company, there was such a question, since the external and internal lines require constant expansion, and the number of ports on the old Panasonic KX-TA624 was set statically and was not subject to expansion. The opening of offices in other cities and the introduction of a unified customer service in other cities also pushed for qualitative changes.
')
Technical task

The final product must have the following characteristics:
1) have a large number (in our case at least 100) of external and internal lines and be ready for expansion;
2) be able to greet users during working hours and report that they called during non-working hours when there is no one in place;
3) redirection timeouts when no response / busy / unavailability must be configured individually;
4) queues should be provided. Queue - a group of numbers, the distribution of calls within which occurs according to certain rules;
5) write log messages (both text and audio);
6) have a flexible policy of distribution of rights to external calls. Users who can call only internal numbers should be provided; city ​​numbers; to any rooms;
7) depending on the time of day, call one or another number.

Unsuccessful experience

The initial choice fell on the Planet ipx-1900. Characteristics can be found here:
www.planet.com.ru/en/product/product_keyf.php?id=18500

Among other things, support is claimed:
• Autoinformer (AA)
• Interactive Voice Responses (IVR)
• Call Detail Report (CDR)

In practice, none of these parameters work. Planet support ignored questions. It was impossible to get 8800 on this iron by standard means.

I had to dig deeper. On this PBX there is a com-port and telnet, when connected to it, a login and password is requested. Technical support for Planet refused to provide details for entry ... more precisely, it ignored the request. A page with firmware for the device can be found here:
planet.com.ru/en/support/download2.php?id=18500&file_type=65&prod_model=IPX-1900

The firmware was nothing more than an archive:
$ mkdir untar && cd untar && tar xvf ../FW-IPX1900_1.16.8.dat rootfs.jffs2 vmImage start_install.sh aimage.tar.gz 


The most interesting was start_install.sh - this script is executed immediately after downloading the firmware to the device. Immediately after the line:
 #!/bin/sh 

add the line:
 useradd -groot -proot toor 


We pack everything back into the archive and download the firmware to the station.

If everything goes well, it will be possible to login to the station via com-port or telnet.
Inside was detected by ÎĽClinux with Asterix 1.4

And began dopilivaniya station to working condition. We will not post the list of changes, because it is, by now, irretrievably lost.

Thanks to access to the station console, we managed to implement step 1-4 of the technical task. And add at station 8800, which is also not bad, if not:
1) permanent freezing of the station and external ports;
2) daily station reboots at night;
3) at times, after a reboot, the station could not be synchronized with the temporary server, and she informed clients that the time was not working, although in fact the time was working.

However, in this form, telephony existed in Regtime for about a year and a half. Nevertheless, the management continued to "kick" technical support (yes, yes, technical support) on the theme of making the dream of a completed technical task come true, and technical support was born.

Iron

At the time of the transition from the planet to a regular server, there were:
1) several planet ata-150s voice gateways (2 fxs ports);
2) linksys spa-3000 (1fxo + 1 fxs port) - 2 pieces;
3) a bunch of analog phones (Panasonic heritage);
4) VoIP phone dlink-dph150s, dlink-dph150se;
5) server with Debian OS;
6) network filters, twisted pair, switch :)

Subjective review of the gland

VoIP dlink work well. Hanging almost not observed. There were several models with a marriage, but without any questions they were changed to new ones.

Linksys - not bad. Sometimes there is a hangup, at which the voice gateway itself does not hang, but the FXO port on it. Unfortunately, it is found only at the request of customers.

Planet ata-150s - bad. Very often, hangs occur, periodically there are noises in the tube. Only restart helps. Were bought a pack - so you have to work with what is.

Install Asterisk

Unfortunately, the asterisk installation log on debian has not been saved. Therefore, the article will be translated installation commands on Ubuntu 12.04. By and large, there should be very few differences, for example, Asterisk 1.8 is not included in the main debian repository, but it is in the backports.

For work we use the following packages:
1 asterisk - Asterisk 1.8
2 libasterisk-agi-perl - AGI module for perl. About this a little later.
3 asterisk-mysql - Asterisk extension, which allows storing statistics not in a text file, but in a database

 $ sudo aptitude install asterisk libasterisk-agi-perl asterisk-mysql mysql-server 


Call Log Setup

1) From the database root, create a new database and user:
 CREATE DATABASE astr; GRANT ALL PRIVILEGES ON astr.* TO 'asterisk'@'localhost' IDENTIFIED BY 'super-pass' WITH GRANT OPTION; EXIT; 


2) Go under the newly created user:
 $ mysql -uasterisk -psuper-pass astr 


3) Create a table:
 CREATE TABLE `cdr` ( `calldate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `clid` varchar(80) NOT NULL DEFAULT '', `src` varchar(80) NOT NULL DEFAULT '', `dst` varchar(80) NOT NULL DEFAULT '', `dcontext` varchar(80) NOT NULL DEFAULT '', `channel` varchar(80) NOT NULL DEFAULT '', `dstchannel` varchar(80) NOT NULL DEFAULT '', `lastapp` varchar(80) NOT NULL DEFAULT '', `lastdata` varchar(80) NOT NULL DEFAULT '', `duration` int(11) NOT NULL DEFAULT '0', `billsec` int(11) NOT NULL DEFAULT '0', `disposition` varchar(45) NOT NULL DEFAULT '', `amaflags` int(11) NOT NULL DEFAULT '0', `accountcode` varchar(20) NOT NULL DEFAULT '', `userfield` varchar(255) NOT NULL DEFAULT '', KEY `calldate` (`calldate`), KEY `dst` (`dst`), KEY `accountcode` (`accountcode`) ); EXIT; 


4) Go to the config directory asterisk (all further actions must be performed on behalf of the super-user) and make a copy of all the content just in case:
 # cp -r ../asterisk/ ~/asterisk_config # echo '' > cdr_mysql.conf && mcedit cdr_mysql.conf 

We have it looks like:
 [global] hostname=localhost dbname=astr table=cdr password=super-pass user=asterisk [columns] alias start => calldate 


Config cdr.conf remained unchanged.

Outgoing Call Users and Contexts

For outgoing user calls, we have 4 contexts:
1 phone_int is the default value. Users who are allowed to call only to internal 3-digit numbers.
2 phone_local - users can call 7-digit city numbers;
3 phone_long_d - these users are allowed calls within the country;
4 phone_too_long_d - international calls.

Contexts are integrated into each other, i.e. phone_too_long_d users are allowed to call both internal numbers of employees and inside the city.

Let's start:

1) Let's split sip.conf into several:
 # mcedit sip.conf #include sip_general.conf #include sip_trunk.conf #include sip_internal.conf 


sip_general.conf - the main asterisk settings.
sip_internal.conf - internal numbers of users;
sip_trunk.conf - external lines;

2) An example of configuring 3 numbers in sip_internal.conf:

 [defaults](!) type = friend qualify = yes ;    ; ,     context = phone_int canreinvite = no host = dynamic callgroup = 1 pickupgroup = 1 [101](defaults) secret = pass_for_reception callerid = "Sveta"<101> context = phone_long_d [112](defaults) secret = pass_for_artur callerid = “Artur"<112> context = phone_local [106](defaults) secret = pass_for_fax callerid = "Fax"<106> context = phone_too_long_d [495](defaults) secret = pass_msk callerid = "MSK"<495> 


User 101 is allowed to make calls within Russia (context = phone_long_d); user 112 (phone_local) can call within the city; 106 allowed to call anywhere; user 495 is only allowed to dial extensions (if the context is not set, the phone_int context is used). The secret field is the password that will be used for authorization.

Incoming lines

Example of the main config:

 # mcedit sip_general.conf [general] bindport = 5060 bindaddr=0.0.0.0 allowguest = no allowtransfer = yes allowoverlap = no tos_sip = cs3 tos_audio = ef tos_video = af41 srvlookup = no minexpiry = 900 maxexpiry = 3600 defaultexpiry = 360 checkmwi = 10 language = en relaxdtmf = no rtptimeout = 550 rtpholdtimeout = 600 progressinband = never useragent = PBX dtmfmode = rfc2833 disallow = all domain = pbx.webnames.ru ;    allow = ulaw,alaw,gsm,ilbc,g726,g729,g723 ;   registertimeout = 60 registerattempts = 65535 externip = 8.8.8.8 ; ip  externrefresh = 10 nat = yes canreinvite = nonat insecure = invite register = example_num:pass_for_example_num:example_num@proxyreg_time/example_num 


Setting up the trunk:

 # mcedit sip_trunk.conf [trunk](!) type = friend call-limit=1 canreinvite=no qualify=yes context= from_external disallow=all ; need to disallow=all before we can use allow= allow=ulaw ; Note: In user sections the order of codecs allow=alaw allow=g723.1 ; Asterisk only supports g723.1 pass-thru! allow=g729 ; Pass-thru only unless g729 license obtained allow=gsm ;; example_num [example_num] type = peer username = example_num fromuser = example_num secret = pass_for_example_num fromdomain = 1.1.1.1 ; external pbx ip host = 1.1.1.1 ; external pbx ip port = 5060 outboundproxy = 1.1.1.1 ; external pbx ip outboundproxyport = 5060 context = from_external ;    [pstn_beeline](trunk) username = pstn_beeline fromuser = pstn_beeline host = dynamic secret = pass_for_beeline ;; 88001004022 (RosTelecom) [RTK] username = trace_num type = peer host = 2.2.2.2 ; external pbx ip insecure=port,invite context= from_external 


The example_num line uses authorization and registration at a remote station to commit. Please note for this line spelled:
 register = example_num:pass_for_example_num:example_num@proxyreg_time/example_num 


in sip_general.conf.

The pstn_beeline line does not require registration - in fact, this is one of the “land” lines connected via the fxo port linksys spa 3000, but more on that later.

Line RTK - no authorization or registration is required here. At the station, you need only a user and ip (host field) from which calls will come. This number is 8800 - only incoming telephony is carried out to it. In terms of Rostelecom, the username is the route number.

For all incoming calls, the context is one - from_external.

Dialplan (dial plan) - call routing

The most interesting thing about any PBX is the dial plan. The dial plan routes calls according to the rules described in it. So:

1) Outgoing calls.

 # mcedit extensions.conf [globals] [general] autofallthrough=yes ;      ;      ; dial_internal.pl -     [out_int] ;       exten => *, 1, NoOp() exten => _[1-9]XX, 1, Macro(monitor) exten => _[1-9]XX, n, Macro(int-dial,${EXTEN}) exten => _[1-9]XX, n, Hangup() ;   -  [out_local] ;   exten => _X., 1, Macro(monitor) exten => _[1-79]XXXXXX, 2, Dial(SIP/${EXTEN}@pstn_beeline&SIP/${EXTEN}@example_num) exten => _0[1-79]XXXXXX, 2, Dial(SIP/${EXTEN:1}@pstn_beeline&SIP/${EXTEN:1}@example_num) exten => _83[1-79]XXXXXX, 2, Dial(SIP/${EXTEN:2}@pstn_beeline) exten => _85[1-79]XXXXXX, 2, Dial(SIP/${EXTEN:2}@example_num) ;  -          ; .      exten => _094959874596, 2, Dial(SIP/${EXTEN:1}@pstn_beeline) ; msk line ;  [out_long_d] ;   exten => _X., 1, Macro(monitor) ;     ; 1) -  ; 2) -   exten => _08X., 2, Dial(SIP/${EXTEN:1}@pstn_beeline&SIP/${EXTEN:1}@example_num) ;         exten => _838X., 2, Dial(SIP/${EXTEN:2}@pstn_beeline) exten => _858X., 2, Dial(SIP/${EXTEN:2}@example_num) ;   [out_too_long_d] exten => _X., 1, Macro(monitor) exten => _0X., 2, Dial(SIP/${EXTEN:1}@pstn_beeline&SIP/${EXTEN:1}@example_num) ;      exten => _83X., 2, Dial(SIP/${EXTEN:2}@pstn_beeline) exten => _85X., 2, Dial(SIP/${EXTEN:2}@example_num) ;    [phone_int] include => out_int ;   [phone_local] include => phone_int include => out_local ;  [phone_long_d] include => phone_local include => out_long_d ;   [phone_too_long_d] include => phone_long_d include => out_too_long_d ; ======== ============== 


Parse string:
 exten => _0[1-79]XXXXXX, 2, Dial(SIP/${EXTEN:1}@pstn_beeline&SIP/${EXTEN:1}@example_num) 


_0 [1-79] XXXXXX - the mask of the dialed number. Read more here ( voip.rus.net/tiki-index.php?page=Asterisk+Dialplan+Patterns )

0 - the first digit that came
[1-79] - the second digit can be any number except 8, since This is the exit to the intercity
XXXXXX - any 7 digits

X matches any number from 0 to 9
Z matches any number from 1 to 9
N matches any number from 2 to 9

2 - priority, means that this action will be performed second in a row.

Dial is one of the most used asterisk applications. It is designed to call the number through a certain line. You can read more about this application here ( voip.rus.net/tiki-index.php?page=Asterisk+cmd+Dial )

SIP / $ {EXTEN: 1} is a kind of regexp. For example, when dialing the number 03799039, the number 3799039 will be sent to the channel.

@pstn_beeline - the channel through which the call will be made.

& SIP / $ {EXTEN: 1} @example_num is another channel through which the call will be made if the biline line is busy or unavailable.

 ;   [phone_local] include => phone_int include => out_local 


in order to get the phone_local context, you need to include 2 contexts in it - phone_int and out_local; the user to whom such a context is connected (in the example above is user 112), calls to fixed numbers are allowed.

2) Incoming calls are handled as follows:

 ; ========= ============== [from_external] exten => _X., 1, Macro(dial) exten => s, 1, Macro(dial) ; ========= ============== 


3) Macros

In essence, macros are functions. A macro can be passed parameters that it will use depending on the context. You can refer to the macro as follows:
 exten => _[1-79]XX, n, Macro(int-dial,${EXTEN}) 


_ [1-9] XX - the number by which dialing occurs.
n is the priority;
Macro - the macro application itself.
int-dial - the name of the macro.
$ {EXTEN} - the parameter that will be passed to the macro (in this case, the phone number)

Read more about macros here ( voip.rus.net/tiki-index.php?page=Asterisk+cmd+Macro&highlight=Macro ()).

Macros that we use in terms of typing:

 ; =============================== ;       ;   /var/lib/asterisk/agi/dial_internal.pl ;      (  ) ;     ;     users .. asterisk [macro-int-dial] exten => s, 1, NoOp() exten => s, 2, AGI(/var/lib/asterisk/agi/dial_internal.pl, ${ARG1}) exten => s, n, Hangup() ;    ( ) ;         ;     [phone_int] ;     /var/lib/asterisk/agi/ivr.pl [macro-monitor] exten => s, 1, AGI(/var/lib/asterisk/agi/monitor.pl) ;     [macro-groupe-dial] exten => s, 1, Queue(${ARG1}, rtT,,,100) ;     ;   -  (     ) ;   ( <->. ), ;   - “  ,    " [macro-dial] exten => s, 1, AGI(/var/lib/asterisk/agi/ivr.pl) exten => s, n, Hangup() ; =============================== 


In almost all contexts, the AGI application is used. Read more about the application here ( voip.rus.net/tiki-index.php?page=Asterisk+cmd+AGI&highlight=AGI ()).

How we use this application - in the next section.

AGI greeting

Task.
Implement a menu that works like this:
1) Weekends and non-working hours - a message stating that the customer called during non-working hours; voice time work.
2) Working time - greeting; depending on the time, switch the client to
• secretary (if the client got into the office;);
• technical support during the rest of the working time

Working time is considered Monday-Friday from 9 to 21; the office is open from 9 to 13 and from 14 to 18 on weekdays (from one to two in the office lunch).

A tool for solving the problem.
To solve the problem, the AGI tool was chosen.
AGI (Asterisk Gateway Interface) is Asterisk's built-in method for executing external scripts (similar to CGI for http servers), which can extend the functionality of asterisk using other programming languages.
Perl was chosen as the development language as a universal tool for solving any task. :-)
On cpan there is a module Asterisk :: AGI search.cpan.org/~jamesgol/asterisk-perl-1.03/lib/Asterisk/AGI.pm .

AGI's advantages are simplicity of development; flexibility. Cons - significantly increases the load on the server. The script is compiled each time it is accessed, and not cached; on the Internet, they write that AGI is buggy, but during our work (~ 0.5 years) there were no problems with this. We also have no problems with computing power.

The solution of the problem.
All incoming calls are sent here (see previous section):
 exten => s, 1, AGI(/var/lib/asterisk/agi/ivr.pl) 


The incoming call handler (/var/lib/asterisk/agi/ivr.pl) will look like this:
 use Data::Dumper; use warnings; use strict; use Asterisk::AGI; use Time::localtime; my $AGI = new Asterisk::AGI; my %input = $AGI->ReadParse(); #   ""  # ,    #  check_ivr my $schedule_time = '/var/lib/asterisk/agi/schedule.conf'; #    my $support = '300'; #   my $recep = '101'; # non_working -   # working -    (   9-13;14-18 ) # work_supp -      (default 13-14; 18-21) my @ivr = (\&non_working, \&working, \&work_supp); #START $AGI->answer(); #          my $mode = &check_ivr(); # $AGI->verbose( "Mode => $mode", 0); &{$ivr[$mode]}; #   $AGI->hangup(); exit(); sub non_working{ #       $AGI->exec('Playback', 'offduty'); } sub working{ #  $AGI->exec('Playback', 'welcome'); #       $AGI->exec('Macro', "monitor"); #   $AGI->exec('Macro', "int-dial,$recep"); } sub work_supp{ $AGI->exec('Playback', 'welcome'); $AGI->exec('Macro', "monitor"); #     $AGI->exec('Macro', "groupe-dial,$support"); } ################# check_ivr ##################################### #  ( .      ):# # $wday -    (   - 0..6 )############### # $hour -  (   - 0..23 )########################### # $date -  (   - . )################### #   ( 0..2 ):####################################### # 0 -  ;########################################### # 1 -  ;############################################## # 2 -  ..###################################### sub check_ivr { my ( $wday, $hour, $date ) = @_; #         -   ($wday, $hour, $date ) = &_date_now_ if !$date||!$hour||!$date; my ( %check, $check); # -        my %sch_dates; open ( SCH, $schedule_time ); while ( <SCH> ) { if ( $_ =~ /^(\d{1,2}\.\d{1,2})\s*(.*)[\r\n]*$/) { my ( $sch_date, $sch ) = ($1, $2); $date =~ s/^0(\d)/$1\./; $date =~ s/0(\d)$/$1/; $sch ||= '0'; $sch_dates{$sch_date} = $sch; } } close(SCH); foreach my $schedule_d (keys %sch_dates){ if ( $date eq $schedule_d ) { if ( $sch_dates{$date} ) { return &_check_time_( $hour, $sch_dates{$date} ); } else { return $sch_dates{$date} } } } #   ?   1(  )  0 (  ) $check{wday} = $wday>0&&$wday<6 ? '1':'0'; #   0, 1, 2 -  _check_time_ $check{hour} = &_check_time_( $hour ); $check = 1; foreach ( values %check ) { $check *= $_; } return $check; sub _check_time_ { # $hour_tm -   # $wr_time - work time (    )   [9,13,18,21] my ( $hour_tm, $wr_time) = @_; # $wr_time - work time (    ) #   () my %wr_time = &_parse_work_time_( $wr_time ); # 0 -    # 1 -    ( 9-13; 14-18 ) # 2 - c 13  14;  18  21 my $check_tm = 0; if( $hour_tm>$wr_time{st_office}&&$hour_tm<$wr_time{end_support} ) { if ( $hour_tm==$wr_time{lunch}||$hour_tm>$wr_time{end_office} ) { $check_tm = 2; } else { $check_tm = 1 } } return $check_tm; } #     [9,13,18,21] #    # %work_time = ( st_office => 8, # lunch => 13, # end_office => 17, # end_support => 21); sub _parse_work_time_ { my ( $work_time ) = @_; #      1 #   . $work_time = "[9,13,18,21]" if (!$work_time||$work_time eq 1 ); $work_time =~ s/^\[(.+)\][\r\n]*$/$1/; my %work_time; ( $work_time{st_office}, $work_time{lunch}, $work_time{end_office}, $work_time{end_support}, $work_time{lunch_support} ) = split /\s*,\s*/, $work_time; $work_time{st_office} -= 1; $work_time{end_office} -= 1; return %work_time; } sub _date_now_ { return ( localtime->wday, localtime->hour, localtime->mday.'.'.(localtime->mon+1) ); } } __END__ 


The /var/lib/asterisk/agi/schedule.conf file stores “exceptional” time, i.e. the time when the office does not work as usual, for example, a holiday or short day. Example:

# 1 - date (day.month)
# 2 - what day (optional parameter)
# 0 is non-working or empty
# 1 - a normal worker ([9,13,18,21]) or an array
# 2.1 - office start time (9)
# 2.2 - lunch (13, that is, from 13 to 14)
# 2.3 - office end time (18)
# 2.4 - technical support end time
# date is entered without zeros. 06.11 - does not work; 6.11 - works
29.12 [9,11,17,20]
31.12

December 29 [9,11,17,20] (December 29) - abbreviated day. The office is open from 9 to 17; lunch from 11 to 12; technical support works up to 20.
December 31 is a non-working day.

AGI call handler

Task.
When calling the number, the call must be redirected after a certain timeout / busy / non-response / unavailability to another number (as a rule, this is one of the queues). "Timeout" and "other number" - dynamic variables - for each number they can be set individually.

Tool.
As in the last section - AGI.

The solution of the problem.

Employee internal numbers are stored in the mysql database in the users table.
Create a table:
 CREATE TABLE `users` ( `num` int(11) PRIMARY KEY NOT NULL, `timeout` tinyint(4) NOT NULL DEFAULT '10', `queue` int(11) DEFAULT NULL ); 


num - employee's phone number;
timeout - time in seconds, after which the call will be redirected;
queue - the queue number to which the call will be forwarded.

add entries for numbers:
 INSERT INTO `users` VALUES (101,10,300), (106,20,0), (112,20,0); 


check what happened:
SELECT * FROM users;
+ ----- + --------- + ------- +
| num | timeout | queue |
+ ----- + --------- + ------- +
| 101 | 10 | 300 |
| 106 | 20 | 0 |
| 112 | 20 | 0 |
+ ----- + --------- + ------- +

If you call 101 after 10 seconds, the call will go to 300 number (we have this technical support number); when you call 112 or 106, the call will not go anywhere, but will simply end in 20 seconds.

You can call the handler as follows (AGI (/var/lib/asterisk/agi/dial_internal.pl, $ {ARG1})):

In dialplan this is:
 exten => _[1-9]XX, n, Macro(int-dial,${EXTEN}) [macro-int-dial] exten => s, 1, NoOp() exten => s, 2, AGI(/var/lib/asterisk/agi/dial_internal.pl, ${ARG1}) exten => s, n, Hangup() 


The phone number is in the $ {EXTEN} variable macro, and then passed to the /var/lib/asterisk/agi/dial_internal.pl handler using $ {ARG1}.

Handler Code:

 #!/usr/bin/perl use Data::Dumper; use warnings; use strict; use Asterisk::AGI; use DBI; my $user = 'asterisk'; my $pass = 'super-pass'; my $db = 'astr'; my $AGI = new Asterisk::AGI; my %input = $AGI->ReadParse(); $AGI->answer(); #     my $exten = $input{arg_1}; #    ,       my ($timeout, $queue) = &get_timeout($exten); #     #  ,    . $timeout ||= '10'; #$AGI->verbose("$timeout $queue", 0); $AGI->exec('Dial', "SIP/$exten, $timeout, Tt"); #           if ( $queue ) { # $AGI->verbose('$queue', 0); $AGI->exec('Macro', "groupe-dial,$queue") if ( $AGI->get_variable('DIALSTATUS') ne 'ANSWER'); } $AGI->hangup(); exit(); sub get_timeout { my ($num) = @_; my $dbh = DBI->connect("DBI:mysql:database=$db;host=localhost", $user, $pass, {'RaiseError' => 1}); my $sth = $dbh->prepare("SELECT * FROM users WHERE num like $num"); $sth->execute(); my $ref = $sth->fetchrow_hashref(); ( $timeout, $queue ) = ( ${$ref}{timeout}, ${$ref}{queue}); $sth->finish (); $dbh->disconnect(); return ($timeout, $queue); } __END__ 




. AGI. , , .
: ./2013/03/28/20130328.150550.9033779401.wav,
those. .////__.__.___._.wav

, grep' ( / ..)

/var/lib/asterisk/agi/monitor.pl:
 #!/usr/bin/perl use Data::Dumper; use warnings; use strict; use Asterisk::AGI; use File::Path qw(make_path); #    my $dir = '/mnt/pbx/'; my $AGI = new Asterisk::AGI; my %input = $AGI->ReadParse(); #  -  ,    #   my $prop = $input{arg_1}; $AGI->answer(); my ($date, $time) = split / /, $AGI->get_variable('CDR(start)'); $time =~ s/://g; $date =~ s/-/\//g; $date .= '/'; my $dir = $dir.$date; #        $date =~ s/\///g; #        #        - 'ivr' $prop ||= $AGI->get_variable('CDR(src)'); #    $prop =~ s/[\+\.\'\"\:\(\)\[\]\&\^\$\#\@\!\%\*\s]//g; my $file = $prop ? $dir.$date.".$time.$prop" : $dir.$date.".$time.anon"; #   $file .= '.wav'; $AGI->exec('MixMonitor', "$file, a"); exit(); __END__ 

MixMonitor ( www.voip-info.org/wiki/view/MixMonitor )

Queues

With queues, everything is relatively simple. The config is called queues.conf. We have 2 queues - technical support (number 300) and accounting (301):

 [general] persistentmembers=yes autofill=yes autopause=no monitor-type=MixMonitor strategy=ringall ;  . ringinuse=no timeout=100 retry=2 wrapuptime=0 maxlen=0 defaultrule = plus10 [301] member => SIP/105,1 member => SIP/109,1 [300] member => SIP/102,1 member => SIP/108,1 

You can read more about queue features here:
www.voip-info.org/wiki/view/Asterisk+config+queues.conf

Setting up external lines through linksys spa-3000

Task.
linksys spa-3000 fxo- fxs. , ( .. ), fxs ( ).
1) , fxo ;
2) , ;
3) , .

.
, , .. . Admin login->Advanced->PSTN Line:
Proxy: 10.0.0.5 # (ip )
Outbound Proxy: 10.0.0.5 # (ip )
Register: yes
User ID: pstn_beeline
Password: pass_for_beeline

# , .
Dial Plan 2: (<:@gw0>)
PSTN Caller Default DP:2

(pstn_beeline).

106 fax:
Proxy: 10.0.0.5 # (ip )
Outbound Proxy: 10.0.0.5 # (ip )
Register: yes
User ID: 106
Password: pass_for_fax

(106)



asterisk -r — asterisk
asterisk -rx 'sip show peers' — asterisk. -x , asterisk

, asterisk, :
sip reload — sip.conf
dialplan reload —
sip show channels —
sip set debug ip ip__peer'a — debug . .
core set verbose 3 — . .

Source: https://habr.com/ru/post/180265/


All Articles