大規模な開発会社では、遅かれ早かれ、電話交換の機能を拡張し、従来の電話からIPに移行するという問題が生じます。
2011年の遠い春に、当社は外部と内部の回線を常に拡張する必要があり、古いPanasonic KX-TA624のポート数が静的に設定され、拡張できなかったため、このような問題に直面しました。 他の都市にオフィスを開設し、他の都市に統一された顧客サービスを導入したことも、質的な変化を促しました。
参照条件
最終製品には次の特性が必要です。
1)多数(この場合は少なくとも100)の外部および内部回線があり、拡張の準備ができている。
2)営業時間中にユーザーに挨拶し、誰も配置されていない勤務時間外に電話したことを報告できる。
3)応答しない/通話中/利用不可の場合のコール転送タイムアウトを個別に設定する必要があります。
4)キューを提供する必要があります。 キュー-番号のグループ。特定のルールに従って発生するコールの分布。
5)メッセージログ(テキストと音声の両方)を記録します。
6)外部コールへの権利の分配について柔軟なポリシーを持っている。 内線番号のみを呼び出すことができるユーザーを提供する必要があります。 都市番号へ。 任意の番号に。
7)時刻に応じて、1つまたは別の番号に電話します。
悪い経験
最初の選択はPlanet ipx-1900に落ちました。 仕様はここにあります:
www.planet.com.ru/en/product/product_keyf.php?id=18500
とりわけ、サポートが宣言されています:
•自動インフォーマー(AA)
•インタラクティブ音声応答(IVR)
•通話詳細レポート(CDR)
実際には、これらのパラメーターはいずれも機能しません。 Planetのサポートは質問を無視しました。 標準的な手段でこれに8800の鉄をつけることは不可能でした。
もっと深く選択しなければなりませんでした。 このPBXには、comポートとtelnetがあり、接続するとログインとパスワードが要求されます。 Planetの技術サポートは、ログインの詳細の提供を拒否しました...より正確には、リクエストを無視しました。 デバイスのファームウェアのページは次の場所にあります。
planet.com.ru/en/support/download2.php?id=18500&file_type=65&prod_model=IPX-1900
ファームウェアはアーカイブに過ぎないことが判明しました。
$ mkdir untar && cd untar && tar xvf ../FW-IPX1900_1.16.8.dat rootfs.jffs2 vmImage start_install.sh aimage.tar.gz
最も興味深いのはstart_install.shでした。このスクリプトは、ファームウェアをデバイスにダウンロードした直後に実行されます。 行の直後:
#!/bin/sh
次の行を追加します。
useradd -groot -proot toor
すべてをアーカイブに戻し、ファームウェアをステーションにダウンロードします。
すべてがうまくいけば、com-portまたはtelnet経由でステーションにログインできます。
sterAsterix 1.4を搭載したClinuxが内部で発見されました
そして、ステーションの稼働状態へのドーピングが始まりました。 変更のリストを投稿することはありません。それは、今では取り返しのつかないほど失われているからです。
ステーションのコンソールにアクセスしたおかげで、技術仕様のp.1-4を実装することができました。 そして、ステーション8800で追加します。
1)ステーションと外部ポートの絶え間ないハング。
2)夜間の毎日のステーションの再起動。
3)再起動後、ステーションが一時サーバーと同期できなかった場合があり、実際には時間が機能しているにもかかわらず、時間が機能していないことをクライアントに通知しました。
しかし、この形式では、電話がラグタイムに約1年半存在していました。 それにもかかわらず、リーダーシップは、技術的なタスクを遂行するという夢を実現することをテーマに、技術サポートを「キック」し続け(はい、技術サポートでした)、技術サポートが生まれました。
鉄
惑星から通常のサーバーへの移行時に、自由に使用できました:
1)複数の惑星ata-150s音声ゲートウェイ(2 fxsポート);
2)linksys spa-3000(1fxo + 1 fxs port)-2個;
3)アナログ電話の束(Panasonicレガシー);
4)VoIP電話dlink-dph150s、dlink-dph150se。
5)Debian OSを搭載したサーバー。
6)サージプロテクター、ツイストペア、スイッチ:)
鉄の主観的レビュー
VoIP dlinkはうまく機能します。 凍結はほとんどありません。 結婚したいくつかのモデルがありましたが、それらは疑いもなく新しいものに置き換えられました。
Linksysは悪くありません。 時々フリーズが発生し、音声ゲートウェイ自体ではなく、その上のFXOポートがハングします。 残念ながら、それは顧客のリクエストでのみ検出されます。
Planet ata-150s-悪い。 頻繁にフリーズが発生し、定期的にハンドセットにノイズがあります。 再起動のみが役立ちます。 彼らはパックで購入された-だからあなたは何で作業する必要があります。
アスタリスクをインストールする
残念ながら、debianのアスタリスクインストールログは保存されませんでした。 したがって、Ubuntu 12.04のインストール手順はこの記事用に翻訳されます。 概して、ほとんど違いはありません。たとえば、Asterisk 1.8はメインのdebianリポジトリには含まれていませんが、バックポートには含まれています。
作業には、次のパッケージを使用します。
1アスタリスク-アスタリスク1.8
2 libasterisk-agi-perl-perl用のAGIモジュール。 これについては後で詳しく説明します。
3 asterisk-mysql-テキストファイルではなくデータベースに統計を保存できるアスタリスク拡張
$ sudo aptitude install asterisk libasterisk-agi-perl asterisk-mysql mysql-server
通話履歴の設定
1)データベースのルートから、新しいデータベースとユーザーを作成します。
CREATE DATABASE astr; GRANT ALL PRIVILEGES ON astr.* TO 'asterisk'@'localhost' IDENTIFIED BY 'super-pass' WITH GRANT OPTION; EXIT;
2)作成したユーザーの下に移動します。
$ mysql -uasterisk -psuper-pass astr
3)テーブルを作成します。
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)アスタリスク設定ディレクトリに移動し(これ以降のすべてのアクションはスーパーユーザーに代わって実行する必要があります)、念のため次のすべてのコンテンツのコピーを作成します。
# cp -r ../asterisk/ ~/asterisk_config # echo '' > cdr_mysql.conf && mcedit cdr_mysql.conf
私たちと一緒にそれはフォームを持っています:
[global] hostname=localhost dbname=astr table=cdr password=super-pass user=asterisk [columns] alias start => calldate
cdr.conf構成は変更されていません。
発信ユーザーとコンテキスト
ユーザーからの発信通話には、4つのコンテキストがあります。
1 phone_int-デフォルト値。 3桁の内部番号のみに電話をかけることができるユーザー。
2 phone_local-ユーザーは7桁の都市内番号を呼び出すことができます。
3 phone_long_d-これらのユーザーは国内での通話を許可されています。
4 phone_too_long_d-国際電話。
コンテキストは互いに含まれています。 phone_too_long_dユーザーは、従業員の内部番号と市内の両方に電話をかけることができます。
続行:
1)sip.confをいくつかに分けましょう:
# mcedit sip.conf #include sip_general.conf #include sip_trunk.conf #include sip_internal.conf
sip_general.conf-アスタリスクのメイン設定。
sip_internal.conf-ユーザーの内部番号。
sip_trunk.conf-外部回線。
2)sip_internal.confに3つの数値を設定する例:
[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>
ユーザー101は、ロシア内での呼び出しを許可されています(コンテキスト= phone_long_d)。 ユーザー112(phone_local)は市内で呼び出すことができます。 106はどこにでも電話できます。 ユーザー495は、内部番号への呼び出しのみが許可されます(コンテキストが指定されていない場合、phone_intコンテキストが使用されます)。 秘密フィールドは、認証に使用されるパスワードです。
着信回線
メイン設定の例:
# 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
トランクのセットアップ:
# 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
example_num行は、リモートステーションでの認証と登録を使用して完了します。 この行には次のように書かれていることに注意してください。
register = example_num:pass_for_example_num:example_num@proxyreg_time/example_num
sip_general.confで。
pstn_beeline行は登録を必要としません。実際、これはlinksys spa 3000のfxoポートを介して接続される「土地」行の1つですが、それについては後で詳しく説明します。
RTKライン-ここでは承認も登録も必要ありません。 ステーションでは、ユーザーとIP(ホストフィールド)のみが必要で、そこから呼び出しが行われます。 これは番号8800です。着信電話のみが提供されます。 Rostelecomに関しては、ユーザー名はルート番号です。
すべての着信コールのコンテキストは1-from_externalです。
ダイヤルプラン(ダイヤルプラン)-通話ルーティング
PBXの作業で最も興味深いのは、ダイヤルプランです。 ダイヤルプランは、説明されているルールに従ってコールをルーティングします。 だから:
1)発信通話。
# 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 ; ======== ==============
文字列の解析:
exten => _0[1-79]XXXXXX, 2, Dial(SIP/${EXTEN:1}@pstn_beeline&SIP/${EXTEN:1}@example_num)
_0 [1-79] XXXXXX-ダイヤル番号のマスク。 詳細はこちら( voip.rus.net/tiki-index.php?page=Asterisk+Dialplan+Patterns )
0は最初に来た数字です
[1-79]-2番目の数字は8以外の任意の数字です。 これは都市間への出口です
XXXXXX-任意の7桁
Xは0〜9の任意の数に一致します
Zは1から9までの任意の数に一致します
Nは2から9までの任意の数に一致します
2-優先度。このアクションが2番目に連続して実行されることを意味します。
ダイヤルは、最も使用されているアスタリスクアプリケーションの1つです。 特定の回線を介して番号を呼び出すように設計されています。 このアプリケーションの詳細はこちら( voip.rus.net/tiki-index.php?page=Asterisk+cmd+Dial )
SIP / $ {EXTEN:1}-一種の正規表現。 たとえば、03799039をダイヤルすると、番号3799039がチャネルに送信されます。
@pstn_beeline-呼び出しが行われるチャネル。
&SIP / $ {EXTEN:1} @example_num-ビーラインがビジーであるか利用できない場合に通話が行われる別のチャネル。
; [phone_local] include => phone_int include => out_local
phone_localコンテキストを取得するには、2つのコンテキスト(phone_intおよびout_local)を含める必要があります。 そのようなコンテキストに接続しているユーザー(上記の例では、これはユーザー112)には、固定電話番号への呼び出しが許可されます。
2)着信コールは次のように処理されます。
; ========= ============== [from_external] exten => _X., 1, Macro(dial) exten => s, 1, Macro(dial) ; ========= ==============
3)マクロ
マクロは基本的に関数です。 コンテキストに応じて使用するマクロにパラメーターを渡すことができます。 次のようにマクロにアクセスできます。
exten => _[1-79]XX, n, Macro(int-dial,${EXTEN})
_ [1-9] XX-ダイヤルする番号。
nは優先順位です。
マクロは、マクロアプリケーションそのものです。
int-dialはマクロの名前です。
$ {EXTEN}-マクロに渡されるパラメーター(この場合、電話番号)
マクロの詳細については、こちらをご覧ください( voip.rus.net/tiki-index.php?page=Asterisk+cmd+Macro&highlight=Macro ())。
ダイヤルに使用するマクロは次のとおりです。
; =============================== ; ; /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() ; ===============================
ほとんどすべてのコンテキストで、AGIアプリケーションが使用されます。 アプリケーションの詳細については、こちらをご覧ください( voip.rus.net/tiki-index.php?page=Asterisk+cmd+AGI&highlight=AGI ())。
このアプリケーションの使用方法について-次のセクション。
AGIあいさつ
チャレンジ。
次のように機能するメニューを実装します。
1)週末と非稼働時間-営業時間外に顧客が電話したメッセージ。 仕事の時間を表明する。
2)勤務時間は挨拶です。 時間に応じて、クライアントを
•秘書(クライアントが営業時間中に転倒した場合)。
•その他の勤務時間中のテクニカルサポート
勤務時間は月曜日から金曜日の9から21です。 オフィスは平日は9時から13時まで、14時から18時まで営業しています(オフィスランチでは1時から2時まで)。
問題を解決するためのツール。
この問題を解決するために、AGIツールが選択されました。
AGI(Asterisk Gateway Interface)は、他のプログラミング言語を使用してアスタリスクの機能を拡張できる、Asteriskに組み込まれた外部スクリプト(httpサーバーのCGIと同様)を実行する方法です。
Perlは開発言語として選ばれました-あらゆる問題を解決するための普遍的なツールとして。 :-)
cpanには、アスタリスク:: AGIモジュールsearch.cpan.org/~jamesgol/asterisk-perl-1.03/lib/Asterisk/AGI.pmがあります。
長所AGI-開発の容易さ。 柔軟性。 短所-サーバーの負荷が大幅に増加します。 スクリプトは呼び出しごとにコンパイルされ、キャッシュされません。 インターネット上でAGIはバグだと書いていますが、私たちの仕事(〜0.5年)の間、これに問題はありませんでした。 計算能力にも問題はありません。
問題の解決策。
ここですべての着信コールを転送します(前のセクションを参照)。
exten => s, 1, AGI(/var/lib/asterisk/agi/ivr.pl)
着信コールハンドラ(/var/lib/asterisk/agi/ivr.pl)は次のようになります。
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__
ファイル/var/lib/asterisk/agi/schedule.confには、「例外的な」時間、つまり 休日や短縮日など、オフィスが通常どおり機能していない時間。 例:
#1-日付(day.month)
#2-曜日(オプションのパラメーター)
#0非稼働または空
#1-通常の動作([9,13,18,21])または配列
#2.1-オフィス開始時間(9)
#2.2-昼食(13、つまり13から14)
#2.3-オフィスのシャットダウン時間(18)
#2.4-テクニカルサポートの完了時間
#日付はゼロなしで入力されます。 06.11-機能しません。 6.11-作品
29.12 [9,11,17,20]
12/31
12月29日[9,11,17,20](12月29日)は短縮日です。 オフィスは9から17まで開いています。 11から12までの昼食。 テクニカルサポートは20まで機能します。
12/31-休業日。
AGIコールハンドラー
チャレンジ。
番号を呼び出すとき、呼び出しは特定のタイムアウト/ビジー/無応答/別の番号への利用不可を介してリダイレクトされる必要があります(原則として、これはキューの1つ)。 「タイムアウト」と「その他の数値」は動的変数です。数値ごとに個別に設定できます。
ツール。
最後のセクションのように-AGI。
問題の解決策。
従業員の内部番号は、mysqlデータベースによってusersテーブルに保存されます。
テーブルを作成します。
CREATE TABLE `users` ( `num` int(11) PRIMARY KEY NOT NULL, `timeout` tinyint(4) NOT NULL DEFAULT '10', `queue` int(11) DEFAULT NULL );
num-従業員の電話番号。
timeout-コールが転送されるまでの秒単位の時間。
queue-呼び出しが転送されるキューの番号。
番号のエントリを追加します。
INSERT INTO `users` VALUES (101,10,300), (106,20,0), (112,20,0);
何が起こったかを確認してください:
SELECT * FROMユーザー;
+ ----- + --------- + ------- +
| num | タイムアウト| キュー|
+ ----- + --------- + ------- +
| 101 | 10 | 300 |
| 106 | 20 | 0 |
| 112 | 20 | 0 |
+ ----- + --------- + ------- +
101に電話すると、10秒後に300番に電話がかかります(このテクニカルサポート番号があります)。 112または106に電話をかけると、通話はどこにも行きませんが、20秒で終了します。
ハンドラーには次のようにアクセスできます(AGI(/var/lib/asterisk/agi/dial_internal.pl、$ {ARG1})):
ダイヤルプランでは:
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()
電話番号はマクロ変数$ {EXTEN}に分類され、$ {ARG1}を使用してハンドラー/var/lib/asterisk/agi/dial_internal.plに渡されます。
ハンドラーコード:
#!/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、
つまり./year/month/day/year_month_number.hours_minutes_seconds.number_of_existing_call.wav
ファイル名は、すべてのファイルを1つのディレクトリに配置し、特定のパラメーター(電話番号/時間など)で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.confと呼ばれます。テクニカルサポート(300番)とアカウンティング(301)の2行があります。
[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
キュー機能の詳細については、
www.voip-info.org / wiki / view / Asterisk + config + queues.confをご覧ください。linksysspa
-3000
Taskを介して外部回線を設定します。
Linksys spa-3000には、1つのfxoポートと1つのfxがあります。音声ゲートウェイに接続されている番号(以降、latと呼びます)に電話をかける場合、呼び出しはfxsポートに送信する必要があります(そこにFAXがあります)。同時に、
1)オフィスからfxoポートに接続された回線を介して電話をかけることができるはずです。
2)通話が別の回線を経由した場合、FAX番号に切り替えます。
3)ステーションに接続された任意の回線を介してファックスから呼び出します。
解決策。
計画を実装するには、g.shを構成する必要があります。次のように。管理者ログインページ->詳細設定-> PSTN行に移動します:
プロキシ:10.0.0.5#(ipステーション)
アウトバウンドプロキシ:10.0.0.5#(ipステーション)
登録:はい
ユーザーID:pstn_beeline
パスワード:pass_for_beeline
#発信するにはすぐにファクスにステーションをバイパスして行動しました。
ダイヤルプラン2:(<:@ gw0>)
PSTN発信者のデフォルトDP:2
ステーションでの外部回線の構成は、外部回線(pstn_beeline)セクションで説明されています。
106ファックス番号:
プロキシ:10.0.0.5#(IPステーション)
アウトバウンドプロキシ:10.0.0.5#(IPステーション)
登録:はい
ユーザーID:106
パスワード:pass_for_fax
ステーションでの内線番号の設定については、発信コールのユーザーとコンテキストのセクションで説明してい
ます (106)便利なコマンドアスタリスク-r-
コマンドライン
アスタリスク-rx 'sip show peers' へのアクセス-アスタリスクコンソールを入力せずにコンソールに接続ユーザーのリストを表示-xスイッチ
を使用すると、最もよく使用するコマンド、アスタリスクコンソール、
sip reload-sip.confからの情報の
再読み込みconfig dialplan reload- ダイヤルプランの再読み込み
sip show channels-作成されたチャンネルのリスト
sip set debug ip ip_peer_a_a-特定のチャネルのデバッグを有効にします。ステーションとリモートステーションの間を通過するパケットを表示します。
コアセットの詳細なデバッグ3に不可欠-デバッグモードを有効にします。チャネル作成中に実行されているアプリケーションを示します。