今日は、面倒な正規表現に頼ることなく、適切な方向に通話を自動的にルーティングするようにアスタリスクを教えることができるソリューションを共有したいと思います。
実践は、ますます多くの企業が通信コストについて考え始めていることを示しています。 この場合の費用の大部分は、携帯電話番号への通話です。 ここから、発信通話を処理し、通話が無料または最低コストで行われる回線にルーティングするタスクが生まれました。
私の場合、GSMゲートウェイに挿入された対応するSIMカードを介して、Big Threeオペレーターのホーム地域に通話をルーティングする必要がありました。 選択した演算子の代わりに、主題との類推によって他の方向を使用できます。
OpenVox VoxStack VS-GW1202-4Gはゲートウェイとして機能し、既知のオペレーターのSIMカードが以前に挿入され、アスタリスクへの3つのトランクが構成されていました。
もちろん、この問題を解決する方法はたくさんありますが、MySQLデータベースからの数値の自動調整と、目的の行へのリダイレクションという、最適と思われる解決策について詳しく説明します。 実装は非常に単純ですが、一部の場所ではいように見えるかもしれません。
すべての作業をいくつかの段階に分けることができます。
- データベースを作成して入力する
- データベースを操作するためにアスタリスクを準備する
- 発信通話を処理するためのダイヤルプランを書く
ベース準備
最初に、別のデータベースを作成する必要があります(オプション):
CREATE DATABASE telcodes;
私たちの状況ではルートへのアクセスは与えないほうがいいです。なぜなら これは必要ではありません。また、設定ファイルにルートログインの形式のセキュリティホールとオープン形式のMySQLパスワードは必要ありません。 したがって、データベースへのアクセスのみを任意のユーザーに許可します(私の場合、ユーザー: "mobile"、パスワード: "heavypass")
CREATE DATABASE telcodes; GRANT ALL ON telcodes.* TO mobile@localhost IDENTIFIED BY 'mobile'; FLUSH PRIVILEGES; SET PASSWORD FOR 'mobile'@'localhost'=PASSWORD('heavypass');
テーブルを作成します。
非表示のテキスト
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;
そして今、あなたは詰め物に直接行くことができます。 誰もが自分の方法を自由に選択できます。私は次のことに焦点を当てます。
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"
RossvyazのWebサイトからモバイルオペレーターのコードのリストを取り出し、エンコードを変換してデータベースにアップロードします。 ファイルへのパスはオプションです。
データベースはいっぱいですが、エンコードの問題を回避するために、小さな変更を行います。 ホームリージョンのコールにビッグ3番号を選択する必要があります。次に、それらを変更し、リージョンをhomeとしてマークし、名前をそれぞれbeeline 、 mtsおよびmegafonに変更します。
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 = ' ';
データベースを使用する準備ができました。
アスタリスクの準備
ODBCを使用して、アスタリスクをデータベースに接続します。 これは統一されたソリューションだと思います。 まず、ODBCサポートを使用してアスタリスクを再構築する必要があります。 私の場合のOSの品質はUbuntu Server 12.04です。
パッケージunixodbc、unixodbc-devおよびlibmyodbcを配置します
apt-get install unixodbc unixodbc-dev libmyodbc
アスタリスクのソースがあるディレクトリで、次のことを行います。
./configure && make menuselect
func_odbcの可用性を確認する必要がある関数で、 res_odbcモジュールが使用可能で有効になっていることを確認します。 次に、保存して実行します。
make && make install
ODBCのドライバーがある場所を探します
# dpkg -L libmyodbc
非表示のテキスト
/. /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
ODBCの構成ファイルがある場所を探します
#odbcinst -j
非表示のテキスト
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
/etc/odbcinst.iniを編集して、ファイルにエントリを追加します。
非表示のテキスト
[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 =
/etc/odbc.iniファイルにデータベースへの接続を記述します
非表示のテキスト
[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
そして現在、ODBCを使用してMySQLにアスタリスクを直接導入しています。 /etc/asterisk/res_odbc.iniに変更を加える
非表示のテキスト
[telcodes] enabled => yes dsn => telcodes-mysql username => mobile password => heavypass pooling => no limit => 1 pre-connect => yes
/etc/asterisk/modules.confにモジュールロードを書き込みます
preload => res_odbc.so
これで、Asterisk自体を再起動するか、 res_odbc.soモジュールをロードすることができます。 次に、CLIでコマンドを実行します。
odbc show all
非表示のテキスト
アスター* CLI> odbcすべて表示
ODBC DSN設定
-名前:telcodes
DSN:telcodes-mysql
最後の接続試行:1970-01-01 03:00:00
プール済み:いいえ
接続済み:はい
ODBC DSN設定
-名前:telcodes
DSN:telcodes-mysql
最後の接続試行:1970-01-01 03:00:00
プール済み:いいえ
接続済み:はい
この時点で、2番目の段階は完了したと見なすことができます。データベースを作成して入力し、アスタリスクと友達になりました。
ダイヤルプラン作成
さて、発信コールを処理するためのダイヤルプランの直接作成を開始できます。
ダイヤルされた各番号はマクロによって処理され、その結果、呼び出しが行われる回線が決定されます。 ダイヤルされた番号は、マクロに渡される引数として機能します。 マクロを入力する前でも最初の文字(8)は切り捨てられます。その後、SQLクエリでは、演算子コードと比較するために最初の3文字(123)と残りの7文字(4567890)を選択して、特定の番号付け能力に属するかどうかを判断します。
すべてのデータベース操作はfunc_odbc.conf構成ファイルに登録されます。 ここで、データベースとやり取りするための関数を作成して作成し、その結果をダイヤルプランで使用します。 各セクションはその機能を説明し、各セクションの名前は通常大文字で埋められます。
私の場合、領域と演算子に属する番号を決定し、マクロによるさらなる処理のために結果を転送する必要があります。
/etc/asterisk/func_odbc.confにエントリを追加します
[MOBILE] dsn=telcodes-mysql read=SELECT operator,region FROM `telcodes` WHERE ${ARG1:3:9} BETWEEN `begin` AND `end` AND `code`=${ARG1:0:3}
クエリの結果は、コンマで区切られた2つの値になることを覚えておく価値があります。この番号を提供する演算子とサービス地域です。
さて、これで数値処理ルール自体を直接記述できます。 この例では、不要なルールを省略し、関連するもののみを残します。 すべての変更は、ファイル/etc/asterisk/extensions.confで行われます
発信通話のコンテキストを作成します。
非表示のテキスト
[from-users]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN}への呼び出し)
同じ=> n、設定(TARGETNO = $ {EXTEN})
同じ=> n、マクロ(seeknumber-odbc、$ {EXTEN:1:10})
同じ=> n、Noop($ {TRUNK_MOB})
同じ=> n、Goto(to-$ {TRUNK_MOB}、$ {EXTEN}、1)
同じ=> n、ハングアップ
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN}への呼び出し)
同じ=> n、設定(TARGETNO = $ {EXTEN})
同じ=> n、マクロ(seeknumber-odbc、$ {EXTEN:1:10})
同じ=> n、Noop($ {TRUNK_MOB})
同じ=> n、Goto(to-$ {TRUNK_MOB}、$ {EXTEN}、1)
同じ=> n、ハングアップ
デフォルトのプロバイダーだけでなく、モバイルプロバイダーへの呼び出しのコンテキストも作成します。 各トランクの構成では、同時セッションの数を1つに制限し、回線がビジーまたは使用不可の場合にデフォルトでコール転送をトランクに追加しました。
非表示のテキスト
[to-prov-trunk]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN}その他への呼び出し)
同じ=> n、ダイヤル(SIP / prov-trunk / $ {EXTEN}、140、Tt)
同じ=> n、ハングアップ()
[to-beeline]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN} beelineへの呼び出し)
同じ=> n、ダイヤル(SIP /ビーライン/ $ {EXTEN}、140、Tt)
同じ=> n、Goto(ステータス、s-$ {DIALSTATUS}、1)
[メガホンへ]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN}メガフォンへの呼び出し)
同じ=> n、ダイヤル(SIP / megafon / $ {EXTEN}、140、Tt)
同じ=> n、Goto(ステータス、s-$ {DIALSTATUS}、1)
[to-mts]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN} mtsまでの呼び出し)
同じ=> n、ダイヤル(SIP / mts / $ {EXTEN}、140、Tt)
同じ=> n、Goto(ステータス、s-$ {DIALSTATUS}、1)
[ステータス]
exten => s-ANSWER、1、ハングアップ()
exten => s-CHANUNAVAIL、1、Goto(to-prov-trunk、$ {TARGETNO}、1)
exten => s-BUSY、1、Goto(to-prov-trunk、$ {TARGETNO}、1)
exten => s-。、1、Hangup()
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN}その他への呼び出し)
同じ=> n、ダイヤル(SIP / prov-trunk / $ {EXTEN}、140、Tt)
同じ=> n、ハングアップ()
[to-beeline]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN} beelineへの呼び出し)
同じ=> n、ダイヤル(SIP /ビーライン/ $ {EXTEN}、140、Tt)
同じ=> n、Goto(ステータス、s-$ {DIALSTATUS}、1)
[メガホンへ]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN}メガフォンへの呼び出し)
同じ=> n、ダイヤル(SIP / megafon / $ {EXTEN}、140、Tt)
同じ=> n、Goto(ステータス、s-$ {DIALSTATUS}、1)
[to-mts]
exten => _8XXXXX。、1、NoOp($ {CALLERID(num)}から$ {EXTEN} mtsまでの呼び出し)
同じ=> n、ダイヤル(SIP / mts / $ {EXTEN}、140、Tt)
同じ=> n、Goto(ステータス、s-$ {DIALSTATUS}、1)
[ステータス]
exten => s-ANSWER、1、ハングアップ()
exten => s-CHANUNAVAIL、1、Goto(to-prov-trunk、$ {TARGETNO}、1)
exten => s-BUSY、1、Goto(to-prov-trunk、$ {TARGETNO}、1)
exten => s-。、1、Hangup()
さて、今マクロ自体:
非表示のテキスト
[マクロシーク番号-odbc]
exten => s、1、NoOp(== tel nomber == $ {ARG1:0:3} == $ {ARG1:3:9} ==)
同じ=> n、設定(結果= $ {ODBC_MOBILE()})
same => n、Set(operator = $ {CUT(result、\ ,, 1)})
same => n、Set(region = $ {CUT(result、\ ,, 2)})
同じ=> n、NoOp(地域の名前= $ {region})
同じ=> n、NoOp(演算子の名前= $ {演算子})
同じ=> n、設定(TRUNK_MOB = prov-trunk)
同じ=> n、ExecIf($ ["$ {operator}" = "beeline"& "$ {region}" = "home"]?Set(TRUNK_MOB = beeline))
same => n、ExecIf($ ["$ {operator}" = "mts"& "$ {region}" = "home"]?Set(TRUNK_MOB = mts))
同じ=> n、ExecIf($ ["$ {operator}" = "megafon"& "$ {region}" = "home"]?セット(TRUNK_MOB = megafon))
exten => s、1、NoOp(== tel nomber == $ {ARG1:0:3} == $ {ARG1:3:9} ==)
同じ=> n、設定(結果= $ {ODBC_MOBILE()})
same => n、Set(operator = $ {CUT(result、\ ,, 1)})
same => n、Set(region = $ {CUT(result、\ ,, 2)})
同じ=> n、NoOp(地域の名前= $ {region})
同じ=> n、NoOp(演算子の名前= $ {演算子})
同じ=> n、設定(TRUNK_MOB = prov-trunk)
同じ=> n、ExecIf($ ["$ {operator}" = "beeline"& "$ {region}" = "home"]?Set(TRUNK_MOB = beeline))
same => n、ExecIf($ ["$ {operator}" = "mts"& "$ {region}" = "home"]?Set(TRUNK_MOB = mts))
同じ=> n、ExecIf($ ["$ {operator}" = "megafon"& "$ {region}" = "home"]?セット(TRUNK_MOB = megafon))
その結果、私の意見では、電話番号ごとに目的の方向に通話を配信するための優れた統合ソリューションであることが判明しました。 さらに、RosSvyaz Webサイトから新しいデータベースをダウンロードして処理するbashスクリプトを記述し、毎月のアップグレードのためにcrontabに追加することで、さらに自動化できると言えますが、これは宿題と見なされます;)