📜 ⬆️ ⬇️

How to easily and simply teach your Asterisk to call through the desired operator

Greetings,% username%!

Today I would like to share a solution that allows you to teach your Asterisk to automatically route calls to the appropriate destinations without resorting to cumbersome regular expressions.

image
')
Practice shows that more and more companies are starting to think about their communication expenses. The lion's share of expenses is calls to mobile numbers. Hence, the task was born to process outgoing calls and send through the line where the call will be made free of charge or at the lowest cost.

In my case, it was necessary to marshutize calls to the home region of the Big Three operators through the corresponding SIM cards inserted into the GSM gateway. Instead of the selected operators, you can use any other directions by analogy with the subject.

OpenVox VoxStack VS-GW1202-4G acted as a gateway, in which SIM cards of operators known to you were inserted in advance and 3 trunks to Asterisk were configured.

Of course, there are a lot of ways to solve the problem, but I would like to dwell on a solution that I found optimal: automatic reconciliation of numbers from the MySQL database and further redirection to the desired line. The implementation is quite simple, although in some places it may seem clumsy.

You can break all the work into several stages:
  1. Create and populate database
  2. Prepare Asterisk to work with the database
  3. Write a dialplan to handle outgoing calls


Base preparation



First you need to create a separate database (optional):

CREATE DATABASE telcodes; 


Route access in our situation is better not to give, because there is no need for this, and no one needs a security hole in the form of a root login and password to MySQL in the open form in the configuration file. Therefore, we give access to an arbitrary user only to our database (in my case, the user: “mobile”, password: “heavypass”)

 CREATE DATABASE telcodes; GRANT ALL ON telcodes.* TO mobile@localhost IDENTIFIED BY 'mobile'; FLUSH PRIVILEGES; SET PASSWORD FOR 'mobile'@'localhost'=PASSWORD('heavypass'); 


Create a table:
Hidden text
 CREATE TABLE telcodes ( code smallint(3) NOT NULL, begin int(11) NOT NULL, end int(11) NOT NULL, ammount int (11) NOT NULL, operator varchar(100) NOT NULL, region varchar(100) NOT NULL) DEFAULT CHARSET=utf8; 


And now you can go directly to the filling. Everyone is free to choose for himself the way, I will focus on the following:

 wget http://www.rossvyaz.ru/docs/articles/Kody_DEF-9kh.csv cat Kody_DEF-9kh.csv | iconv -f pt154 -t utf8 >> telcodes.csv mysqlimport -umobile -p telcodes /usr/src/telcodes.csv --fields-terminated-by=';' --lines-terminated-by="\r\n" 

We download the list of codes of mobile operators from the Rossvyaz website, convert the encoding and fill it in our database. The path to the file is optional.

The base is full, but in order to avoid problems with encodings, we will make small changes: I need to select the numbers of the big three for calls in my home region, then I only change them, I mark the region as home , and change the names to beeline , mts and megafon, respectively:

 UPDATE telcodes set region = 'home',operator = 'beeline' where operator = '-' and region = '   '; UPDATE telcodes set region = 'home',operator = 'mts' where operator = ' ' and region = '   '; UPDATE telcodes set region = 'home',operator = 'megafon' where operator = '' and region = '   '; 


Database is ready to use.

Asterisk preparation



We will connect Asterisk with the database using ODBC, since I think this is a unified solution. First you need to rebuild Asterisk with ODBC support. Ubuntu Server 12.04 acts as an OS in my case.

Install unixodbc, unixodbc-dev and libmyodbc packages

 apt-get install unixodbc unixodbc-dev libmyodbc 


In the Asterisk source directory we run:
 ./configure && make menuselect 


We check that the res_odbc module is available and enabled, in the functions we need to check the availability of func_odbc . Then we save and execute:

 make && make install 


We look where drivers for ODBC lie
 # dpkg -L libmyodbc 

Hidden text
 /. /usr /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/odbc /usr/lib/x86_64-linux-gnu/odbc/libmyodbc.so #  /usr/share /usr/share/libmyodbc /usr/share/libmyodbc/odbcinst.ini /usr/share/doc /usr/share/doc/libmyodbc /usr/share/doc/libmyodbc/README.Debian /usr/share/doc/libmyodbc/changelog.Debian.gz /usr/share/doc/libmyodbc/examples /usr/share/doc/libmyodbc/examples/odbc.ini /usr/share/doc/libmyodbc/copyright 



We look where there are configuration files for ODBC
 #odbcinst -j 

Hidden text
 unixODBC 2.2.14 DRIVERS............: /etc/odbcinst.ini SYSTEM DATA SOURCES: /etc/odbc.ini FILE DATA SOURCES..: /etc/ODBCDataSources USER DATA SOURCES..: /root/.odbc.ini SQLULEN Size.......: 8 SQLLEN Size........: 8 SQLSETPOSIROW Size.: 8 



Edit /etc/odbcinst.ini , add an entry to the file:
Hidden text
 [MySQL] Description = MySQL driver Driver = /usr/lib/x86_64-linux-gnu/odbc/libmyodbc.so #   Setup = /usr/lib/x86_64-linux-gnu/odbc/libodbcmyS.so #    libodbcmyS.so CPTimeout = CPReuse = 



Describe the connection to the database in the /etc/odbc.ini file
Hidden text
 [telcodes-mysql] Driver = MySQL Description = MySQL telcodes via ODBC Server = localhost # ,    Port = 3306 User = mobile #   Password = heavypass #  Database = telcodes # ,    Socket = /var/run/mysqld/mysqld.sock 



