12.AsterNET.ARIでIVRに挑戦してみる。

次は、AsterNET.ARIを使って、IVR(音声自動応答)に挑戦してみます。

 

1.まず、IVRで使用する音声データを用意します。形式は色々ありますが、Windows標準音声ファイル形式であるWAV形式が適当でしょう。ここでは、歯科予約IVRを想定して、以下の8種類のガイダンスメッセージを用意します。

  1. 「お電話ありがとうございます。アグリモ歯科です。」

  2. 「ご予約の日付を4桁で入力し、最後に#を入力してください。例えば、6月1日の場合は、0601#と入力してください。どうぞ。」

  3. 「ご予約の時間を2桁で入力し、最後に#を入力してください。例えば、17時の場合は、17#と入力してください。どうぞ。」

  4. 「ご予約内容の確認をさせていただきます。ご予約の日時は、」

  5. 「ですね。よろしければ1と#を、もう一度やり直す場合は2と#を、入力してください。」

  6. 「ご予約を賜りました。ご予約番号は、」

  7. 「です。ご来院をお待ちしております。有難うございました。」

  8. 「認識できません。もう一度、入力してください。」

2.FreePBXにログインして、メニュー「Admin」-「Sound Language」を選択します。

3.「Custom Language」をクリックします。

4.「+ Add New Custom Language」をクリックします。

5.「Language Code」欄に「ja」と入力し、「Browse」をクリックます。

6.音声ファイルを全部選択し、「開く」をクリックします。

7.音声ファイルのアップロードが終わったら、「Convert to」で「g722」と「ulaw」のみ選択し、右下の「Submit」をクリックします。(※「wav」は非選択にします。)

8.「OK」をクリックします。

9.音声ファイルの「WAV」形式が「g722」形式と「ulaw」形式にコンバートされます。

10.New Custom Language が登録されました。実際の保存場所は、/var/lib/asterisk/sounds/ja の中です。

11.Visual Studio を開いて、いよいよ本題、AsterNET.ARIに挑戦してみる。で使用したソースプログラム(program.cs)をIVR用に変更します。

12.「開始」をクリックして実行してみます。正常に接続できている場合は、コマンドプロンプト画面内に「Connection state is now True」と表示されます。

13.内線1000番へ電話を掛け、IVRが動作していることを確認できれば完了です。

 

【ソース(program.cs)】  ※このソースプログラムはサンプルです。完全動作するものではありません。

using System;
using AsterNET.ARI.Models;

namespace AsterNET.ARI.TestApplication
{
    internal class Program
    {
        public static AriClient ActionClient;
        public static Playback playback;
        public static string ChannelID;
        public static string dtmf_str;
        public static string [] yoyaku_hiduke = new string [100];
        public static string [] yoyaku_jikan = new string[100];
        public static string sentaku;
        public static int yoyaku_no = 1;


        private static void Main(string[] args)
        {
            try
            {
                // Create a new Ari Connection
                ActionClient = new AriClient(
                    new StasisEndpoint("192.168.24.200", 8088, "test_user", "test_password"),
                    "HelloWorld");

                // Hook into required events
                ActionClient.OnChannelDtmfReceivedEvent += ActionClientOnChannelDtmfReceivedEvent;
                ActionClient.OnConnectionStateChanged += ActionClientOnConnectionStateChanged;
                ActionClient.OnPlaybackFinishedEvent += ActionClient_OnPlaybackFinishedEvent;
                ActionClient.OnPlaybackStartedEvent += ActionClient_OnPlaybackStartedEvent;
                ActionClient.OnStasisStartEvent += c_OnStasisStartEvent;
                ActionClient.OnUnhandledException += ActionClient_OnUnhandledException;
 
                ActionClient.Connect();

                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadKey();
            }
        }

        private static void ActionClient_OnUnhandledException(object sender, Exception exception)
        {
            //Console.WriteLine("ActionClient_OnUnhandledException: " + exception.Message);
        }

