Commit 2092fdab authored by Karen McElroy's avatar Karen McElroy

Change this sample to use a config file and upgrade to netcore3.1

parent c32ec90c

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.960
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IVR-X2", "IVR-X2\IVR-X2.csproj", "{505B4FE9-8766-4A57-80B9-F78D11585AE3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X2protobuf", "X2protobuf\X2protobuf.csproj", "{727A61B6-456E-492A-9B93-96679F23A775}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{505B4FE9-8766-4A57-80B9-F78D11585AE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{505B4FE9-8766-4A57-80B9-F78D11585AE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{505B4FE9-8766-4A57-80B9-F78D11585AE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{505B4FE9-8766-4A57-80B9-F78D11585AE3}.Release|Any CPU.Build.0 = Release|Any CPU
{727A61B6-456E-492A-9B93-96679F23A775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{727A61B6-456E-492A-9B93-96679F23A775}.Debug|Any CPU.Build.0 = Debug|Any CPU
{727A61B6-456E-492A-9B93-96679F23A775}.Release|Any CPU.ActiveCfg = Release|Any CPU
{727A61B6-456E-492A-9B93-96679F23A775}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {760E8BF0-88E3-4A57-BE14-817AFF34E4EC}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.6.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IVR-X2", "IVR-X2\IVR-X2.csproj", "{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X2protobuf", "X2protobuf\X2protobuf.csproj", "{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Debug|x64.ActiveCfg = Debug|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Debug|x64.Build.0 = Debug|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Debug|x86.ActiveCfg = Debug|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Debug|x86.Build.0 = Debug|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Release|Any CPU.Build.0 = Release|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Release|x64.ActiveCfg = Release|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Release|x64.Build.0 = Release|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Release|x86.ActiveCfg = Release|Any CPU
{1F9CBB0D-4B40-4F62-8691-53FA3EB27CEE}.Release|x86.Build.0 = Release|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Debug|x64.ActiveCfg = Debug|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Debug|x64.Build.0 = Debug|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Debug|x86.ActiveCfg = Debug|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Debug|x86.Build.0 = Debug|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Release|Any CPU.Build.0 = Release|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Release|x64.ActiveCfg = Release|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Release|x64.Build.0 = Release|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Release|x86.ActiveCfg = Release|Any CPU
{54DE5159-DB56-483E-B8DF-A6F6DD353A0E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
using System;
using System.Collections.Generic;
using System.Text;
namespace PIKAHMPX2.IVRClient
{
class AccountService
{
private Gpnetd.Account.AccountClient accountClient;
public AccountService(Gpnetd.Account.AccountClient accountClient)
{
this.accountClient = accountClient;
}
public Dictionary<string, string> ListApps(string account_id)
{
var application_dict = new Dictionary<string, string>();
Gpnetd.AccountListApplicationsReq request = new Gpnetd.AccountListApplicationsReq { AccountId = account_id };
Gpnetd.AccountListApplicationsResp response = accountClient.ListApplications(request);
foreach (Gpnetd.ApplicationDetail app_detail in response.Applications)
{
application_dict.Add(app_detail.Name, app_detail.ApplicationId);
}
return application_dict;
}
public string GetApplicationToken(string account_id, string application_id)
{
Gpnetd.AccountGenerateApplicationTokenReq request = new Gpnetd.AccountGenerateApplicationTokenReq
{ AccountId = account_id, ApplicationId = application_id, HoursValid = 24 };
Gpnetd.AccountGenerateApplicationTokenResp response = accountClient.GenerateApplicationToken(request);
return response.Token;
}
}
}
using System;
namespace PIKAHMPX2.IVRClient
{
public class Application
{
private Grpc.Core.Channel grpcChannel;
private Gpnetd.Credentials credentials;
private EventsService eventsService;
private string token;
Ivr ivr;
public Application(string application_id, string account_id, Grpc.Core.Channel grpcChannel, string app_token)
{
credentials = new Gpnetd.Credentials();
credentials.ApplicationId = application_id;
credentials.AccountId = account_id;
this.grpcChannel = grpcChannel;
token = app_token;
ivr = new Ivr(grpcChannel);
eventsService = new EventsService(new Gpnetd.Events.EventsClient(grpcChannel), this);
}
public Grpc.Core.Channel GetGrpcChannel()
{
return this.grpcChannel;
}
public Gpnetd.Credentials GetCredentials()
{
return this.credentials;
}
public Ivr GetIvr()
{
return ivr;
}
public string GetToken()
{
return token;
}
public void Start()
{
ivr.Initialize();
eventsService.ProcessEvents(token);
Console.WriteLine("Starting application..");
}
}
}
\ No newline at end of file
using System;
namespace PIKAHMPX2.IVRClient
{
public class AuthService
{
readonly Auth.Auth.AuthClient authClient;
internal AuthService(Auth.Auth.AuthClient authCLient)
{
this.authClient = authCLient;
}
internal Auth.AuthLoginResp GetAccountToken(string userName, string passWord)
{
Auth.AuthLoginReq request = new Auth.AuthLoginReq { User = userName, Password = passWord };
try
{
Auth.AuthLoginResp response = authClient.Login(request);
return response;
}
catch
{
Console.WriteLine("Failed to get Token");
throw;
}
}
}
}
\ No newline at end of file
using System;
using Grpc.Core;
namespace PIKAHMPX2.IVRClient
{
public class CallService
{
readonly Gpnetd.Call.CallClient callService;
public CallService(Gpnetd.Call.CallClient callClient)
{
this.callService = callClient;
}
// finish
public Gpnetd.CallGetInfoResp GetInfo(uint handle)
{
Gpnetd.CallGetInfoReq request = new Gpnetd.CallGetInfoReq { CallHandle = handle };
return callService.GetInfo(request);
}
public bool AnswerCall(uint callHandle)
{
Gpnetd.CallAnswerReq request = new Gpnetd.CallAnswerReq { CallHandle = callHandle };
CallOptions options = new CallOptions();
try
{
Gpnetd.CallAnswerResp response = callService.Answer(request, options);
}
catch (RpcException ex)
{
Console.WriteLine("RPCException: AnswerCall() failed: " + ex.Message);
return false;
}
return true;
}
public void DropCall(uint callHandle, Gpnetd.CallCauseEnum cause)
{
Gpnetd.CallDropReq request = new Gpnetd.CallDropReq { CallHandle = callHandle, Cause = (uint)cause };
CallOptions options = new CallOptions();
callService.Drop(request, options);
}
}
}
\ No newline at end of file
using System;
using System.IO;
using System.Threading.Tasks;
using Grpc.Core;
namespace PIKAHMPX2.IVRClient
{
public class ChannelService
{
readonly Gpnetd.Channel.ChannelClient channelClient;
public static int streamBufferSize = 16384;
public ChannelService(Gpnetd.Channel.ChannelClient channelClient)
{
this.channelClient = channelClient;
}
public bool CollectDigits(uint handle)
{
Gpnetd.ChannelCollectDigitsReq req = new Gpnetd.ChannelCollectDigitsReq { ChannelHandle = handle, TermCond = null };
var resp = channelClient.CollectDigits(req);
return true;
}
public async Task<bool> PlayFile(string filename, uint channelHandle)
{
Console.WriteLine("Info: Playing {0} on {1} channel", filename, channelHandle);
try
{
BinaryReader reader = new BinaryReader(File.Open(filename, FileMode.Open));
try
{
Gpnetd.AudioFlags flags = new Gpnetd.AudioFlags {
BeepBeforeRecord = false,
Encoding = Gpnetd.AudioEncodingEnum.MuLaw,
Sampling = Gpnetd.AudioSamplingEnum.Rate8Khz,
};
using (var ch = channelClient.PlayStream()) {
// setup message, sent before audio
Gpnetd.TermConditions termConditions = new Gpnetd.TermConditions {
};
Gpnetd.ChannelPlaySetup setup = new Gpnetd.ChannelPlaySetup { ChannelHandle = channelHandle, Flags = flags, TermCond = termConditions };
Gpnetd.ChannelPlayDataMsg playSetupMsg = new Gpnetd.ChannelPlayDataMsg { Setup = setup };
await ch.RequestStream.WriteAsync(playSetupMsg); // do I need to react to the response?
await ch.ResponseStream.MoveNext();
Console.WriteLine("Total Length {0}", reader.BaseStream.Length);
while (reader.BaseStream.Position < (reader.BaseStream.Length - streamBufferSize))
{
Gpnetd.ChannelPlayAudio audio = new Gpnetd.ChannelPlayAudio
{
Length = (uint)streamBufferSize,
LastBuf = false,
Data = Google.Protobuf.ByteString.CopyFrom(reader.ReadBytes(streamBufferSize))
};
Gpnetd.ChannelPlayDataMsg playDataMsg = new Gpnetd.ChannelPlayDataMsg { Audio = audio };
await ch.RequestStream.WriteAsync(playDataMsg);
await ch.ResponseStream.MoveNext();
}
Gpnetd.ChannelPlayAudio last_audio = new Gpnetd.ChannelPlayAudio
{
Length = (uint)(streamBufferSize - (reader.BaseStream.Length - reader.BaseStream.Position)),
LastBuf = true,
Data = Google.Protobuf.ByteString.CopyFrom(reader.ReadBytes((int)(streamBufferSize - (reader.BaseStream.Length - reader.BaseStream.Position))))
};
Gpnetd.ChannelPlayDataMsg lastPlayDataMsg = new Gpnetd.ChannelPlayDataMsg { Audio = last_audio };
reader.Dispose();
await ch.RequestStream.WriteAsync(lastPlayDataMsg);
await ch.ResponseStream.MoveNext();
await ch.RequestStream.CompleteAsync();
await ch.ResponseStream.MoveNext();
Console.WriteLine("Info: Finished sending audio file");
}
}
catch (RpcException ex)
{
Console.WriteLine("RPCException: Channel.PlayFile:" + ex.Message);
reader.Dispose();
throw;
}
}
catch (Exception ex)
{
Console.WriteLine("Exception: Channel.PlayFile:" + ex.Message);
return false;
}
return true;
}
/// <summary>
/// RecordToFile writes raw byte stream of data from X1 server to file on local disk
/// </summary>
/// <param name="filename"></param>
/// <param name="channelHandle"></param>
/// <returns></returns>
public async Task<bool> RecordToFile(string filename, uint channelHandle)
{
filename = filename + System.DateTime.Now.ToFileTime();
Console.WriteLine("Info: Writing to {0} from channel {1} ", filename, channelHandle);
try
{
BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.CreateNew));
try
{
Gpnetd.AudioFlags flags = new Gpnetd.AudioFlags {
BeepBeforeRecord = true,
Encoding = Gpnetd.AudioEncodingEnum.MuLaw,
Sampling = Gpnetd.AudioSamplingEnum.Rate8Khz,
};
var poundKey = 0x800;
Gpnetd.TermConditions termConditions = new Gpnetd.TermConditions { SilenceTimeout = Ivr.IVR_SAMPLE_RECORD_SILENCE_TIMEOUT, DigitMask = (uint)poundKey }; //
Gpnetd.ChannelRecordReq request = new Gpnetd.ChannelRecordReq { ChannelHandle = channelHandle, Flags = flags, TermCond = termConditions };
using (var ch = channelClient.RecordStream(request)) {
var responseStream = ch.ResponseStream;
while (await responseStream.MoveNext())
{
writer.BaseStream.Write(responseStream.Current.Data.ToByteArray(), 0, responseStream.Current.Data.Length);
}
writer.Dispose();
Console.WriteLine("Info: finished writing to {0} ", filename);
}
}
catch (RpcException ex)
{
Console.WriteLine("RPCException: Channel.RecordToFile:" + ex.Message);
}
}
catch (Exception ex)
{
Console.WriteLine("Exception: Channel.RecordToFile:" + ex.Message);
throw;
}
return true;
}
}
}
\ No newline at end of file
This diff is collapsed.
using System;
using System.Collections.Generic;
using Grpc.Core;
namespace PIKAHMPX2.IVRClient
{
public class GroupService
{
readonly Gpnetd.Group.GroupClient groupClient;
internal GroupService(Gpnetd.Group.GroupClient groupClient)
{
this.groupClient = groupClient;
}
internal List<string> ListGroups()
{
Gpnetd.GroupListGroupsReq request = new Gpnetd.GroupListGroupsReq { };
Gpnetd.GroupListGroupsResp response;
var groupList = new List<string>();
try
{
response = groupClient.ListGroups(request);
}
catch (RpcException ex)
{
throw ex;
}
foreach (string groupName in response.GroupName)
{
groupList.Add(groupName);
}
return groupList;
}
internal int GetNumOfChannels(uint handle)
{
Gpnetd.GroupGetConfigReq request = new Gpnetd.GroupGetConfigReq { GroupHandle = handle };
try
{
Gpnetd.GroupGetConfigResp response = groupClient.GetConfig(request);
return response.Config.NumberOfChannels;
}
catch (RpcException ex)
{
Console.Write("Error group.GetConfig(): " + ex);
return 0;
}
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>IVR_X2</RootNamespace>
<StartupObject>PIKAHMPX2.IVRClient.Program</StartupObject>
<!--
<StartupObject>IvrClient.Program</StartupObject>
-->
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\X2protobuf\X2protobuf.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>IVR_X2</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Grpc.Core" Version="2.37.1" />
<PackageReference Include="YamlDotNet" Version="11.1.1" />
<ProjectReference Include="../X2protobuf/X2protobuf.csproj" />
</ItemGroup>
</Project>
This diff is collapsed.
using Grpc.Core;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using YamlDotNet.Serialization;
namespace PIKAHMPX2.IVRClient
{
class Program
{
private class Config
{
public String ip { get; set; }
public String certificate { get; set; }
public String serverName { get; set; }
public String username { get; set; }
public String password { get; set; }
public String applicationName { get; set; }
public String[] dids { get; set; }
public Boolean connectUsingServername { get; set; }
}
static void Main(string[] args)
{
AuthService authService;
AccountService accountService;
Console.WriteLine("Starting HMP X2 IVR sample ...");
var input = new StreamReader("conf.yaml");
var deserializer = new Deserializer();
var config = (Config)deserializer.Deserialize(input, typeof(Config));
//set up SSL connection
var sslCredential = new SslCredentials(File.ReadAllText(config.certificate));
string serverAddress = config.ip;
if (config.connectUsingServername)
{
string ip = config.ip;
string port = ip.Split(':')[1];
serverAddress = config.serverName + ':' + port;
}
Grpc.Core.Channel gRpcChannel = new Channel(serverAddress, sslCredential);
string token = null;
string account_id = null;
string application_id = null;
authService = new AuthService(new Auth.Auth.AuthClient(gRpcChannel));
try
{
Auth.AuthLoginResp response = authService.GetAccountToken(config.username, config.password);
token = response.Token;
account_id = response.AccountId;
}
catch (RpcException ex) {
Console.WriteLine("Failed to set up SSL connection, will quit, exception is:", ex.Message);
Environment.Exit(0);
}
//Set up connection with token
try
{
var asyncAuthInterceptor = new AsyncAuthInterceptor((context, metadata) =>
{
metadata.Add("authorization", token);
return Task.CompletedTask;
});
var sslCredentialToken = new SslCredentials(File.ReadAllText(config.certificate));
// create channel credentials with TLS and authorization token
var channelCredentials = ChannelCredentials.Create(sslCredentialToken, CallCredentials.FromInterceptor(asyncAuthInterceptor));
var gRpcChan = new Grpc.Core.Channel(serverAddress, channelCredentials);
GroupService groupService = new GroupService(new Gpnetd.Group.GroupClient(gRpcChan));
List<string> groupNames = null;
try
{
groupNames = groupService.ListGroups();
Console.WriteLine("\nAccessing data ...");
Console.WriteLine("====================");
if (groupNames.Count > 0)
{
Console.WriteLine("Succeeded");
}
}
catch
{
Console.WriteLine("Unable to contact the server");
throw;
}
accountService = new AccountService(new Gpnetd.Account.AccountClient(gRpcChan));
var account_apps = accountService.ListApps(account_id);
if (!account_apps.TryGetValue(config.applicationName, out application_id))
{
Console.WriteLine("The application does not exist for the given user");
System.Environment.Exit(0);
}
string app_token = accountService.GetApplicationToken(account_id, application_id);
var application = new Application(application_id, account_id, gRpcChan, app_token);
application.Start();
}
catch (Exception ex)
{
Console.WriteLine("Failed to initialize the system. \nError details: " + ex.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
Environment.Exit(0);
}
Console.WriteLine("Press any key to quit...");
Console.ReadKey();
System.Threading.Thread.Sleep(100);
}
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
{
"runtimeOptions": {
"additionalProbingPaths": [
"C:\\Users\\lcai\\.dotnet\\store\\|arch|\\|tfm|",
"C:\\Users\\lcai\\.nuget\\packages",
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder"
]
}
}
\ No newline at end of file
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v3.1",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v3.1": {
"IVR-X2/1.0.0": {
"dependencies": {
"Grpc.Core": "2.37.1",
"X2protobuf": "1.0.0",
"YamlDotNet": "11.1.1"
},
"runtime": {
"IVR-X2.dll": {}
}
},
"Google.Protobuf/3.16.0": {
"dependencies": {
"System.Memory": "4.5.3",
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
},
"runtime": {
"lib/netstandard2.0/Google.Protobuf.dll": {
"assemblyVersion": "3.16.0.0",
"fileVersion": "3.16.0.0"
}
}
},
"Grpc.Core/2.37.1": {
"dependencies": {
"Grpc.Core.Api": "2.37.1",
"System.Memory": "4.5.3"
},
"runtime": {
"lib/netstandard2.0/Grpc.Core.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.37.1.0"
}
},