And now Asterisk is directly acquainted with MySQL using ODBC. Making changes to /etc/asterisk/res_odbc.ini
Hidden text
 [telcodes] enabled => yes dsn => telcodes-mysql username => mobile password => heavypass pooling => no limit => 1 pre-connect => yes 



and write the module load in /etc/asterisk/modules.conf
 preload => res_odbc.so 


Now you can restart Asterisk itself, or just load the res_odbc.so module. Then in the CLI we execute the command:
 odbc show all 

Hidden text
aster * CLI> odbc show all

ODBC DSN Settings
- Name: telcodes
DSN: telcodes-mysql
Last connection attempt: 1970-01-01 03:00:00
Pooled: No
Connected: Yes


At this point, the second stage can be considered complete, we created and populated the database and made friends with Asterisk.

Writing a dialplan



Well, now you can proceed directly to writing a dialplan to handle outgoing calls.

Each dialed number is processed by a macro, as a result of which the line through which the call will be made will be determined. The argument to be passed to the macro will be the number to be dialed. The first character (8) will be cut off before it gets into the macro, then in the SQL query we will select further first 3 characters (123) for comparison with the operator code and the remaining 7 characters (4567890) to determine belonging to one or another numbering capacity.

All work with the database is written in the configuration file func_odbc.conf . Here we invent and compose functions for interacting with the database, and then use their result in the dialplan. Each section describes its function, the name of each section is usually filled in upper case.
In my case, it is necessary to determine the belonging of the number to the region and the operator and transfer the result for further processing by the macro.

Add to /etc/asterisk/func_odbc.conf entry
 [MOBILE] dsn=telcodes-mysql read=SELECT operator,region FROM `telcodes` WHERE ${ARG1:3:9} BETWEEN `begin` AND `end` AND `code`=${ARG1:0:3} 

It is worth remembering that the result of the query will be 2 values, separated by a comma: the operator serving the number, as well as the service region.

Well, now you can directly write the rules themselves number processing. In the example I will omit the extra rules, I will leave only what is relevant. All changes are made in the file /etc/asterisk/extensions.conf

Create a context for outgoing calls.
Hidden text
[from-users]

exten => _8XXXXX., 1, NoOp (Call from $ {CALLERID (num)} to $ {EXTEN})
same => n, Set (TARGETNO = $ {EXTEN})
same => n, Macro (seeknumber-odbc, $ {EXTEN: 1: 10})
same => n, Noop ($ {TRUNK_MOB})
same => n, Goto (to - $ {TRUNK_MOB}, $ {EXTEN}, 1)
same => n, hangup



We create contexts for calls to mobile service providers, as well as for the default provider. In setting up each trunk, I limited the number of simultaneous sessions to one and added call forwarding to the default trunk in case of busy or unavailable lines.

Hidden text
[to-prov-trunk]
exten => _8XXXXX., 1, NoOp (Call from $ {CALLERID (num)} to $ {EXTEN} other)
same => n, Dial (SIP / prov-trunk / $ {EXTEN}, 140, Tt)
same => n, hangup ()

[to-beeline]
exten => _8XXXXX., 1, NoOp (Call from $ {CALLERID (num)} to $ {EXTEN} beeline)
same => n, Dial (SIP / beeline / $ {EXTEN}, 140, Tt)
same => n, Goto (status, s - $ {DIALSTATUS}, 1)

[to-megafon]
exten => _8XXXXX., 1, NoOp (Call from $ {CALLERID (num)} to $ {EXTEN} megafon)
same => n, Dial (SIP / megafon / $ {EXTEN}, 140, Tt)
same => n, Goto (status, s - $ {DIALSTATUS}, 1)

[to-mts]
exten => _8XXXXX., 1, NoOp (Call from $ {CALLERID (num)} to $ {EXTEN} mts)
same => n, Dial (SIP / mts / $ {EXTEN}, 140, Tt)
same => n, Goto (status, s - $ {DIALSTATUS}, 1)

[status]
exten => s-ANSWER, 1, Hangup ()
exten => s-CHANUNAVAIL, 1, Goto (to-prov-trunk, $ {TARGETNO}, 1)
exten => s-BUSY, 1, Goto (to-prov-trunk, $ {TARGETNO}, 1)
exten => s -., 1, Hangup ()



Well, now the macro itself:
Hidden text
[macro-seeknumber-odbc]
exten => s, 1, NoOp (== tel nomber == $ {ARG1: 0: 3} == $ {ARG1: 3: 9} ==)
same => n, Set (result = $ {ODBC_MOBILE ()})
same => n, Set (operator = $ {CUT (result, \ ,, 1)})
same => n, Set (region = $ {CUT (result, \ ,, 2)})
same => n, NoOp (name of region = $ {region})
same => n, NoOp (name of operator = $ {operator})
same => n, Set (TRUNK_MOB = prov-trunk)
same => n, ExecIf ($ ["$ {operator}" = "beeline" & "$ {region}" = "home"]? Set (TRUNK_MOB = beeline))
same => n, ExecIf ($ ["$ {operator}" = "mts" & "$ {region}" = "home"]? Set (TRUNK_MOB = mts))
same => n, ExecIf ($ ["$ {operator}" = "megafon" & "$ {region}" = "home"]? Set (TRUNK_MOB = megafon))


The result was, in my opinion, a good unified solution for distributing calls to the right directions by phone number. In addition, I can say that it can be automated even more by writing a bash script to download and process fresh databases from the RosSvyaz website and add it to the crontab for a monthly upgrade, but this will be considered homework;)

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


All Articles