Asteriskを触りはじめてから2年くらいのエンジニアです。
ダイアルプランからCDR(call detail records)以外にも、カスタム情報をDBに保存したい時があると思います。
やり方としてはAGIを使えばいろいろな言語で実装できますが、今回はAsteriskに実装されているODBCファンクションを利用したいと思います。
注意点として、AsteriskのMYSQLファンクションは最新バージョンではサポートされていないので使わないほうが良いです。
目次
前提条件
以下の構成で作業を行います。
Asteriskはメジャーバージョンの違いがなければ問題ないと思います。
mysqlはバージョンの差異による影響はほとんどなさそうです。
Asterisk, mysql,に加えて、ODBCのパッケージ諸々が必要です。
以下のコマンドを実行して追加します。
1 2 3 |
# sudo yum install unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel # sudo yum install mysql-connector-odbc |
ODBCドライバを設定する
新しいバージョンのUnixODBCをインストールしていれば、以下の内容に近い、/etc/odbcinst.iniが自動で作成されています。
1 2 3 4 5 6 7 8 9 10 11 |
# Driver from the mysql-connector-odbc package # Setup from the unixODBC package [MySQL] Description = ODBC for MySQL Driver = /usr/lib/libmyodbc5.so Setup = /usr/lib/libodbcmyS.so Driver64 = /usr/lib64/libmyodbc5.so Setup64 = /usr/lib64/libodbcmyS.so FileUsage = 1 Pooling = Yes CPTimeout = 120 |
このファイルは特に変更する必要はありません。
Mysql ODBCコネクタの設定をする
ODBCがmysqlに接続をする具体的な設定を行います。
以下にならって設定をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[asterisk-connector] #説明 Description=MySQL connection to 'asterisk' database #上記で作成したドライバ名を使用する driver=MySQL #mysqlのホスト server=localhost #database名 database=asterisk #mysqlのポート Port=3306 #mysqlのソケット Socket=/var/lib/mysql/mysql.sock #charset Charset=utf8 |
ここで重要なポイントは、driverにodbcinst.iniで設定したドライバ名を指定することです。
それ以外は環境に合わせて入力してください。
AsteriskのODBC接続設定
上記で作成したODBCコネクタをAsterisk上で利用する設定をします。
設定ファイルは、/etc/asterisk/res_odbc.confです。
freepbxの場合、/etc/asterisk/res_odbc_custom.confです。
1 2 3 4 5 6 7 8 9 10 11 |
[asteriskodbc] #yesで有効に enabled=>yes #ODBCコネクタ名を指定 dsn=>asterisk-connector #DB接続ユーザー username=>user #DB接続パスワード password=>password #接続先DB名 database=>asterisk |
ここで重要なポイントは、dsnに上記で設定したODBCコネクタ名を指定することです。
enabledはyesに設定して、その他は環境に合わせて設定してください。
ODBCファンクションの設定
ダイアルプランから呼び出し、DBの読み書きを行う関数を定義します。
設定ファイルは、/etc/asterisk/func_odbc.confです。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#関数名 [INSERT_RECORD] #dsn名を指定 dsn=asteriskodbc #書き込みを行うSQL writesql=INSERT INTO uui(uui) VALUES('${SQL_ESC(${VAL1})}') #関数名 [SELECT_RECORD] #dsn名を指定 dsn=asteriskodbc #書き込みを行うSQL readsql=SELECT column FROM table WHERE id=${ARG1} |
上記で書き込み、読み込みの各関数を定義しました。
func_odbc.confで設定するdsn名は、AsteriskのODBC接続設定で設定したものを利用します。
ダイアルプランからODBCファンクションを呼び出す
下記のダイアルプランでODBCファンクションを呼び出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[odbctest] exten => s,1,Answer() same => n,NoOp(ODBC test dayo) same => n,Set(ODBC_INSERT_RECORD()=${FROMEXTEN}) same => n,Set(RET=${ODBC_SELECT_RECORD(1)}) same => n,NoOp(select result is ${RET}) 結果↓ -- Executing [s@odbctest:1] Answer("SIP/1234o-00000024", "") in new stack -- Executing [s@odbctest:2] NoOp("SIP/1234o-00000024", "ODBC test dayo") in new stack -- Executing [s@odbctest:3] Set("SIP/1234o-00000022", "ODBC_RECORD_UUI()=0338636754") in new stack -- Executing [s@odbctest:4] Set("SIP/1234o-00000022", "RET=test") in new stack -- Executing [s@odbctest:5] NoOp("SIP/1234o-00000022", "select result is test") in new stack |
呼び出すときは、
ODBC_関数名
で呼び出すことができます。
トラブルシューティング
作成したODBCファンクションが呼び出されない時
具体的には、以下のエラーが出たときです。
1 |
ERROR[6984][C-00000020]: pbx_functions.c:608 ast_func_read: Function ODBC_SELECT_RECORD not registered |
この場合、作成したファンクションがodbcモジュールで認識されていないので、
以下のコマンドでモジュールをリロードする必要があります。
1 2 |
# asterisk -rvvvvv $ module reload func_odbc.so |
AsteriskのODBC接続設定を確認したい時
以下コマンドで読み込まれているODBC接続設定を確認することができます。
1 2 3 4 5 6 7 8 9 10 |
# asterisk -rvvvv $ odbc show ODBC DSN Settings ----------------- Name: asteriskodbc DSN: asterisk-connector Last connection attempt: 1970-01-01 09:00:00 Number of active connections: 1 (out of 1) |
また、
odbc read
もしくは
odbc write
コマンドで読み込まれている定義された関数を確認することができます。
1 2 3 4 5 6 7 8 9 10 |
# asterisk -rvvvv $ odbc read show write $ odbc read ODBC_INSERT_RECORD ODBC_SELECT_RECORD #定義されている関数の一覧 $ odbc read ODBC_SELECT_RECORD Usage: odbc read <name> <args> [exec] Evaluates the SQL provided in the ODBC function <name>, and optionally executes the function. This function is intended for testing purposes. Remember to quote arguments containing spaces. |
おまけ:一度に複数のカラムを更新する
ODBCファンクションの構文は、以下のようになっています。
1 |
ODBC_functionname(<arg1>[...[,<argN>]])[=[val1][...[,valN]] |
わかりづらいのは、関数の引数として与えたargNも、右オペランドで与えたval1も関数内で利用できる変数だということです。
1 2 3 4 5 6 7 8 9 10 11 12 |
# func_odbc.conf [INSERT_RECORD] dsn=asteriskodbc writesql=INSERT INTO uui(uui, description) VALUES('${SQL_ESC(${VAL1})}', '${SQL_ESC(${VAL2})}') ### 関数を変更した場合は以下を実行 ### # asterisk -rvvvv $ module load func_odbc.so # dialplan # 右オペランドにカンマ区切りでVALを入れる same => n,set(ODBC_RECORD_UUI()=${FROMEXTEN},"my number") |
以下のようにARGとVALをミックスして使用することもできます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[INSERT_RECORD] dsn=asteriskodbc writesql=INSERT INTO uui(uui, description) VALUES('${SQL_ESC(${VAL1})}', '${SQL_ESC(${ARG1})}') ## Linuxコマンドラインから一発でモジュールリロード # asterisk -rx "module load func_odbc.so" # dialplan same => n,set(ODBC_RECORD_UUI("mix example")=${FROMEXTEN}) ### ARGにスペースが含まれる引数を与えると、以下のようなWARNINGが出ます。 [2019-07-24 08:40:42] WARNING[26989][C-00000033]: pbx_variables.c:1101 pbx_builtin_setvar: Please avoid unnecessary spaces on variables as it may lead to unexpected results ('ODBC_INSERT_RECORD("mix example")' set to '0338636754'). # 推奨されないようですが、一応Mysqlにはスペースを含むデータが入っていました |
おわりに
これまではAGIからPHPのPDOを通してDB連携を行うことが多かったですが、
ODBCを利用することでよりダイアルプランを読んだだけでDB処理がわかるようになりました。
数少ない(?)Asteriskエンジニアの一人としてAsteriskの情報は今後も発信していきたいと思います。
- AWS Step Functionsの基本を再学習しました - 2024-09-23
- Amazon SESでバウンスメールを管理する - 2024-07-07
- TEAMをv1.1.1にアップデートしカスタムドメインを設定する - 2024-02-17
- コールセンター白書2023とAmazon Connect - 2023-12-25
- Provide dynamic and personalized CX with in-app web call for Amazon Connect - 2023-12-16