Skip to main content

CSTA SignalR client API

tip

It's recommended to use the SignalR API for new development, if your programming language support SignalR.

Clients​

SignalR is a modern two-way communication that support multiple transport technologies, ideally using WebSocket. A thorough guide can be found in Microsoft's own documentation here.

TechnologyPackage
.NETMicrosoft.AspNetCore.SignalR.Client
JavaScript@microsoft/signalr

How to use​

tip

The SignalR client support JSON requests, responses and events. They follow the CSTA format in the ECMA-323 CSTA Standard, but are supported in JSON instead of XML.

  1. SignalR hub: Instantiate a client class and connect
  2. Authentication: Login using CSTA StartApplicationSession request
  3. Call other CSTA methods on the client to interact with your hosted pbx

.NET sample client​

The C# sample client is written for .NET Core 6, but should be backwards compatible to older ASP.NET Core versions.

using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Options;
using Unitel.Csta.Standard.Events;
using Unitel.Csta.Standard.Requests;

namespace Unitel.Csta.SignalR.TestClient
{
public class SignalRClient
{
private readonly ILogger<SignalRClient> _logger;
private readonly string _uri;

private HubConnection _connection;

delegate void NotifyClientConnectionDelegate<T>(T message);

public event NotifyClientConnectionDelegate<ConnectionClearedEvent> NotifyOnConnectionClearedEvent;
public event NotifyClientConnectionDelegate<DeliveredEvent> NotifyOnDeliveredEvent;
public event NotifyClientConnectionDelegate<EstablishedEvent> NotifyOnEstablishedEvent;

public event NotifyClientSignalRClosed NotifySignalRClosed;

public SignalRClient(ILogger<SignalRClient> logger)
{
_logger = logger;
_uri = "GATEWAY_API" + "/csta";
_connection = new HubConnectionBuilder().WithUrl(new Uri(_uri)).Build();
}

public async Task Start()
{
SetupSignalRConnectionEventListeners();
SetupCstaEventListeners();

try
{
_logger.LogDebug($"SignalR client connecting...");

if (_connection.State == HubConnectionState.Disconnected)
{
await _connection.StartAsync();
}
else
{
_logger.LogDebug($"SignalR client already connected.");
}
}
catch (Exception e)
{
_logger.LogError(e, $"Failed to start SignalR client, {e.Message}");
NotifySignalRClosed();
throw;
}
}

public async Task Stop()
{
try
{
_logger.LogDebug($"SignalR client shutting down...");
if (_connection != null)
{
await _connection.StopAsync();
await _connection.DisposeAsync();
_connection = null;
}
}
catch (Exception e)
{
_logger.LogError(e, $"Failed to stop SignalR client, {e.Message}");
throw;
}
}

public async Task<StartApplicationSessionPosResponse> StartApplicationSession(StartApplicationSession request)
{
return await _connection.InvokeAsync<StartApplicationSessionPosResponse>("StartApplicationSession", request);
}

public async Task<MonitorStartResponse> MonitorStart(MonitorStart request)
{
return await _connection.InvokeAsync<MonitorStartResponse>("MonitorStart", request);
}

public async Task<MakeCallResponse> MakeCall(MakeCall request)
{
return await _connection.InvokeAsync<MakeCallResponse>("MakeCall", request);
}

public async Task<ClearConnectionResponse> ClearConnection(ClearConnection request)
{
return await _connection.InvokeAsync<ClearConnectionResponse>("ClearConnection", request);
}

private void SetupCstaEventListeners()
{
_connection.On<ConnectionClearedEvent>("ConnectionCleared", (message) =>
{
NotifyOnConnectionClearedEvent(message);
_logger.LogDebug($"ConnectionClearedEvent");
});

_connection.On<DeliveredEvent>("Delivered", (message) =>
{
NotifyOnDeliveredEvent(message);
_logger.LogDebug($"DeliveredEvent");
});

_connection.On<EstablishedEvent>("Established", (message) =>
{
NotifyOnEstablishedEvent(message);
_logger.LogDebug($"EstablishedEvent");
});
}

private void SetupSignalRConnectionEventListeners()
{
_connection.Closed += error =>
{
_logger.LogInformation("SignalR Client connection closed.");

NotifySignalRClosed();

return Task.CompletedTask;
};
}
}
}

Use Case​

class Test 
{

public void ExecuteTest()
{
var client = new CstaClient();
client.NotifySignalRClosed += () => { _logger.LogInformation("Connection closed"); };
client.NotifyOnEvent += (e) => { _logger.LogInformation("Event received"); };

await client.Start();

await client.StartApplicationSession(CreateStartApplicationSessionRequest());
await client.MakeCall(CreateMakeCallRequest("222", "333"))
}

private StartApplicationSessionRequest CreateStartApplicationSessionRequest()
{
return new StartApplicationSessionRequest
{
ApplicationInfo = new ApplicationInfo
{
ApplicationSpecificInfo = new ApplicationSpecificInfo
{
UserId = "username",
Password = "password",
PbxDomain = "pbxDomain"
}
}
};
}

private MakeCallRequest CreateMakeCallRequest(string callerId, string calleeId)
{
return new MakeCallRequest
{
CallingDevice = callerId,
CalledDirectoryNumber = calleeId,
PrivateData = new RequestResponsePrivateData
{
RequestId = Guid.NewGuid().ToString(),
}
};
}
}


TypeScript ES6 sample client​

class CstaClient {
connection!: HubConnection;

async connect(): Promise<void> {
this.connection = new HubConnectionBuilder().withUrl(GATEWAY_API).build();
await this.connection.start();
console.log("Connected to csta gateway");
}

async disconnect(): Promise<void> {
await this.connection.stop();
}

async startApplicationSession(username: string, password: string, pbxDomain: string) {
const response = await this.connection.invoke("StartApplicationSession", {
applicationInfo: {
applicationSpecificInfo: {
"vendorData:userID": username,
"vendorData:password": password,
"vendorData:pbxDomain": pbxDomain,
},
},
requestedSessionDuration: 120,
});
console.log(response);
}

async monitorStart(trunkId: string, deviceId: string): Promise<void> {
const response = await this.connection.invoke("MonitorStart", {
monitorObject: { deviceObject: "u-" + trunkId + "-" + deviceId },
});
console.log("MonitorStart response", response);
}

async makeCall(callingDevice: string, calledDirectoryNumber: string): Promise<void> {
const response = await this.connection.invoke("MakeCall", {
callingDevice: callingDevice,
calledDirectoryNumber: calledDirectoryNumber,
});
console.log("MakeCall Response", response);
}

async clearConnection(callId: string): Promise<void> {
const response = await this.connection.invoke("ClearConnection", {
connectionToBeCleared: {
callId: callId,
},
privateData: {
requestId: "request-clearconnection-" + callId,
},
});

console.log("ClearConnection Response", response);
}

subscribeToEvents(): void {
this.connection.on("Delivered", (e: DeliveredEvent) => {
console.log("Delivered", e);
});

this.connection.on("Established", (e: EstablishedEvent) => {
console.log("Established", e);
});

this.connection.on("ConnectionCleared", (e: ConnectionClearedEvent) => {
console.log("ConnectionCleared", e);
});
}
}

export default new CstaClient();

Use Case​

const client = new CstaClient();
await client.connect();
await client.startApplicationSession("username", "password", "pbxDomain");
await client.makeCall("22334455", "333");

Get access to uni-tel CSTA SignalR API​

If you want to know more, feel free to contact us here. The contact form is in Danish only, but inquiries in English are most welcome.