AsteriskのAGIでダイアルプランからDynamoDBを参照する

こんにちは。西山です。

ギークフィードではオフィスの電話システムとして、社内にAsteriskサーバーを立てて利用しています。

リモートワーク開始後に電話を取る人も機会も減ったこともあり、効率よく着信電話を処理するためにコールフロー内で処理を行う必要が出てきました。

今回はAsteriskのダイアルプランからAWSサービスへアクセスする方法を、DynamoDBを例に紹介します。

数少ないAsteriskエンジニアの一助になれば幸いです。

 

※Asteriskとは?

AsteriskはオープンソースのPBXでDigiumのMark Spencerによって始められました。(主に)Linuxプラットフォーム上で動作します。
PBXというと会社内の電話やビジネスホン等を思い浮かべるのですが、Asteriskが使用されるのは、いわゆる電話の分野だけではありません。通話を繋いだり切ったり(呼制御)、通話を必要とするサービスは旧来の電話だけで使われるわけではありません。様々な音声サービスに使用できるのがAsteriskです。このため電話交換機からインターネット上の音声サービスまで様々に使用されているのがAsteriskです。

— Voip-Info.jpより引用

※AGIとは?

Asterisk Gateway Interfaceの略。Asteriskのダイアルプラン(コールフロー)と、チャネル・呼制御を行う外部プログラムとの間のインターフェースです。AGIプログラムは同期的に実行されます。

 

目次

AGIをインストール

AGIは様々な言語で提供されていますが、私はPHP版のAGIしか使ったことがないので今回もPHPAGIを利用します。

AGIのインストールは簡単です。

 

  1. PHPAGIのサイトからzipファイルをダウンロード
  2. phpagi.php, phpagi-fastagi.php, phpagi-asmanager.phpを、Asteriskがインストールされているサーバーの/var/lib/asterisk/agi-binに配置する
  3. 上記ファイルにAsterisk実行ユーザーへ実行権限を付与する

 

上記が完了すると、ダイアルプラン内からAGIファンクションでPHPのAGIスクリプトを実行することができます。

 

スクリプトを書く

実行するスクリプトをPHPで書きます。基本的には普通のPHPコードを書く際と同じですが、一部AGIの要素が入っています。

 

#!/usr/bin/env php
<?php
require_once('/var/lib/asterisk/agi-bin/phpagi.php');
require 'vendor/autoload.php';
use Aws\Sdk; use Aws\DynamoDb\Marshaler;
use Aws\DynamoDb\Exception\DynamoDbException;
$targetPhonenumber = trim($argv[1]);

// AsteriskとやりとりをするAGIインスタンスを作成
$agi = new AGI();
// NoOpは何もせずログを書く
$agi->exec('NoOp', 'start agi script: checkDynamoDB.php');
$agi->exec('NoOp', 'targetPhonenumber: ' . $targetPhonenumber);

// DynamoDB
$sdk = new Sdk([
  'region' => 'ap-northeast-1',
  'version' => 'latest',
  'credentials' => [
    'key' => 'アクセスキー',
    'secret' => 'シークレットアクセスキー'
  ]
]);
$dynamodb = $sdk->createDynamoDb();
$marshaler = new Marshaler();
$key = $marshaler->marshalJson('{ "phoneNumber": "' . $targetPhonenumber . '" }');
$params = [ 'TableName' => 'DynamoDBのテーブル名', 'Key' => $key ];
$result = $dynamodb->getItem($params);
if (!is_null($result->get('Item'))) {
  // hit in database
  $agi->exec('NoOp', 'hit in database');
  // Gotoはダイアルプランの特定コンテキストやラベルに移動する
  $agi->exec('Goto', 'specified-customer');
} else { 
  // not hit
  $agi->exec('NoOp', 'not hit in database');
}
return;
?>

1行目のシェバンはAsteriskがスクリプトを解釈するために必須です。

AGIインスタンスを作成し、exec関数を使うことでAsteriskの呼制御をプログラムから実行することができます。

例として上記スクリプトでは、引数で渡された顧客電話番号をDynamoDBで検索し、DB内でヒットしたら特定のラベルへダイアルプランフローを移動し、ヒットしない場合はもとのフローに戻るという処理になっています。

AWSの認証に関しては社内の物理サーバーからのアクセスのため、アクセスキーを使用しています。もちろんAWS CLIをインストールする方法でも問題ありません。

AsteriskサーバーがEC2の場合、インスタンスプロファイルに必要なIAMロールをアタッチしてセキュアに認証を行いましょう。

また、スクリプトファイルもAsterisk実行ユーザーへ実行権限を与えてください。

 

ダイアルプランからAGIを呼び出す

最後にダイアルプランからAGIを呼び出します。

AGI関数の第一引数には実行するスクリプトを指定し、第二引数にはスクリプトに渡す引数を指定します。この場合は、電話をかけてきた相手の電話番号を渡しています。

ダイアルプランは/etc/asterisk/extensions.confです。

 

[incoming]
;------------------------------------
;GeekFeed代表 0338636754=GEEKFEED
;------------------------------------
exten => ${GEEKFEED},1,NoOp(GF NUMBER)
exten => ${GEEKFEED},n,Macro(cidnamecheck)
exten => ${GEEKFEED},n,Set(CALLERID(num)=${CALLERID(num)})
exten => ${GEEKFEED},n,NoOp("CallerID num is "${CALLERID(num)})
exten => ${GEEKFEED},n,Set(CALLERID(name)=GEEKFEED:${CALLERID(num)})
exten => ${GEEKFEED},n,NoOp("CallerID name is "${CALLERID(name)})

; for dynamodb
exten => ${GEEKFEED},n,AGI(checkDynamoDB.php, ${CALLERID(num)})
; 
exten => ${GEEKFEED},n(open),Dial(${GROUP_ALL},30,tTwW)
exten => ${GEEKFEED},n(specified-customer),Playback(ja/silence/ja/greeting)
exten => ${GEEKFEED},n,Hangup

 

ダイアルプラン変更後は、

$ dialplan reload

をAsteriskコンソールで実行します。

 

Tips

AGIをデバッグするには、上記でも記載しているNoOp関数を指定してAsteriskコンソールでログを確認することができます。

また、Asteriskコンソールで

$ agi set debug on

を実行することで、AGIのデバッグを有効化することができます。

 

AGIスクリプトはAGIインスタンスの処理以外は普通にPHPスクリプトとして実行することもできるので、Linuxターミナル上でphpコマンドで実行することでもデバッグを行えます。

 

さいごに

いつものエンジニア募集の告知

ギークフィードではハイレベルなクラウドエンジニア(を目指している人含む)を随時募集しています。
量より質を重視する企業理念の関係上、採用合格率は決して高くありませんが、我こそはと思う方はhttps://www.geekfeed.co.jp/recruitment
よりご気軽にご応募ください!

この記事が気に入ったら
いいね ! しよう

Twitter で

【採用情報】一緒に働く仲間を募集しています

採用情報
ページトップへ