        private static void ActionClient_OnPlaybackFinishedEvent(IAriClient sender, PlaybackFinishedEvent e)
        {
            // Play IVR Voices
            switch(playback.Id)
            {
                case "onsei1":
                    playback = sender.Channels.Play(ChannelID, "sound:onsei2", "ja", 0, 0, "onsei2");
                    sender.Channels.Record(ChannelID, "recode_onsei1", "wav", 0, 10000, "overwrite", true, "#");
                    //playback = sender.Channels.Play(ChannelID, "sound:onsei8", "ja", 0, 0, "onsei1");
                    break;
                case "onsei2":
                    playback = sender.Channels.Play(ChannelID, "sound:onsei3", "ja", 0, 0, "onsei3");
                    sender.Channels.Record(ChannelID, "recode_onsei2", "wav", 0, 10000, "overwrite", true, "#");
                    //playback = sender.Channels.Play(ChannelID, "sound:onsei8", "ja", 0, 0, "onsei2");
                    break;
                case "onsei3":
                    playback = sender.Channels.Play(ChannelID, "sound:onsei4", "ja", 0, 0, "onsei4");
                    break;
                case "onsei4":
                    playback = sender.Channels.Play(ChannelID, string.Format("sound:digits/{0}", yoyaku_hiduke[yoyaku_no].Substring(0, 2).ToString()), "ja", 0, 0, "yoyaku-hiduke1");
                    Console.WriteLine(string.Format("予約日時: {0}月{1}日の{2}時",
                            yoyaku_hiduke[yoyaku_no].Substring(0, 2),
                            yoyaku_hiduke[yoyaku_no].Substring(2, 2),
                            yoyaku_jikan[yoyaku_no]));
                    break;
                case "yoyaku-hiduke1":
                    playback = sender.Channels.Play(ChannelID, string.Format("sound:digits/{0}", yoyaku_hiduke[yoyaku_no].Substring(2, 2).ToString()), "ja", 0, 0, "yoyaku-hiduke2");
                    break;
                case "yoyaku-hiduke2":
                    playback = sender.Channels.Play(ChannelID, string.Format("sound:digits/{0}", yoyaku_jikan[yoyaku_no].Substring(0, 2).ToString()), "ja", 0, 0, "yoyaku-jikan");
                    break;
                case "yoyaku-jikan":
                    playback = sender.Channels.Play(ChannelID, "sound:onsei5", "ja", 0, 0, "onsei5");
                    sender.Channels.Record(ChannelID, "recode_onsei3", "wav", 0, 10000, "overwrite", true, "#");
                    //playback = sender.Channels.Play(ChannelID, "sound:onsei8", "ja", 0, 0, "onsei1");
                    break;
                case "onsei5":
                    playback = sender.Channels.Play(ChannelID, "sound:onsei6", "ja", 0, 0, "onsei6");
                    break;
                case "onsei6":
                    playback = sender.Channels.Play(ChannelID, string.Format("sound:digits/{0}", yoyaku_no.ToString()), "ja", 0, 0, "yoyaku-bangou");
                    Console.WriteLine("選択: " + sentaku);
                    Console.WriteLine("予約番号: " + yoyaku_no);
                    yoyaku_no += 1;
                    break;
                case "yoyaku-bangou":
                    playback = sender.Channels.Play(ChannelID, "sound:onsei7", "ja", 0, 0, "onsei7");
                    break;
                case "onsei7":
                    sender.Channels.Hangup(ChannelID, "normal");
                    break;
                //case "onsei8":
                //    break;
                default:
                    break;
            }
        }

        private static void ActionClient_OnPlaybackStartedEvent(IAriClient sender, PlaybackStartedEvent e)
        {
            Console.WriteLine("Playing playbackId: " + playback.Id);
        }

        private static void ActionClientOnConnectionStateChanged(object sender)
        {
            Console.WriteLine("Connection state is now {0}", ActionClient.Connected);
        }

        private static void ActionClientOnChannelDtmfReceivedEvent(IAriClient sender, ChannelDtmfReceivedEvent e)
        {
            // When DTMF received
            switch (e.Digit)
            {
                case "*":
                    break;
                case "#":
                    Console.WriteLine("Confirm dtmf_str: " + dtmf_str);
                    switch (playback.Id)
                    {
                        case "onsei3":
                            yoyaku_hiduke[yoyaku_no] = dtmf_str;
                            dtmf_str = "";
                            break;
                        case "onsei4":
                            yoyaku_jikan[yoyaku_no] = dtmf_str;
                            dtmf_str = "";
                            break;
                        case "onsei6":
                            sentaku = dtmf_str;
                            dtmf_str = "";
                            break;
                    }
                    break;
                default:
                    //sender.Playbacks.Stop(playback.Id);     //Stop playback
                    //sender.Channels.Play(e.Channel.Id, string.Format("sound:digits/{0}", e.Digit));
                    switch (playback.Id)
                    {
                        case "onsei3":
                        case "onsei4":
                        case "onsei6":
                            dtmf_str += e.Digit;
                            break;
                    }
                    break;
            }
        }

        private static void c_OnStasisStartEvent(IAriClient sender, StasisStartEvent e)
        {
            try
            {
                dtmf_str = "";
                yoyaku_hiduke[yoyaku_no] = "";
                yoyaku_jikan[yoyaku_no] = "";
                sentaku = "";

                ChannelID = e.Channel.Id;
                Console.WriteLine("\r\nChannelID: " + ChannelID);

                // Answer the channel
                sender.Channels.Answer(e.Channel.Id);

                // Play IVR Voices
                playback = sender.Channels.Play(e.Channel.Id, "sound:onsei1", "ja", 0, 0, "onsei1");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadKey();
            }
        }
    }
}