Documentation

Your First SIP/Analog Program

This tutorial will step you through creating a windows service that listens for calls on two SIP or Analog lines.

You can find the source for this example here: https://github.com/ivrToolkit/ivrToolkit/tree/develop/Examples/MyFirstApp

Create the application stub

Lets start by creating a simple Windows Service. I am going to assume you know how to use the dotnet command line.

md MyFirstApp
cd MyFirstApp
dotnet new sln
dotnet new worker --output MyFirstApp --framework net6.0
dotnet sln add MyFirstApp

Add Packages

Add the ivrToolkit nuget packages you want to use.

cd MyFirstApp
dotnet add package ivrToolkit.Core -v 6.0.0-beta-01
dotnet add package ivrToolkit.Plugin.Dialogic.Common -v 6.0.0-beta-01
dotnet add package ivrToolkit.Plugin.Dialogic.Analog -v 6.0.0-beta-01
dotnet add package ivrToolkit.Plugin.Dialogic.Sip -v 6.0.0-beta-01

Make it a Windows Service

FYI, this app will run as a console app as well.

Add the windows service nuget package

dotnet add package Microsoft.Extensions.Hosting.WindowsServices

add UseWindowsService() to program.cs

using System;
using System.IO;
using ivrToolkit.Plugin.Dialogic.Common;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace MyFirstApp
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            // Make the working directory the location of the EXE file
            Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
            return Host.CreateDefaultBuilder(args)

                // set this up as a windows service
                .UseWindowsService()
                .ConfigureServices((_services) =>
                {
                    services.AddHostedService<Worker>();
                });
        }
    }
}

Worker.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using ivrToolkit.Core;
using ivrToolkit.Plugin.Dialogic.Analog;
using ivrToolkit.Plugin.Dialogic.Common;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
    
namespace MyFirstApp
{
    public class Worker : BackgroundService
    {
        private readonly ILoggerFactory _loggerFactory;
        private readonly DialogicVoiceProperties _voiceProperties;
        private readonly ILogger<Worker> _logger;
        private PluginManager _pluginManager;
    
        public Worker(ILoggerFactory loggerFactory, DialogicVoiceProperties voiceProperties)
        {
            _loggerFactory = loggerFactory;
            _voiceProperties = voiceProperties;
            _logger = loggerFactory.CreateLogger<Worker>();
        }
    
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            await Task.Run(() =>
            {
                _logger.LogInformation("Starting the windows service.");
                try
                {
                    _logger.LogDebug("Starting the Dialogic Analog Plugin");
                    var ivrPlugin = new AnalogPlugin(_loggerFactory, _voiceProperties);
                    _pluginManager = new PluginManager(_loggerFactory, ivrPlugin);
    
                    _logger.LogDebug("Getting line 1");
                    var line1 = _pluginManager.GetLine(1);
                    var waitCall1 = new WaitCall(_loggerFactory, line1, _voiceProperties);
                    var thread1 = new Thread(waitCall1.Run);
    
                    _logger.LogDebug("Getting line 2");
                    var line2 = _pluginManager.GetLine(2);
                    var waitCall2 = new WaitCall(_loggerFactory, line2, _voiceProperties);
                    var thread2 = new Thread(waitCall2.Run);
    
                    thread1.Start();
                    thread2.Start();
                }
                catch (Exception e)
                {
                    _logger.LogError(e, e.Message);
                }
            }, stoppingToken);
        }
    
        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            await Task.Run(() =>
            {
                _pluginManager?.ReleaseAll();
                _pluginManager?.Dispose();
            }, cancellationToken);
        }
    }
    
}

WaitCall.cs

using System;
using System.Threading;
using ivrToolkit.Core;
using ivrToolkit.Core.Exceptions;
using ivrToolkit.Core.Interfaces;
using ivrToolkit.Plugin.Dialogic.Common;
using Microsoft.Extensions.Logging;
using MyFirstApp.ScriptBlocks;
    
namespace MyFirstApp
{
    public class WaitCall
    {
        private readonly ILogger<WaitCall> _logger;
        private readonly ILoggerFactory _loggerFactory;
        private readonly DialogicVoiceProperties _voiceProperties;
        private readonly IIvrLine _line;
    
        public WaitCall(ILoggerFactory loggerFactory, IIvrLine line, DialogicVoiceProperties voiceProperties)
        {
            _voiceProperties = voiceProperties;
            _loggerFactory = loggerFactory;
            _line = line;
            _logger = loggerFactory.CreateLogger<WaitCall>();
        }
    
