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
On this page
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
}