        public void Run()
        {
            var lineNumber = _line.LineNumber;
            try
            {
                _logger.LogInformation("WaitCall: Line {0}: Got Line", lineNumber);
                while (true)
                {
                    _logger.LogInformation("WaitCall: Line {0}: Hang Up", lineNumber);
                    _line.Hangup();
                    Thread.Sleep(1000);
                    _logger.LogInformation("WaitCall: Line {0}: Wait Rings", lineNumber);
                    _line.WaitRings(1);
    
                    try
                    {
                        var manager = new ScriptManager(_loggerFactory, new WelcomeScript(_loggerFactory, _voiceProperties, _line));
    
                        while (manager.HasNext())
                        {
                            // execute the next script
                            manager.Execute();
                        }
    
                        _line.Hangup();
                    }
                    catch (HangupException)
                    {
                        _line.Hangup();
                    }
    
                }
            }
            catch (DisposingException)
            {
                _logger.LogDebug("DisposingException on line {0}", lineNumber);
                _line.Dispose();
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Exception on line {0}{1}", lineNumber, e.Message);
            }
        }
    }
}

WelcomeScript.cs

// 
// Copyright 2021 Troy Makaro
// 
// This file is part of ivrToolkit, distributed under the Apache-2.0 license.
// 
// 
    
using ivrToolkit.Core;
using ivrToolkit.Core.Interfaces;
using Microsoft.Extensions.Logging;
    
namespace MyFirstApp.ScriptBlocks
{
    public class WelcomeScript : AbstractScript
    {
        private readonly ILoggerFactory _loggerFactory;
        private readonly VoiceProperties _voiceProperties;
        private readonly IIvrLine _line;
        private readonly ILogger<WelcomeScript> _logger;
    
        public WelcomeScript(ILoggerFactory loggerFactory, VoiceProperties voiceProperties, IIvrLine line) : base(loggerFactory, voiceProperties, line)
        {
            _loggerFactory = loggerFactory;
            _voiceProperties = voiceProperties;
            _line = line;
            _logger = loggerFactory.CreateLogger<WelcomeScript>();
            _logger.LogDebug("Ctr()");
        }
    
        public override string Description => "Welcome";
    
        public override IScript Execute()
        {
            _logger.LogDebug("Execute()");
            // say My welcome message
            Line.PlayFile(@"Voice Files\ThankYou.wav");
            return new MainScript(_loggerFactory, _voiceProperties, _line);
        }
    
    } // class
}

MainScript.cs

// 
// Copyright 2021 Troy Makaro
// 
// This file is part of ivrToolkit, distributed under the Apache-2.0 license.
// 
// 
    
using ivrToolkit.Core;
using ivrToolkit.Core.Extensions;
using ivrToolkit.Core.Interfaces;
using Microsoft.Extensions.Logging;
    
namespace MyFirstApp.ScriptBlocks
{
    public class MainScript : AbstractScript
    {
        private readonly ILoggerFactory _loggerFactory;
        private readonly VoiceProperties _voiceProperties;
        private readonly IIvrLine _line;
        private readonly ILogger<MainScript> _logger;
    
        public MainScript(ILoggerFactory loggerFactory, VoiceProperties voiceProperties, IIvrLine line) : base(loggerFactory, voiceProperties, line)
        {
            _loggerFactory = loggerFactory;
            _logger = loggerFactory.CreateLogger<MainScript>();
            _logger.LogDebug("Ctr()");
            _voiceProperties = voiceProperties;
            _line = line;
        }
    
        public override string Description => "Main Script";
    
        public override IScript Execute()
        {
            _logger.LogDebug("Execute()");
            while (true)
            {
                string result = PromptFunctions.RegularPrompt(@"Voice Files\Press1234.wav");
    
                Line.PlayFile(@"Voice Files\YouPressed.wav");
    
                Line.PlayCharacters(result);
    
                Line.PlayFile(result == "1234" ? @"Voice Files\Correct.wav" : @"Voice Files\Incorrect.wav");
    
                result = PromptFunctions.SingleDigitPrompt(@"Voice Files\TryAgain.wav""12");
                if (result == "2"break;
            } // endless loop
            return new GoodbyeScript(_loggerFactory, _voiceProperties, _line);
        }
    } // class
}

GoodbyeScript.cs

// 
// Copyright 2021 Troy Makaro
// 
// This file is part of ivrToolkit, distributed under the Apache-2.0 license.
// 
// 
    
using ivrToolkit.Core;
using ivrToolkit.Core.Interfaces;
using Microsoft.Extensions.Logging;
    
namespace MyFirstApp.ScriptBlocks
{
    public class GoodbyeScript : AbstractScript
    {
        private readonly ILogger<GoodbyeScript> _logger;
    
        public GoodbyeScript(ILoggerFactory loggerFactory, VoiceProperties voiceProperties, IIvrLine line) : base(loggerFactory, voiceProperties, line)
        {
            _logger = loggerFactory.CreateLogger<GoodbyeScript>();
            _logger.LogDebug("Ctr()");
        }
    
        public override string Description => "Goodbye";
    
        public override IScript Execute()
        {
            _logger.LogDebug("Execute");
            // say my goodbye message
            Line.PlayFile(@"Voice Files\Goodbye.wav");
            return null// signal the end
        }
    } // class
}