Avaya Aura Application Enablement Services

Latest Release: 10.1 (December 2021)

TSAPI Frequently Asked Questions

General

To enable and access the AE Services logging of TSAPI events:

  1. Login to the Linux interface of the AE Services server. Navigate to the '/opt/mvap/conf' directory.
  2. If the file named 'tracemask' does not exist, create a file called 'tracemask' and insert the one of the following lines in it:
    • TSAPI= 0xffffffff Everything on
    • TSAPI=0x00000c3e Everything on except mutex tracing and message tracing
    • TSAPI=0x00000c3f To see the messages to/from CM for TSAPI use
  3. If there is a file named 'tracemask', modify the TSAPI values, if required.
  4. Save and close the file.

Starting with AE Services Release 6, it is possible to enable logging from the AE Services Web Interface

  1. From the AE Services Management Console main menu, navigate to Status > Log Manager > Trace Logging Levels.
  2. On the Trace Logging Levels page, select "Everything on" for the "TSAPI Service" and click "Apply Changes".
  3. On the Log Manager Confirmation page, click "Apply".

When tracing is complete, if needed disable tracing and then collect the logs using the following procedure. Navigate to the '/opt/mvap/logs' directory. When a TSAPI message is received, a new directory named 'TSAPI' will be created in it. Root privileges are required to access the TSAPI directory. The 'TSAPI' directory contains the log files (g3trace.out and csta_trace.out) related to the events occurring in different portions of the system that handle TSAPI messages. You can copy files off the server using a secure FTP tool such as winscp.

No, TSAPI cannot be used to get to the media stream on Communication Manager. Use DMCC to access the media stream on Communication Manager.

There may be many reasons for this behavior. The network connectivity between the client machine and the AE Services server may be broken. If you are sure that your network connectivity is functioning properly, check to see what value you supplied to the notifyAll argument of the acsEventNotify() function. If you supplied the Boolean value FALSE for this argument, you will only be notified when the incoming event queue transitions from empty to non-empty. It is possible that additional events can arrive in the queue before you have removed the first event from the queue. When this happens you will NOT receive another event notification when these additional events arrive. To deal with this situation, be sure to check the numEvents argument returned when acsGetEventPoll() is called. If the value of numEvents is greater than zero when acsGetEventPoll() returns, there are more events in the queue. Since you set the notifyAll argument to acsEventNotify() to FALSE, you will not get any notification that these additional events are in the queue. You will need to insure that acsGetEventPoll() gets called again until the value returned in numEvents is zero. Remember, it is the programmer?s responsibility to retrieve these events in a timely manner or the stream may be closed by TSAPI.

To understand the message capacity between AE Services and Communication Manager one must understand a couple of things. First is the capacity of a CLAN interface. The CLAN (on Communication Manager) can transmit 240 messages per second toward AE Services and will recieve 200 per second. The second concept is that of a 'switch connection'. A switch connection is a collection of CLANs that are bundled together to logically provide more through put than a single CLAN can handle. This aggregation allows more messages to be exchanged between Communication Manager and AE Services than a single CLAN can support. Using mutiple CLANs basically multiplies the total message capacity (the number of CLANs * the number of messages a CLAN can handle in a particular direction). The third concept is that different Communication Manager platforms may or may not support CLAN interface circuit packs. The platforms that do not support CLANs allow the processor ethernet connection (procr) to be used to carry CTI messages. However depending on the switch release and platform the capacity of the procr was limited by the software (in order to avoid swamping the system with CTI traffic), or completely blocked (on the larger platforms to force the CTI message traffic to use the CLAN interfaces). Smaller platforms (G3si and S8300 servers) limit the CTI traffic to 240 outbound/200 inbound. With larger systems the system release plays into the maximum CTI traffic allowed. Prior to Communication Manager release 5.0 the upper limit of CTI messages was 720 per second. Starting with Release 5.0 Communication Manager allows 1000 messages per second, and the procr interface can be used for CTI traffic on the medium and large platforms.

The capacities of the various system platforms is documented in of the 'Avaya Communication Manager System Capacities' documentation which can be found on www.avaya.com/support under documentation for Communication Manager. Given the information is release specific, make sure you select the system release you are interested in.

If your application was built using any version of the TSAPI SDK prior to the AES TSAPI 3.1 SDK and it is using private data (any version) you must recompile it using the AES 3.1 TSAPI SDK. Be sure to refer to the "Upgrading and maintaining applications that use private data" section in Chapter 5 of the "Avaya MultiVantage Application Enablement Services TSAPI for Avaya Communication Manager Programmers Reference Release 3.1.0" for details regarding coding changes that may be required in your application.

Both JTAPI and TSAPI sample applications are available on the DevConnect web portal. The sample applications can be found by clicking on the Sample Applications link in the left hand navigation bar on the left hand side of the main page. The sample applications can be tested against the AES-CM Remote Lab. Please see more details about this remote lab here

This generic error is documented in "Avaya MultiVantage Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference Release 3.1.0" document 02-300544 issue 2 dated May 2006 (http://support.avaya.com/elmodocs2/AES/3.1.1/02_300544_2.pdf). Notice that it is a generic TSAPI document, and not specific for Communication Manager. In Chapter 3, section 'API Control Services (ACS) functions and confirmation events', it is mentioned that the serverID field is passed as part of acsOpenStream() call, and the field should contain the advertised service - NOT the IP address of AES server.

There is provision in TSAPI to obtain calling party phone number but not caller ID (caller Name) but applications can utilize the ANI information to look up the caller name from their customer database.

The fields that contain the trunk related information are trunkGroup, trunk and trunkMember These 3 fields are all part of the private parameters. This information is documented in the Avaya Computer Telephony 1.3 TSAPI for Avaya MultiVantage Programmer's Reference document, issue 1, dated October 2003. (http://support.avaya.com/elmodocs2/centre_vu_ip/r1.3/1d3Defprog.pdf)

There is no specific limit on the number of simultaneous single-step-conferences or service-observe calls. Having said that, there are two other system capacities that would have a bearing on the maximum number of calls for the above. One is the maximum number of simultaneous 3-way conference calls, and the other is the maximum number of active adjunct control associations, and both parameters vary by switch platform and release. To check out the specific limit of these two parameters for the switch platform and software version you have, please refer to "Avaya Communication Manager System Capacities Table Release 3.0" (http://support.avaya.com/elmodocs2/comm_mgr/r3/pdfs/245601_4_1.pdf)

Yes, by default, when a 'cstaMonitorDevice' request is sent, the TSAPI client application gets notified for all the events. To reduce the load between the Avaya server and the TSAPI client application, use any of the following methods:

  • Use filtering to control the number of events that are sent by the server. The 'cstaChangeMonitorFilter()' function could be used to filter out certain CSTA unsolicited events. Other events cannot be filtered.
  • When the 'Event Minimization' feature on CM is set to 'y' on the CTI link, only one set of events is sent to the TSAPI service even when more than one device is monitored. For more information, see the TSAPI Programmer's Guide.

TSAPI (G3PD) requests that are sent to CM timeout after nine seconds.

TSAPI does not provide functionality for getting the IP addresses used for media transmission, given an extension. For getting the IP addresses in use for media transmission for the device, use the 'status station' command in the SAT session of Communication Manager (CM). Similarly, the IP addresses can be obtained from the System Management Service (SMS) Web Service in AE Services server 4.1 by executing the 'status station <extension-number>' command where "status" is the operation type and "station" is the model type and <extension-number> is the qualifier. This gives the IP address used for media transmission in the 'IP_Signaling_Switch_End_IP_Address' field.

With the 'list registered-ip-stations' command in the SAT session of Communication Manager (CM), the IP address for the registered devices can be listed. The IP addresses of the stations can be obtained from the System Management Service (SMS) Web Service in AE Services server 4.1 by executing the 'list RegisteredIPStations' command where "list" is the operation type and "RegisteredIPStations" is the model type. This gives the IP addresses of the stations in the 'Station_IP_Address' field.

The forwarding event is supported beginning with AE Services release 4.1. For more details, refer to chapter 4 in the document - "Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, (December 2007) (02-300544)".

It is not possible to introduce delay between Agent login and AutoIn using the Auto Available Split (AAS) feature. Use the TSAPI snapshot services like 'cstaQueryAgentState', 'cstaQueryDeviceInfo', 'attQueryACDsplit' and 'attQueryAgentLogin' to get the desired status information.

Using TSAPI, a developer can use the 'cstaSnapshotCallReq()' request and the response for this request has the connection state information associated with all the devices in the bridged call. All the parties on the bridged appearance will be listed in the response. For all the active parties in the call, the 'Local Conn Info' field shows 'Connected' status for parties in a talking state, where as it shows 'null' when the party has not joined the call. Snapshot Response data for the scenario mentioned above is given below:

12:53:38 0 SERVICE: Make Call: Calling Device: 3000 Called Device: 2009
12:53:38 0 CONFIRM: Make Call: New Call: [Call ID: 6812 Static Device ID: 3000]

Private Data: Vendor: ECS
Event Type: ATT_MAKE_CALL_CONF
Service: Make Call
UCID: 00000000000000000000

12:53:49 0 SERVICE: Answer Call: Alerting Call: [Call ID: 6812 Static Device ID: 2024]
12:53:49 0 CONFIRM: Answer Call
12:53:55 0 SERVICE: Snapshot Call: Snapshot Object: [Call ID: 6812 Static Device ID: 2024]
12:53:55 0 CONFIRM: Snapshot Call: Number of Devices: 3
  Device: [Status: ID Provided Type: Explicit Private Local   Number Device ID: 3000]
  Call: [Call ID: 6812 Static Device ID: 3000] Local Conn Info: Connected
  Device: [Status: ID Provided Type: Explicit Private Local Number Device ID: 2009]
  Call: [Call ID: 6812 Static Device ID: 2009] Local Conn Info: Null
  Device: [Status: ID Provided Type: Explicit Private Local Number Device ID: 2024]
  Call: [Call ID: 6812 Static Device ID: 2024] Local Conn Info: Connected

Private Data: Vendor: ECS
Event Type : ATT_SNAPSHOT_CALL_CONF

In case of an inbound trunk call, trunk information is provided as private data delivered with events such as Delivered event (CSTADeliveredEvent), Established event (CSTAEstablishedEvent). In order to properly access this information, the application must first negotiate the private data version during the acsOpenStream() process so that the server sends private data associated with the events. If private data accompanies an event, for example CSTADeliveredEvent, then the private data will be stored in the location that the application specified as the privateData parameter in the acsGetEventBlock() or acsGetEventPoll() request. If the privateData pointer is set to NULL in these requests, then the private data is not delivered to the application for that event. If acsGetEventBlock() or acsGetEventPoll() returns a Private Data length of 0, then no private data is provided with this event. For events which report trunk group and trunk member information in the private data will have appropriate fields for them in the event structure. Following snippet shows how to extract the trunk information from the private data of a Delivered event.

retcode = acsGetEventBlock(acsHandle, (void *)&cstaEvent, &eventBufSize, (PrivateData_t *)&privateData, NULL);
if(rc == ACSPOSITIVE_ACK) // success case
{
if ((cstaEvent.eventHeader.eventClass == CSTAUNSOLICITED) && (cstaEvent.eventHeader.eventType == CSTA_DELIVERED))
{
if (privateData.length > 0)
{
// Confirmation contains private data
if (attPrivateData(&privateData, &attEvent) != ACSPOSITIVE_ACK)
{
// Decoding error
}
else if( attEvent.eventType == ATT_DELIVERED)
{
ATTDeliveredEvent_t *deliveredEvent = attEvent.u.deliveredEvent;
DeviceID_t Group = deliveredEvent.trunkGroup ;
DeviceID_t member = deliveredEvent.trunkMember;
}
}
}
}

Yes, to develop software applications using TSAPI, the TSAPI Client version and the TSAPI SDK version must be the same. For example, TSAPI SDK 4.1 should be used with TSAPI Client 4.1.

Follow the 'DevConnect Search' link in the left navigation bar of this page; enter the keywords of 'TSAPI Client' and check the SDKs/APIs box; Click 'Submit'; Examine the results for the highest numbered release (sometimes it is necessary to look at the "From Page:" information below the specific link to the information to find the release information).

Release 4.1.0 of the AE Services TSAPI client used with AE Services Server 4.1.x contains several enhancements from AE Services Release 3.1, as described below:

  • The AE Services Release 4.1.0 TSAPI Windows client library provides support for secure client connections with a Release 4.1 AE Services Server via Transport Layer Security (TLS).
  • The AE Services Release 4.1.0 TSAPI Windows client library provides better detection of network connectivity problems when communicating with a Release 4.1 AE Services Server.
  • The AE Services Release 4.1.0 TSAPI Windows client library allows up to four alternate TSAPI links (Tlinks) to be specified for a given TSAPI link. In the event that the library is unable to connect to the preferred TSAPI link, it will attempt a connection to an alternate TSAPI link.
  • AE Services Release 4.1.0 Avaya Private Data Library enhances private data version 7, enabling applications to receive additional call event reports during predictive call scenarios.
  • The AE Services Release 4.1.0 Avaya Private Data Library now supports private data version 8. Private data version 8 provides applications with access to the single-step transfer call feature.

When external party joins the conference call, trunk information such as trunk member and trunk group is available in the private data in the Established Events. This trunk related information is not available in the connection clear event, i.e. when a party drops out of the call.

In TSAPI, if a call is connected through a trunk with an unknown device identifier, a dynamic device identifier is created for the purpose of identifying the external party. The TSAPI service may use different dynamic identifiers to represent the external parties connected to the same trunk at different times. A trunk identifier is meaningful to an application only for the duration of the call and cannot be retained and used at a later time. The party which dropped out can be found with the help of this dynamic device id. For example, if one off-PBX extension joins the conference call, then a dynamic device id will be assigned to it (example: T478#3) for that call. This off-PBX number will have trunk group member and trunk member associated with it for the current call duration. So when the T478#3 is dropped out, then it means that the extension associated with the trunk group number and group member has dropped out.

There are two ways to do this:

  • Monitor the device using cstaMonitorDevice() to initiate event reporting for a specific device. Call ID can be extracted from the call control events such as delivered, established, etc. The Application will continue to receive the events until Monitor Stop Service is used.
  • Using snapshotdevice() method, the call ID for calls which exist at that moment at the device can be obtained. Device Snapshot Services return information about calls that are associated with a given CSTA Device objects. This information includes a list of calls associated with the given Device and the Connection State of each call (at that Device).

The error "CSTA_UNIVERSAL_FAILURE_CONF, error: 33(RESOURCE_BUSY)" indicates that the requested device is busy or not in the idle state.

The device can be in a "busy" state ("not idle") in the following situations:

  • The user at the specified extension is busy on a call.
  • The switch is busy with another CSTA request. This can happen when two TSAPI Services are issuing requests, such as, Hold, Retrieve Call, Clear Connection, Make Call, etcetera, for a common device.

Information on error responses to requests can be found in the "Avaya MultiVantage Applicatio Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference" document for the release of the API you are working with.

When a device is not connected or switches to out-of-service state, after the device monitor is started, monitoring for this device ends. The application will receive a cstaMonitorEndedEvent reporting this situation. The application must periodically try to re-establish the monitor. The monitor will be successfully established when the device is back in "in-service" state.

Communication Manager uses the Monitor Ended Event Report to cancel a subscription to a previously requested cstaMonitorCall, cstaMonitorDevice or cstaMonitorCallsViaDevice() Service when a monitor object is removed or changed to become an invalid object by switch administration or when the switch can no longer provide the information.

Following are the reasons for the "acsOpenStream()" method to return negative values:

  1. Returns -1 (ACSERR_APIVERDENIED): The requested API version (apiVer) is invalid or the client library does not support it.
  2. Returns -2 (ACSERR_BADPARAMETER): One or more of the parameters is invalid.
  3. Returns -4 (ACSERR_NODRIVER): No TSAPI Client Library Driver was found or installed on the system.
  4. Returns -5 (ACSERR_NOSERVER): The advertised service (serverID) is not available in the network.
  5. Returns -6 (ACSERR_NORESOURCE): There are insufficient resources to open an ACS Stream.

This error occurs when the Security Database (SDB) is turned on and the CTI user login that is used by the TSAPI application does not have the permission to access the database. There are two possibilities why you might encounter the above specified error:

  1. The SDB is enabled. If there are no more dependencies on SDB for the application then disabling the SDB will resolve the issue. Avaya does not recommend this approach for field sites. It is appropriate for lab testing environments.
  2. The CTI user configured on AE Services may have limited access to the device it is attempting to control. By changing the administration of the CTI user or the devices it is allowed to operate on, the problem can be corrected. The CTI security data base on AE Services can be accessed via the web based OA&M interface by navigating through the following path: Administration > Security Database . The procedures for provisioning the SDB are covered in chapter 5 of Avaya MultiVantage® Application Enablement Services Administration and Maintenance Guide Release 4.1 document number 02-300357, Issue 8, December 2007. This is the preferred solution.

The Automatic Call Distribution (ACD) extension should be monitored in order to get the agent logged in and out state change events. Use the cstaMonitorDevice() request with the ACD/Hunt Group extension as the input parameter to establish this monitor. By putting a monitor on a hunt group the application will get events every time agents login or logout. To stop getting such events, use the cstaMonitorStop()request.

After establishing the monitor, the ACD/hunt group should be queried to see if there are already any agents logged in. Use the attQueryAgentLogin() request with the hunt group's extension for this task. The system's response includes the number of logged in agents, and the station extension's of the logged in agents. The application should then use the cstaQueryAgentState() request to discover the status of each logged in agent (e.g. Work mode, Talk mode, etc). The application can use the cstaQueryDeviceInfo() request to discover the station extension to agent extension binding.

To receive other agent state change events, the agent extension or station extension must be polled by the application using the cstaQueryAgentState() request.

Multiple copies of an event will occur when the cstaMonitorDevice() request is called multiple times on the same device. The cstaMonitorDevice() request adds the device (e.g. station) being monitored into a list of monitors. If a single device is being monitored multiple times, the application receives an event for each of the monitors started for the device.

The 'PRIVILEGE_VIOLATION_ON_SPECIFIED_DEVICE' error occurs because of any one of the following reasons:

  1. Invalid destination specified.
  2. Toll restrictions on destination
  3. COR restrictions on destination.
  4. Destination is a remote access extension.
  5. Call origination restriction on the redirecting device.
  6. Call is in vector processing.

The service observing feature provided by Communication Manager allows a 'supervisor' to eavesdrop on a specified agent and customer conversation in either the "no-talk", "listen only" or the "listen and talk" service observing mode. To access this functionality this through a TSAPI application, the application makes use of the MakeCall method with the appropriate service observing FAC (Feature Access Code) and the extension that the agent logged in from. For example, if the Talk/Listen Service Observing FAC is *70 and the extension the agent logged in from is 4000, a MakeCall request would be issued with *704000 as the called party. The MakeCall() request is issued on behalf of a third extension (the observer). In a call recording scenario this third extension is typically a DMCC softphone (client media mode device) which records the agent/customer conversation, but that is not a requirement for service observing.

There are three FACs associated with service observing. The application must decide which mode it wishes to be in for the duration of the service observing session when it invokes service observing.

  • Listen only - the service observer can hear the conversation but can not be heard.
  • Listen/Talk - the service observer can hear and be heard.
  • No Talk - This mode is used by call recording applications since it reduces timeslot consumption on G650 gateways increasing call recording capacity on the system.
In all modes the agent and customer are unaware of the service observing party unless the service observer talks.

An alternative way to "eavesdrop" on a conversation would be to use the "SingleStepConference" operation. The difference in this method when compared to the former is that the application would have to get the call ID for the call in question. It can be done by either by monitoring all agents and tracking the call ID in the call progress events, or by issuing a SnapshotDevice command on the agent extension. The Single Step Conference can be done in either Silent or Active mode. In Silent mode the observer can not be heard, or 'seen'. In Active mode the observer can talk and listen to the conversation and is 'seen' via a display update. In Silent mode the agent and customer are unaware of the listen in party through the system station display.

With servicing observing and single step conference the additional party in the call can be discovered either through CTI events, system access terminal commands, unexpectedly encountering system parties in a call limits, and other feature interactions.

For more information on Service Observing see section "Service Observing" from document Feature Description and Implementation for Avaya Communication Manager 555-245-205 Issue 6 January 2008.

When any TSAPI application tries to access a device, either for call control or monitoring purposes, TSAPI service performs validation and verification before providing the access to the device. When any of these validations fail for a device, the error TSERVER_DEVICE_NOT_SUPPORTED (35) is returned. It is necessary to understand this validation sequence and then ensure that the configuration is correct.

  1. If the Security Database (SDB) is enabled then the access to devices is validated as per the SDB. In a test setup, applications may choose to disable the SDB and then no further checking is required. However, Avaya recommended use of SDB for security reasons in fielded applications. To verify if the SDB is enabled, please browse to "CTI OAM Administration > Administration > Security Database > SDB Control" is enabled for DMCC and TSAPI/JTAPI services.
  2. If the SDB is enabled, then CTI user credentials provided by the application must be valid and the CTI user should have permissions to perform the desired operations. There are various service types such as Call Origination and Termination, device/device call/device and call/call. Permissions can be set to restrict access to any of these services for any CTI user. Setting a CTI user to "unrestricted" access allows access to all the service types and all devices. Developers should ensure that the right permissions are set for the CTI user used by the application. To verify or change the permissions browse to "CTI OAM Administration > Administration > Security Database > CTI Users > List All Users", then select the desired user and click Edit.
  3. If the user does not have unrestricted access, then access to any device depends upon the device configuration. The device type needs to be set appropriately set to PHONE/VDN/AGENT ID to gain access permission. To verify this, browse to "CTI OAM Administration > Administration > Security Database > Devices", select the appropriate device and click Edit Device" and check the device Type.
  4. Every device, added to the SDB, is associated with a Tlink group. This group restricts which devices can be accessed with a selected Tlink (aka switch connection). To verify the device is associated with the Tlink provided by the application, browse to "CTI OAM Administration > Administration > Security Database > Devices, select the appropriate device and click Edit Device" and check the tlink group associated with this device. Now browse to "CTI OAM Administration > Administration > Security Database > Tlink Group", select the appropriate Tlink group and click Edit Tlinks Group" and check if the Tlink selected by the application is part of this group.
The user should ensure that the configuration is correct with respect to the above mentioned parameters, User may refer chapter "The Security Database" from Avaya MultiVantage® Application Enablement Services Administration and Maintenance Guide Release 4.2 02-300357 Issue 10 May 2008

In TSAPI, to know which extension an agent is logging into, use the 'cstaMonitorDevice' function to monitor the hunt group extension. Then the application will get Login and Logout event reports for agents logging in and logging out of that hunt group. The application can also use the 'attQueryAgentLogin' function to find out which agents are logged into a particular hunt group. Then, the 'cstaQueryDeviceInfo' function can be used to query the agent ID so as to know which extension it is logged into. The 'cstaQueryAgentState' service provides the application with the current agent state for a device. For more details, see Chapter 4 - "Switching Function Services" of the document Avaya MultiVantage Application Enablement Services TSAPI Programmer's Reference, 02-300545, Release 4.1, December 2007, Issue 3.

The latest TSAPI SDK version available for supporting the Solaris SPARK platform is R3.1. Please refer to Avaya MultiVantage® Application Enablement Services TSAPI, JTAPI, and CVLAN Client and SDK Installation Guide Release 3.1.0, Document number 02-300543, Release 3.1.0, June 2006, Issue 3 for more details about the Solaris version. In AE Services R4.1 and later, support for Solaris and other operating systems such as HP-UX and SCO UnixWare has been discontinued.

1. Navigate to the Release History in the main Avaya Aura Application Enablement Services topic.

2. Select the AE Services release you are using to open to the appropriate Release Contents topic.

3. Select TSAPI Downloads in the Topic Contents box.

4. Click on the link to the TSAPI Programmer's Reference.

CSTA is a protocol whereas the TSAPI library is Avaya's implementation of the CSTA protocol. It is not possible to use any implementation of CSTA protocol other than the Avaya's implementation to communicate with Avaya's Communication Manager through Avaya's AE Services server. Avaya's implementation of CSTA protocol is provided as TSAPI library. Avaya's TSAPI service and DMCC services are the only ways to communicate with the Avaya's AE Services server using the CSTA protocol. The TSAPI service conforms to the CSTA I specification and provides the call control functionality. The DMCC Service conforms to the CSTA III specification and provides first party as well as third party call control.

There are two different categories for events that an application can receive - UNSOLICITED includes ACSUNSOLICITED/CSTAUNSOLICITED events and CONFIRMATION includes ACSCONFIRMATION/CSTACONFIRMATION events.

A CONFIRMATION event is received as a response to a TSAPI request. There is only one response or confirmation event sent for each TSAPI request. The application needs to setup the notification mechanism for receiving these events. For example, the TSAPI service will send CSTAMakeCallConfEvent to an application after it (TSAPI) has successfully processed the cstaMakeCall() method.

UNSOLICITED events report state changes of various objects, such as call or device objects, managed by Communication Manager. In addition to setting up the notification mechanism, applications need to start the monitors on the desired object (call or device). Once the monitor is started, any changes to the object state are reported to the application through these events. Multiple unsolicited events could be received for a single monitor. For example, after a call monitor is started by the application, events such as CSTA_DELIVERED, CSTA_ESTABLISHED are sent to the application when the call state changes.

Whenever any TSAPI application is initialized, a session is established with the AE Services server in the form of an ACS stream over which all the requests and responses are sent and received, respectively. The TSAPI service sends a heartbeat event at a regular interval to indicate that the communication channel is still open for further requests. These internal heartbeat events are sent to the TSAPI client at a regular interval called the "heartbeat interval". The TSAPI service will only send a heartbeat event if no other events have been sent to the TSAPI client for the same stream within the last heartbeat interval, and thereby avoiding undue network traffic. When the TSAPI client does not receive two successive heartbeat events within the heartbeat interval duration, the TSAPI client library assumes a network failure and notifies the application with the ACSUNSOLICITED ACS_UNIVERSAL_FAILURE_CONF event.

With AE Services server Release 4.1.0 or later, a TSAPI application can set this heartbeat interval value. The following code sample illustrates how to set the heartbeat interval in TSAPI.

ACSHandle_t acsHandle;		// handle for ACS stream
InvokeID_t invokeID;		// invoke ID for the request
unsigned short interval_value;	// heartbeat interval value, this can not be
					// less than 5 or greater then 60, and by
 					// default this value is set to 20

// With AE Services server 4.1 the last parameter (i.e. privateData) is
// ignored for acsSetHeartbeatInterval(). 
RetCode_t rc = acsSetHeartbeatInterval(acsHandle,invokeID,interval_value, NULL); // set as NULL

// If the function is successfully executed, then a positive value is 
// returned when library generated InvokeIDs are used. 
// In case application generated InvokeIDs are used, then a successful
// completion of the function returns ACSPOSITIVE_ACK and a negative value if
// the function fails.
					

The "Auto In" and "Manual In" Agent work modes differ in the state Agent automatically moves to after handling a call. In the "Auto In" mode, Agent stays in the "READY" state whereas in "Manual In" mode Agent's state changes to "WORK_NOT_READY" after handling a call.

In TSAPI, Agent's work mode can be selected using the cstaSetAgentState method. The following code snippet illustrates how to change the agent work mode and state.

PrivateData_t privateData;		// Privatedata
ACSHandle_t m_acsHandle;		// handle return by acsOpenStream
InvokeID_t invokeID;		// APP_GEN/LIB_GEN
DeviceID_t device;			// Agent Terminal 
AgentMode_t agentMode;		// the mode in which Agent logs in
AgentPassword_t agentPassword	// Agent Password
AgentID_t AgentID;			// AgentID
AgentGroup_t agentGroup;		// Hunt Group Extension (optional)
ATTWorkMode_t workMode;		// "AutoIn"/"ManualIn"
RetCode_t retcode;			// return value from the API
long reasoncode;

agentMode = AM_LOG_IN;		// Requested Agent Mode, allows agent to log 					// in
	
// attV6SetAgentState(privateData, workMode, reasoncode, enablePending)
// this function is used here to set the workMode for Agent.
// workMode is a g3Private Data variable; thus it needs to be set using this
// method. The V6 version of this method is used here as its structure is
// retained for further PDV environment (i.e. PDV 7 and PDV 8) for setting
// Agent's workMode

workMode = WM_AUTO_IN;		// for "AutoIn mode"
//  workMode = WM_MANUAL_IN;	// for "ManualIn mode"

// When Agent Log's in with agentMode as "AM_LOG_IN" then while setting
// privateData information, reasoncode is ignored.

retcode = attV6SetAgentState((ATTPrivateData_t *)&privateData,
				  workMode,	// "WM_AUTO_IN/WM_MANUAL_IN"
				  reasoncode,	// can be set to 0
				  FALSE);	// enablePending flag, set to 							// FALSE, not significant while 							// login Agent 
if (retcode < 0) 
{
	//Error encoding private data 
}


retcode = cstaSetAgentState (m_acsHandle,
				  (InvokeID_t)invokeID,
				  (DeviceID_t *)&device,
				  agentMode,
				  (AgentID_t *)&agentID,
				  (AgentGroup_t *)&agentGroup,
				  (AgentPassword_t *)&agentPassword,
				  (PrivateData_t *)&privateData);

if (retcode < 0)
{
	// error setting the agent state
}
	

The procedure to order the TSAPI SDK is listed below:

  1. Login to the DevConnect portal at http://www.avaya.com/devconnect.
  2. Click on the link for Procurement from the left hand navigation box.
  3. Click on the link for Access DevConnect Procurement Benefits in the middle of the page.
  4. Click on the link for Request Procurement in the middle of the page.
  5. Click on the link for Request Procurement to the left of the Quick Response Solution.
  6. Click on the Details/order link to the left of TSAPI SDK vX.Y (the version will change periodically) which is the eighth procurement offer on this page.
  7. Complete this page and place the order.
The user will receive an email from Innovative Development with an invoice within one business day.

CSTA_MONITOR_ENDED is an unsolicited event received by the application indicating that the monitor associated with the monitorCrossRefID provided with the event has been stopped. One of the causes for this event is EC_RESOURCE_NOT_AVAILABLE, which is encountered when a previously monitored object is no longer available or valid due to switch administration changes or communication protocol errors. For example, when a monitored extension is removed from Communication Manager, the CSTA_MONITOR_ENDED event is generated with EC_RESOURCES_NOT_AVAILABLE as the error cause.

The TSAPIPlatformException exception indicates an implementation specific error that denotes some form of an unrecoverable platform specific problem. The error code 33 (RESOURCE_BUSY) indicates that the resource in question (e.g. a station, a PBX (i.e. Avaya Communication Manager), an agent etc.) is busy with some other activity.

Thus, while setting an agent's state to ACW, the TSAPIPlatformException exception is encountered with the error code set to 33 (RESOURCE BUSY) which indicates that an agent is already busy with some other call. Moreover, the agent's state control (BUSY) is handled by Communication Manager and a change in the agent's state from BUSY to ACW/WORK_NOT_READY using the API is not allowed to the application. Thus, for any invalid state changes, the TSAPIPlatformException exception is thrown. Once the agent is in READY_STATE, its state can be changed to ACW.

From private data version 6, the cstaSetAgentState function allows the application to defer the state change using the enablePending flag. If this flag is set to true, the requested state change will be made pending and will take effect as soon as the agent clears the call. The request in such cases will be positively acknowledged.

When an application creates the cstaMonitorCallsViaDevice request on either the ACD Split device (i.e. hunt group extension) or a VDN (Vector Directory Number), information for the calls involving the ACD Split device or the VDN will be sent to the application through call events. Communication Manager provides a Delivered and an Established event through which information such as the calling device, the alerting device, the called device and the monitoring cross reference ID can be obtained.

The code snippet provided below can be used to retrieve call related information:

RetCode_t retcode = NULL;
CSTAEvent_t cstaEvent; 		// CSTA event buffer
unsigned short eventBufSzise; 	// CSTA event buffer size
ATTPrivateData_t privateData; 	// ATT service request private    
                                 // data buffer

eventBufSzise = sizeof(CSTAEvent_t);
privateData.length = ATT_MAX_PRIVATE_DATA;

retcode = acsGetEventBlock(acsHandle, (void *)&cstaEvent,  
           &eventBufSzise, (PrivateData_t *)&privateData, NULL);

if (retcode != ACSPOSITIVE_ACK) 
	return;    
if (cstaEvent.eventHeader.eventClass == CSTAUNSOLICITED && 
         cstaEvent.eventHEader.evnetType == CSTA_DELIVERED)
{
	SubjectDeviceID_t AlertingDevice;
	CalledDeviceID_t calledDevice;
	CallingDeviceID_t callingDevice;

	AlertingDevice = 
	cstaEvent.event.cstaUnsolicited.u.delivered.alertingDevice;
						// gives the alerting device 
	calledDevice = cstaEvent.event.cstaUnsolicited.u.delivered.calledDevice;        
						// gives the calledDevice
	callingDevice = 	   cstaEvent.event.cstaUnsolicited.u.delivered.callingDevice;    
						// gives the calling Device
}
		

The ACS_UNIVERSAL_FAILURE : TSERVER_STREAM_FAILED error occurs when the TSAPI client library detects a connection failure with the AE Services server. The connection may be broken by the AE Services server due to any one of several errors reported to the TSAPI client before the connection was broken. In such cases, the resolution path would be the resolution for the errors reported earlier. In some cases, the error cannot be reported to the client and the AE Services log files must be examined for the root cause of the issue. These are typically buffer overflow problems caused due to a high traffic rate from the AE Services server to an application which is not properly designed to handle such an amount of traffic.

If no other errors are received from TSAPI services, then it needs to be verified that the TSAPI service and the AE Services server are still running and that there are no network connectivity problems. To do this, log into the AE Services OA&M web page, browse to CTI OAM Administration -> Maintenance -> Service Controller and check the status of the TSAPI service as running. A ping is an adequate first level network connectivity verification tool, but intermittent problems may need to be diagnosed with more sophisticated analysis tools (for example, packet sniffers).

The CSTA_MONITOR_ENDED event indicates that the object being monitored no longer exists. For example, if a call monitor is added on a call object, then the monitor ends when the call is terminated. In case of a device monitor, this event may be received due to the device becoming unavailable. This may be due to switch administration, device maintenance state changes or AE Services to/from Communication Manager connectivity state changes.

When the CSTA_MONITOR_ENDED event is received, it indicates that the application will not receive any more events for the referenced monitored object.

The application will not automatically start receiving events for the previously monitored call/device even if the monitored object becomes valid again. The application needs to add a new monitor on the desired object and start again.

The AE Services Release 4.1 TSAPI Windows client library provides a better detection of network connectivity problems when communicating with a Release 4.1 AE Services server. The client library monitors "heartbeat" messages from the AE Services server. If two consecutive heartbeat messages are missed, the client library reports a stream failure, closes the ACS stream, and notifies the application with an ACSUniversalFailureEvent event with the TSERVER_STREAM_FAILED error code.

No application changes are necessary to take advantage of this new capability. The default interval between heartbeat events is twenty (20) seconds. An application may change this interval using the new ACS service acsSetHeartbeatInterval(). In addition to Windows, the heartbeat functionality is also available for the Linux platform. The way that the developer is notified of the stream failure is via an ACSUniversalFailureEvent event.

A sample code snippet to detect a stream failure is shown next.

RetCode_t rc; 
CSTAEvent_t eventBuf; 
unsigned short eventBufSize; 
EventClass_t eventClass; 
EventType_t eventType; 
unsigned short numEvents; 
ATTPrivateData_t privateData; 
ACSUniversalFailure_t acsError; 

/* Initialize buffer sizes */ 
eventBufSize = sizeof(CSTAEvent_t); 
privateData.length = sizeof(privateData.data); 

/* Block for event */ 
rc = acsGetEventBlock (acsHandle, (void *)&eventBuf, &eventBufSize,
	(PrivateData_t*)&privateData, &numEvents);

if (rc != ACSPOSITIVE_ACK)
{ 
	/* Handle error condition */ 
	return; 
} 

eventClass = EventBuf.eventHeader.eventClass; 
eventType = EventBuf.eventHeader.eventType; 

if (eventClass == ACSUNSOLICITED && eventType == ACS_UNIVERSAL_FAILURE) 
{ 
	acsError = eventBuf.event.acsUnsolicited.u.failureEvent.error; 
	if (acsError == TSERVER_STREAM_FAILED) 
	{ 
		/* Network connection has been lost */ 
		return; 
	} 
}
		
For more information on ACSUniversalFailureEvent and acsSetHeartbeatInterval(), refer Avaya MultiVantage®Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4, section Control Services, subsection ACS functions and confirmation events.

An announcement is a recorded message a caller may hear while the call is in a queue, or when a call receives intercept treatment for some reason. The source or the storage unit for announcements can be integrated in a server or an external unit. Integrated announcements reside on a circuit pack in the switch carrier or on an Avaya G700 media gateway Virtual Announcement Board (VAB).

Announcement extensions are the virtual or logical extensions administered on Communication Manager that are accessed to hear the announcement.

To add an announcement extension, use the SAT terminal to run these commands:

  • Use the SAT command add announcement <extension number>.
  • In the Extension field, type the extension number xxxx.
  • In the COR field, type a valid Class of Restriction code.
  • In the Annc Name field, type the name for this announcement.
  • In the TN field, type a valid tenant number.
  • In the Annc Type field, type 'integrated'.
  • Rest of the fields can be accepted with their default values.
  • Press Enter to save the changes.
  • Use the SAT command list station data-module to determine the announcement extension.
Single Step Conference (SSC) cannot be used to SSC in an announcement extension because an announcement extension does not respond properly to the forced off-hook request used by SSC.

Instead of performing a Single Step Conference, a Consultation Conference could be used to listen to the announcements. Using Consultation Conference poses the risk that the very first part of the announcement could be clipped if the application does not complete the conference request quickly enough.

The prerequisites to run an application on TSAPI are as follows:

  1. A TSAPI client should be installed on the machine deploying the application. The latest TSAPI client version is available at http://www.avaya.com/devconnect.
  2. The following dlls should be copied to the C:\WINNT\system32 folder on the machine:
    • ATTPRV32.dll
    • Csta32.dll
    • Instsrvc.dll
    • AES-libeay32.dll
    • AES-ssleay32.dll
    • The TSLIB.INI file
  3. The registry entry HKEY_LOCAL_MACHINE\SOFTWARE\Avaya\TSAPI Client\3.1\IniDirectory must be available with the path set to the location that the TSAPI client was installed (the default path is C:\Program Files\Avaya\AE Services\TSAPI Client\) so that the TSAPI client library can locate the TSLIB.INI file and other installed files (such as the Trusted Certificate Authority certificate when making a secure TSAPI client connection).

TSAPI libraries for Avaya AE Services are supported only on two operating systems: Windows and Linux. Avaya no longer supports TSAPI libraries for HP-UX and Solaris operating systems starting with AE Services server version 4.0.

No, Avaya's implementation of TSAPI is not compatible with C#. Avaya's TSAPI implementation is a C/C++ based API that provides third party call control capabilities using Avaya Communication Manager.

An extension can be either in an Idle (on-hook) or in a Busy (off-hook) state. In TSAPI, the attQueryStationStatus()method can be used to retrieve the extension's state. It is also possible to get the state of an extension using the cstaSnapshotDeviceReq() method that returns details about each call on the device and status of the extension. Refer to the screenshot below that shows the output of the cstaSnapshotDeviceReq() method invoked using TSAPI exerciser.


As seen in the figure above, the extension's state is Idle when it doesn't have a call and its state is Busy when there is a call at the station.

Please refer to the following FAQ available on http://www.avaya.com/devconnect to validate the configuration between the AE Services server and Avaya Communication Manager: What are the steps to verify that the communication channel between the AE Services server and Avaya Communication Manager is configured correctly?

Even if the configuration is correct, TSAPI Test can fail to run successfully due to several reasons:

  1. Confirm that the TSAPI client has been installed and configured correctly on the machine where test application is running. For information about installing and configuring TSAPI client, see Avaya MultiVantage® Application Enablement Services TSAPI, JTAPI, and CVLAN Client and SDK Installation Guide, 02-300543.
  2. For details on error codes, refer to "Appendix A: Universal Failure Events" in Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4.
  3. In TSAPI Test Application, select the desired Tlink in the Server field and enter the CTI username and password that is allowed to access the Tlink, in the respective fields. If the user is not a valid CT user or the password is incorrect, the TSAPI Test application will fail, as shown in the screenshot below.


  4. If the extension number mentioned in the From field does not exist in Avaya Communication Manager, then TSAPI Test returns an invalid csta device identifier(12) error message as shown in the screenshot below.


  5. If the CTI user has restricted access, change the user to have unrestricted access by browsing to and the CTI OAM Administration -> Administration -> Security Database -> CTI Users and change the user to unrestricted access. If this works follow the procedures in Avaya MultiVantage® Application Enablement Services Administration and Maintenance Guide, Release 4.2, 02-300357, Issue 10, May 2008 to properly configure the Security Database.

    If using an unrestricted user does not correct the issue, then the problem lies in Communication Manager. Attempt the test call using the physical station. Consult Communication Manager technical support organization for further assistance.

    Note that TSAPI Test Application can only be used on certain station types - the ones with speaker phones and under certain conditions with an Analog phone.

  6. There are a couple of related FAQs available on http://www.avaya.com/devconnect in the TSAPI FAQ section related to troubleshooting the situation, as outlined below:
    1. What would cause TSAPI Test on the AE Services server OAM (Operations Administration and Maintenance) web page to fail with "ACS Universal Error 35?"
    2. Why does the TSAPI Test application fail with the error: "No device records found?"

The TSERVER_BAD_PDU error occurs when the TSAPI service cannot parse the request data received from a TSAPI client. This happens when the TSAPI client library from a higher version sends a service request which is available only in the higher version to a lower version TSAPI service. In this case, the TSAPI service is unable to parse the request and returns the TSERVER_BAD_PDU error. For example, when a TSAPI 4.1.0 client sends a acsSetHeartbeatInterval request (supported in TSAPI service version 4.1.0 and later) to a TSAPI 4.0.0 service, the TSAPI service returns the TSERVER_BAD_ERROR error.

This error can be avoided by using only the API methods supported by the TSAPI service serving the request. An application can check the TSAPI service version using the "tsrvVer" field in acsOpenStreamConfEvent.

For further information about the services that are supported in a particular TSAPI version, refer to the document titled Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference.

Telephony Services Application Programming Interface (TSAPI) is an Avaya specific implementation of the Computer Supported Telecommunications Applications (CSTA) standard. Avaya's TSAPI implementation requires the use of Avaya's TSAPI Client. Non-Avaya CSTA API implementations are typically not compatible with the Avaya TSAPI service implementation on Avaya Applications Enablement Services (AE Services). Avaya only provides support for applications using the Avaya TSAPI client.

In TSAPI, the cstaSetAgentState() request can be used to set the reason code for a Call Center Agent. The method allows a client application to login or logout a Call Center Agent to/from a Split and to specify a change to the work mode for a Call Center Agent along with a reason code. The method takes 'Device', 'AgentMode', 'AgentID', 'AgentGroup' and 'AgentPassword' as parameters, and 'Work Mode', 'Reason Code' and 'Enable Pending' as Private Data parameters. The reason code can be set only if the 'AgentMode' is being set to 'Not Ready', 'Work Not Ready' or 'Logout'.

Private Data version 7 and later supports reason codes in the range of 0 to 99. Private Data versions 5 and 6 support single digit reason codes from 1 through 9. Private Data version 4 and earlier does not support reason codes. A reason code value of '0' means that the reason code is not available. Logout reason codes can only be in the range of 0 to 9.

An invokeID is a unique numeric identifier used to match a confirmation/failure event with the corresponding Telephony Services API (TSAPI) service request.

There are two options supported by the Avaya TSAPI to generate and associate an invokeID with the TSAPI service requests:

  1. Application generated invokeID (APP_GEN_ID): If the application chooses this option, then it is the application's responsibility to provide a unique numeric value in the invokeID parameter in all successive TSAPI service requests for a session wherever applicable. An application can choose this option by passing APP_GEN_ID in the invokeIDType parameter of the acsOpenStream() method.
  2. Library generated invokeID (LIB_GEN_ID): If the application chooses this option, then the TSAPI Client library generates a unique numeric value in the invokeID parameter (on behalf of the application) for all successive TSAPI Service requests for a session wherever applicable. In this case, the return value of a method is the invokeID generated by the TSAPI client library for the corresponding request. An application can choose this option by passing LIB_GEN_ID in the invokeIDType parameter of the acsOpenStream() method.
The application has to specify one of the above mentioned invokeID types while opening a session with TSAPI Service. The invokeID type once selected during the acsOpenStream()method call cannot be changed later, and the type selected remains valid till the session is closed. In both the cases, the TSAPI Service will send this same invokeID value in the confirmation/failure event for the corresponding TSAPI Service request

For more information on, how a TSAPI application can match the confirmation/failure event with the corresponding TSAPI Service request, refer to the FAQ document titled "How does a TSAPI application relate a particular ACS or CSTA confirmation/failure event with the corresponding TSAPI service request" available on the DevConnect portal at https://www.avaya.com/devconnect.

For more information about the invokeID types, refer to the acsOpenStream()method description in the section ACS functions and confirmation events of the document titled Avaya MultiVantage Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference Doc-ID: 02-300544, Release 4.2, May 2008, Issue 4 available on http://www.avaya.com/devconnect.

TSAPI Client provides the following two APIs for terminating the active communication channel (i.e., ACS Stream) between the application and the AE Services Server:

  1. acsCloseStream()
  2. acsAbortStream()

While both acsCloseStream() and acsAbortStream() serve a similar purpose, there are some differences between them. A list of these differences is presented below:

  1. In the case of the acsAbortStream(), the ACS Stream's handle becomes invalid immediately after the acsAbortStream() returns, while in the case of acsCloseStream(), the Stream's handle remains valid until the application receives a corresponding confirmation event for acsCloseStream().
  2. In the case of acsCloseStream(), there is an associated confirmation event, while there is no associated confirmation event for acsAbortStream().
  3. In the case of the acsAbortStream(), the system frees all resources associated with the aborted ACS Stream immediately, including any events queued on this Stream, while in the case of acsCloseStream(), the application will continue to receive events until it receives the confirmation event for the acsCloseStream() . Once the confirmation event is received, the system will free all resources associated with the closed ACS Stream.

An application relates a particular ACS or CSTA confirmation/failure event with the corresponding TSAPI Service request by comparing the invokeID value passed in the TSAPI Service request with the invokeID value received in the confirmation/failure event. The invokeID value needs to be unique so that the application can relate a particular ACS or CSTA confirmation/failure event with the corresponding TSAPI Service request.

The sample code snippet below shows how an application sends the invokeID in a TSAPI method.

// The code snippet below shows how to send invokeID in the monitor request.

// Assuming APP_GEN_ID value has been passed in invokeIDType parameter in the 
// acsOpenStream() method, thus this application itself generates and provides 
// a unique invokeID value in the service request.  
// If the application is designed to use Library generated invokeID, then the 
// return code of the called method will act as an invokeID.

ACSHandle_t ulAcsHandle;		// handle returned by the 
                                        // acsOpenStream() method.

unsigned long ulInvokeIDforDevice = GenerateUniqueNumber();
				// GenerateUniqueNumber() method
				// is a user defined method that
				// returns a unique numeric value. The 
				// application can choose any appropriate 
				// implementation.

DeviceID_t szDeviceID= "40010";   	// Set the deviceID of the device to
                                        // be monitored.
CSTAMonitorFilter_t noFilter;           // for storing the monitor filter setting

// Passing 0 to the call filter indicates that this application will receive 
// all the supported call events.
noFilter.call = 0;

// The Agent Filter, Feature Filter, and Maintenance Filter are not supported 
// in Avaya's CSTA implementation when a device is monitored. If one of these 
// is present, it will be ignored.
noFilter.agent = 0; 
noFilter.feature = 0;	
noFilter.maintenance = 0;

// By setting no private filter, all private Events will be received.
noFilter.privateFilter = 0;
			
RetCode_t nRetCode;	              // stores the return code of the request.

nRetCode = cstaMonitorDevice (ulAcsHandle,           // ACS Stream's Handle.
			ulInvokeIDforDevice , // invokeID to be sent. 
			&szDeviceID,          // Device to be monitored.
		                     &noFilter,            // monitor Filter. 
		 	NULL);                // this parameter is 
                                                               // optional and is passed 
                                                              // as NULL here.
if (nRetCode < 0)
{
		// some error occurred while sending the request
		cout<< "Failed to monitor Device" <<endl;
		cout<< "Error Code: "<<nRetCode; 
		// handle error.
} // end of if

 

// for demonstration purposes, another call to cstaMonitorDevice is made for 
// monitoring a Hunt-group Extension with a different invokeID value.

DeviceID_t szHuntgroupID= "49000";

// Call the custom GenerateUniqueNumber() routine to generate another unique 
// number.
unsigned long ulInvokeIDforHuntgroup = GenerateUniqueNumber(); 

nRetCode = cstaMonitorDevice (ulAcsHandle,     		// ACS Stream's Handle.
		ulInvokeIDforHuntgroup, 	// invokeID to be sent. 
		&szHuntgroupID,        		// Hunt-group Extension
					// to be monitored.
			&noFilter,	          	// monitor Filter. 
		 			NULL);                			// this parameter is 
					// optional and is passed 
					// as NULL here.
	if (nRetCode < 0)
{
		// some error occurred while sending the request
		cout<< "Failed to monitor Hunt-group device" <<endl;
		cout<< "Error Code: "<<nRetCode; 
		// handle error.
} // end of if

// When the application receives the corresponding confirmation/failure event
// for the two monitor requests, the application can use invokeID to 
// relate the confirmation/failure event to a particular monitor request. This 
// process is explained in the code snippet below.
		
The sample code snippet below shows how to retrieve the invokeID from the confirmation/failure event.
CSTAEvent_t cstaEvent;	// Assuming the event has been retrieved using one
                        // of the two methods i.e. cstaGetEventPoll() or
                        // cstaGetEventBlock() and the event data is
                        // preserved in cstaEvent.

unsigned long ulInvokeIDforDevice; // assuming the application has preserved
                                   // the invokeID it used while sending the
                                   // monitor request for monitoring a device
                                   // in ulInvokeIDforDevice variable.

unsigned long ulInvokeIDforHuntgroup; // assuming the application has preserved
                                      // the invoked it used while sending the
                                      // monitor request for monitoring a
                                      // Hunt-group in ulInvokeIDforHuntgroup
                                      // variable.

// The application can choose to maintain a deviceID-invokeID mapping to enable 
// invokeID lookup.

 
unsigned long ulRetrievedInvokeID; // To store the invokeID, received in the
                                   // confirmation event. 

// Check for the confirmation event
if (cstaEvent.eventHeader.eventClass == CSTACONFIRMATION)
{
		// extract the invokeID from the confirmation event received.
		ulRetrievedInvokeID = cstaEvent.event.cstaConfirmation.invokeID;	     	       
		cout<<" Retrieved InvokeID:"<< ulRetrievedInvokeID <<endl;

		// check for the event type
		switch(cstaEvent.eventHeader.eventType)
		{
			case CSTA_UNIVERSAL_FAILURE_CONF:
			{
				if (ulRetrievedInvokeID == ulInvokeIDforDevice)
				{
				    cout<<"Failure Event for monitor request for "
					  << "monitoring a Device";
				    // handle error.
				}// End of if

				else if (ulRetrievedInvokeID == ulInvokeIDforHuntgroup )
				{
				    cout<<"Failure Event for monitor request for "
 						  <<"monitoring a Huntgroup Extension" ;
				    // handle error
				}// End of else if
				break;
			}// End of case 

			case CSTA_MONITOR_CONF:	
			{		
				if (ulRetrievedInvokeID == ulInvokeIDforDevice)
				{
					cout<<"Monitor request for monitoring a Device is " 
					    <<"successful";
					cout<<"The application will receive call state "
 					    <<"change notifications for the call activity "
					    <<"on the monitored device ";		
				}// End of if

				else if (ulRetrievedInvokeID == ulInvokeIDforHuntgroup )
				{
				     cout<<"Monitor request for monitoring Hunt-group "
 					   <<"Extension is successful";
				     cout<<"The application will receive the Log-in/Log-
				     cout<<"out event when any Agent Log-in/Log-out ";
				         <<"on this monitored Hunt-group extension ";
				}// end of else If
				break;
			}// End of case
			default: 
			{
				cout<<" Some other confirmation event";
				break;
			}// End of default
		}// End of switch
	}// End of Outer if.

		

As demonstrated in the code above, the application can relate a confirmation/failure event with the corresponding issued TSAPI Service request by comparing the invokeID supplied in the monitor request with the invokeID retrieved from the confirmation/failure event.

Yes, a TSAPI application can use acsEnumServerNames()method to obtain a list of all the advertised services of a specific stream type offered by a given list of AE Services Server. Using acsEnumServerNames()method, the application can specify a callback method that will be called for each server name. When acsEnumServerNames()method is invoked by the application, the TSAPI Client library reads the Fully Qualified Domain Name (FQDN) or IP addresses of the AE Services Server from the TSAPI Client configuration file (i.e., TSLIB.INI). Using these FQDN or IP addresses, the TSAPI Client library queries each AE Services Server for advertised services of the given stream type. For each advertised service name returned by each AE services server, the TSAPI client invokes the callback method with the serverName parameter set to the advertised service name. The code snippet below demonstrates the use of the acsEnumServerNames() method.

// serverName contains name of advertised service name. This name can be used 
// as serverID in acsOpenStream method.
// lParam will be set to the value of user defined variable provided in  
// acsEnumServerNames method call.
Boolean DisplayServerNames(char* serverName, unsigned long lParam)
{  
   Boolean bReturnValue = FALSE;
   if(strlen(serverName) > 0)
   {
	   // An application can choose to add serverName to a list,
    	   // so that such list of advertised names can be presented 
	   // for selecting serverID while opening the ACS Stream later.
 		      cout << endl << "Server Name: " << serverName;
        bReturnValue = TRUE; 
// Return TRUE so that the callback is called 
  // again with the name of the next advertised 
  // service found.
   }// End of if
   return bReturnValue; // If the callback method returns FALSE then,
 		//enumeration will terminate.
}

void EnumerateServerNames()
{
   // acsEnumServerNames()method is used to enumerate the names of all 
   // servers of a specified stream type.
   RetCode_t rc = acsEnumServerNames(
			ST_CSTA,	// Indicates that CSTA services are to be 
				// enumerated.  
			DisplayServerNames, // Call back function, defined above
			NULL, 	// user defined variable, value of this 
				// variable will be passed to the callback 
				// method as lParam parameter. Passed as NULL 
				// here
			);	
	  if ( nRetCode != ACSPOSITIVE_ACK )
   {
		// some error occurred while sending request
		cout<<" Error Code: "<<nRetCode;
		// handle error.
   }
}
		

For more information, refer to the description of acsEnumServerNames in the section ACS functions and confirmation events of document titled Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference Doc-ID: 02-300544, Release 4.2, May 2008, Issue 4 available on http://www.avaya.com/devconnect.

Yes, upgrading AE Services Server does not impact the functionality of existing applications. An application connects to the AE Services Server through the TSAPI Client library. AE Services Server is backward compatible; i.e. it supports previous versions of the TSAPI client library. Thus an existing application will continue to work without any modification.

For each device monitor request, TSAPI Service returns a unique identifier (MonitorCrossRefID) in its confirmation event to the application. Once the application receives the confirmation event, it starts receiving call state change notifications for any call activity on the monitored device.

The sample code below shows how to retrieve monitorCrossRefID from the confirmation event for the monitor request:

CSTAEvent_t cstaEvent; // Assuming the event has been retrieved using one 
			   // of the two methods i.e. cstaGetEventPoll() or 
			   // cstaGetEventBlock() and the event data is present in 
			   // cstaEvent.

long lOriginalMonitorCrossRefID; // To store the monitorCrossRefID from the 
				      // confirmation event of the monitor request.
// Check for the event type
if( cstaEvent.eventHeader.eventType == CSTA_MONITOR_CONF )
{
     // confirmation event for the monitor request, extract monitorCrossRefID.
     lOriginalMonitorCrossRefID = 						
				cstaEvent.event.cstaConfirmation.u.
							monitorStart.monitorCrossRefID;
     cout<<"MonitorCrossRefID :"<< lOriginalMonitorCrossRefID <<endl;
}
		

Each call state change notification contains a unique identifier which is same as that received in the confirmation event for the monitor request for a particular device. The sample code below shows how to retrieve the monitorCrossRefID from the call state change notification:
CSTAEvent_t cstaEvent; // Assuming the call state change unsolicited event has 
			   // been retrieved by using one of the two methods i.e. 
			   // cstaGetEventPoll() or cstaGetEventBlock() and the 
			   // event data is present in cstaEvent.

long lRetrievedMonitorCrossRefID; // To store the monitorCrossRefID from the 
					// call state change notification received.
	lRetrievedMonitorCrossRefID = 						
				cstaEvent.event. cstaUnsolicited.monitorCrossRefId;
	cout<<"MonitorCrossRefID :"<< lRetrievedMonitorCrossRefID <<endl;
}
		

Now, by comparing the lRetrievedMonitorCrossRefID (received in the call state change notification) with the lOriginalMonitorCrossRefID (received from the confirmation event of the monitor request), the application can associate the call state change notification with the corresponding monitor device request.

The valueOutOfRange error occurs when an invalid value is specified for any parameter in a service request. When the TSAPI Service detects an invalid value in a service request, it returns the valueOutofRange error in a service response to the TSAPI application.

For example, in reference to the cstaSetAgentState() request, if the private data parameter workMode is set as WM_AUX_WORK, and when the agentMode is specified as AM_READY, then on detecting this invalid value (AM_READY agent mode is invalid for the WM_AUX_WORK work mode), the TSAPI Service returns the valueOutOfRange error to the TSAPI application

For more information about this error and to find the methods that can return this error, the developer can look for VALUE_OUT_OF_RANGE keyword in the document titled Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, Doc-ID - 02-300544, Release 4.2, May 2008, Issue 4 available on http://www.avaya.com/devconnect.

When an application wants to receive call state change notifications for any call on a particular device, the TSAPI application needs to add a monitor on that device.

For information about the types of events that can be received by the application after adding a monitor on a device, refer to chapter 11 of the document titled Avaya MultiVantage Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, Doc-ID - 02-300544, Release 4.2, May 2008, Issue 4 available on http://www.avaya.com/devconnect.

While all events related to a call on a device are made available to the application, at times, the application may not be interested in receiving all the events. The Filter service is provided to reduce the number and types of event reports generated; this helps in reducing message traffic over the network.

For more information about the supported monitor services and Filter service, refer to Chapter 10 of the document titled Avaya MultiVantage Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, Doc-ID - 02-300544, Release 4.2, May 2008, Issue 4 available on http://www.avaya.com/devconnect.

The application can receive event notifications for call state changes on a device by adding a monitor to the device using the cstaMonitorDevice() method. After processing the cstaMonitorDevice() service request, the TSAPI Service sends a confirmation event (CSTA_MONITOR_CONF) to the application. Once the confirmation event (CSTA_MONITOR_CONF) is received by the application, the application starts receiving call state change notifications for all the call activity at the monitored device.

The sample code snippet below shows how to add a monitor on a device.

/* This code snippet shows how to add a monitor on the device with some
 * specific filter settings. The user can choose the filter settings as per 
 * the application requirements.
 * For information about types of events that can be used for the settings
 * filter, refer to chapter 10 of the document titled TSAPI for Avaya 
 * Communication Manager Programmer's Reference, Doc-ID - 02-300544, Release
 * 4.2, May 2008, Issue 4.
 */

// handle returned by acsOpenStream
ACSHandle_t g_ulAcsHandle;	

// Set the DeviceID of the device to be monitored.
DeviceID_t szDeviceID = "40010"; 

// specifying a value for a type of filter ensures that events reports for 
// the specified filter will be blocked.
// Note: Call cleared events are not sent to the application when the monitor 
//       is added using cstaMonitorDevice method. If the application needs to 
//       receive call cleared events, then it needs to add monitor on call 
//       using cstaMonitorCall() method. 

// Store the Monitor Filter setting
CSTAMonitorFilter_t filter;		 

// A simple TSAPI application that does not require diverted and 
// held events can set a filter for these events as shown. 
filter.call = cfDiverted | cfHeld;

// The Agent Filter, Feature Filter, and Maintenance Filter are not supported 
// in Avaya's CSTA implementation. If one of these is present, it will be 
// ignored.
filter.agent = 0; 
filter.feature = 0;	
filter.maintenance = 0;

// By setting no private filter, all private Events will be received
filter.privateFilter = 0;

// Storage for the Return code from the method
RetCode_t nRetCode = 0;

nRetCode = cstaMonitorDevice (g_ulAcsHandle, // ACS Stream handle
			  		             0,    	     // library generated invokeID
	  			      &szDeviceID, // ID of device to be monitored
				      &filter,    // Filter setting that will apply
 						     // on the monitor. Set to NULL 
						     // to receive all events 
  			              NULL       // private Data set to NULL
				    );

// Check for errors
if (nRetCode < 0)
{
	// some error occurred while sending the request
	cout<< "Failed to monitor Device" <<endl;

	switch( nRetCode )
	{
		case ACSERR_BADHDL:
	  	{	
		    cout<<"g_ulAcsHandle being used is an invalid handle" 
			  <<endl;
		    // handle error
	      }

		break;
	  	case ACSERR_BADPARAMETER:
	  	{
		    cout<<"One or more of the parameters are Invalid" 
			  <<endl;
		    // handle error
	  	}
		break;
		default:
		{
			cout<<"Unexpected/Unknown Error response ";
			cout<<"Return Code: "<<nRetCode<<endl;
		}
		break;
	}//End of Switch
}// End of If

Note 1: The confirmation event CSTA_MONITOR_CONF contains a reference key (monitorCrossRefID) which is a unique value within an ACS session for the duration that the monitor is active and is used by the application to detect event reports associated with the monitor request. This reference key is used when the application needs to remove the monitor. The application can remove the monitor on a station by using cstaMonitorStop() method .

Note 2: In case where multiple devices are being monitored, the monitorCrossRefID is used to distinguish between the events received for each established monitor request. Applications can receive events such as Delivered, Established, etc. for a monitored device, each having a monitorCrossRefID attached with the event. These events can be matched to the monitored device using the monitorCrossRefID.

After the TSAPI client is installed, the installer (or user) can use the TSAPI Test application provided along with the client to verify connectivity from the client system to AE Services Server and ultimately Communication Manager. The Microsoft Windows version of the TSAPI Test application is generally found at "C:\Program Files\Avaya\AE Services\TSAPI Client\ Program\ TSTEST32.exe" location depending upon your installation directory.

For more information about how to use and configure TSAPI Test application, refer to the section "Procedure to verify the TSAPI Windows client installation" in chapter 2 of the document titled "Avaya MultiVantage® Application Enablement Services TSAPI, JTAPI, and CVLAN Client and SDK Installation Guide, Doc-ID- 02-300543, Release 4.2, May 2008 Issue 5", available at location http://www.avaya.com/devconnect.

TSAPI Test is a basic application for making a call. A successful call ensures that the TSAPI client is correctly installed and working. If the TSAPI Test application fails to make the call, an error message is provided to aid in troubleshooting the cause of the failure. Refer to the FAQ document titled "Why is the TSAPI Test Application installed with the TSAPI client failing with an error?" available at location http://www.avaya.com/devconnect -> FAQs -> AE Services TSAPI FAQ, to resolve the error.

The cstaClearCall() method is used for clearing an entire call, whereas the cstaClearConnection() method is used for clearing a connection from a call. A Call is a reference to a set of Connections through which a set of Terminals are communicating. A Connection is a reference to the binding between a Terminal (telephone) and a Call.

The cstaClearCall() method disconnects all the connections (participants) from a specified call and terminates the call itself, rendering all the connections associated with the call invalid. When there is a need to terminate all the connections from a specified call, this method can be used by a TSAPI application.

As shown in the figure below, when three devices are in a conference and the cstaClearCall() method is called by the application for any device, all the connections are disconnected.

Note: The cstaClearCall() method requires a valid CallID to terminate the call. The second parameter (DeviceID) is ignored by this method.

The cstaClearConnection() method disconnects a specified connection (participant) from the designated call and the connection state changes to Null. The connection identifier is no longer associated with the call.

When there is a need to disconnect only a particular connection from a call, the cstaClearConnection() method can be used in a TSAPI application.

As shown in the figure below, when three devices are in a conference call and cstaClearConnection() is called by the application for a particular device, then the associated connection between that device and call will be disconnected. The remaining two devices would still remain connected.

Notes:

  • If a connection is in the alerting state, it cannot be cleared using the cstaClearConnection() method. In this case, the connection can be cleared either when its state changes to Connected, or by clearing the call (using the cstaClearCall() method).
  • cstaClearConnection method needs both a valid CallID and DeviceID to clear a connection.
  • In case where the call has only two connections, the result of invoking either of these methods will be the same, i.e., both connections will be cleared.

No, the call to the acsOpenStream()API will not fail due to the network connection loss between the AE Services Server and Communication Manager. In fact, the network connection between AE Services Server and Communication Manager doesn't affect the state of the ACS stream at all. The application, however, will not be able to access services that require communication with Communication Manager (for example, the Make Call/Monitor Device services).

In the case when there is no connectivity between the AE Services Server and Communication Manager, if the application invokes any of the APIs that require communication with Communication Manager, the TSAPI Service sends an event of type UniversalFailureConfEvent with GENERIC_OPERATION_REJECTION as the error cause. In such case, the application needs to check the connection status, and when the connection is restored, the application can invoke the API again; there is no need for the application to close and reopen the ACS stream.

The application can check the connection status by using cstaSysStatReq() method. The cstaSysStatReq() method provides a snapshot of the connection status at the time the method is called. Please note that this method does not register for system state change notifications, so the application has to call this method each time the application wishes to know the connection status.

The application can use cstaSysStatStart() method to register for events. The cstaSysStatStart() method registers for system state change notifications, allowing the application to receive a system state change notification whenever the AE Services Server's network connection to Communication Manager is lost/re-covered. The parameter systemStatus in the system state change notification indicates the connection status. A value of 'Disabled' for systemStatus indicates 'no connectivity' whereas a value of 'Enabled' indicates that the network connection is 'stable'. The confirmation event of cstaSysStatStart() method provides the application a snapshot of the connection status at the time the method is called. The application can call cstaSysStatStop() method to cancel a previously registered request for system status event reporting.

For more information on the cstaSysStatReq(), cstaSysStatStart(),and cstaSysStatStop() methods, please refer to Chapter 13 titled "System Status Service Group" of the document titled "Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, Doc-ID: 02-300544, Release 4.2, May 2008, Issue 4", available on http://www.avaya.com/devconnect.

The Avaya implementation of TSAPI provides two different ways through which a TSAPI application can retrieve events from the TSAPI Client library:

  1. One way is to use the acsGetEventBlock() method which runs in the blocking mode, i.e., the application's calling thread will be blocked until there is an event available in the Client library's event queue. This method will return with an event that is copied in the application's defined event buffer.
  2. The other way is by using the acsGetEventPoll() method which runs in a non-blocking mode, i.e., if there is no event available in the Client library's event queue, the acsGetEventPoll() method will return immediately with an error code indicating that there is no event available in the Client library's event queue at the moment. When there is more than one event available, the oldest event available on the specified active ACS stream is retrieved and copied in the application's defined event buffer.
For more information on the acsGetEventBlock()/acsGetEventPoll() methods, please refer to the section titled "ACS functions and confirmation events" in the document titled "Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, Doc-ID: 02-300544, Release 4.2, May 2008, Issue 4", available on http://www.avaya.com/devconnect.

Event Service Routine (ESR) is a mechanism that allows a TSAPI application to register with the TSAPI Client library to receive a notification when an event is added in the Client library's event queue. The application can make use of the acsSetESR() method to implement the ESR mechanism. This method allows the application to register a callback method that will be invoked whenever an event is added in the Client library's event queue.

Please note the following important points about the ESR mechanism:

  1. The acsSetESR() method should be invoked after the acsOpenStream() method has returned successfully.
  2. Whenever the callback method is called, the application must retrieve the events from the Client library's event queue to prevent the queue from overflowing. It is recommended that the application should be designed to have a separate thread (one different from the callback method thread) for retrieving and processing the events. In case, the application chooses to receive a notification for each event whenever an event is added in the Client library's event queue, the need to retrieve and process the events in a separate thread becomes more evident. Retrieving and processing the events in a separate thread ensures that the callback method's thread is not blocked and remains free to receive further notifications from the Client library.
  3. The acsSetESR() method allows the application to pass a user defined value to the callback method. For example, the application may pass an object pointer as demonstrated in the code snippet below.
The notifyAll parameter of the acsSetESR() method allows the application to specify the notification type. A value of TRUE for the notifyAll parameter will allow the application to receive a notification for each event and a value of FALSE will allow the application to receive a notification when the Client library's event queue becomes non-empty (i.e., the queue count changes from zero (0) to one (1)). Using FALSE for the notifyAll parameter will reduce the overhead of notifications.

For more information on the acsSetESR() method's signature and for a description of all the method's parameters, please refer to the section titled "ACS functions and confirmation events" in the document titled "Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, DocID: 02-300544, Release 4.2 May 2008 Issue 4", available on http://www.avaya.com/devconnect.

The sample code snippet shown below demonstrates how the ESR mechanism works.

// Callback method to receive event notifications.
// @esrParam:esrparam will be set to the value of user defined variable 
// provided in acsSetESR() method call. 
void __stdcall ESRCallback(unsigned long esrParam)
{
		cout<<" New event added in the client queue"<<endl<<endl;
		
		// In this example, TSAPIInterface class object is passed in the
		// acsSetESR() method call, converting esrParam back to TSAPIInterface 
		// type. 
		TSAPIInterface* pTSAPIObject = (TSAPIInterface*) esrParam;
   
		pTSAPIObject->retrieveEvents();	// retrieveEvents() is a method of 
							// TSAPIInterface class that contains the 
							// code to retrive events from the Client 
							// library event queue. 
} // End of method

// Assume TSAPIInterface is a user defined class that is responsible for 
// opening an ACS Session.

// setESR() method is a member of TSAPIInterface class.
void TSAPIInterface::setESR()
{
		ACSHandle_t* pAcsHandle; // Handle returned by the acsOpenStream(), 
		// probably avaiable as a member variable.
		// Register a callback method with client library to receive a notification
		// when an event is added in the Client library's event queue.
		// Upon success, the Client library will call ESRCallback method whenever
		// the client library's event queue becomes non-empty.
   	
		RetCode_t nRetCode = acsSetESR(*pAcsHandle, // handle returned by
								 // acsOpenStream method.
							ESRCallback,// callback method defined by 
									// the application.
							(unsigned long)this, // passing the object 
									// of the TSAPIInterface class. 
									// as user defined parameter
							FALSE 	// Setting FALSE to receive 
									// callback only when the client 
									// library's event queue becomes non-
									// empty.
							);
   	// Verification for the positive response
		if(nRetCode != ACSPOSITIVE_ACK)
		{
			cout << "ERROR IN SET ESR ";
			if(nRetCode == ACSERR_BADHDL)
			{
				cout <<" pAcsHandle being used is not a valid handle"<<endl;
			}// End of if
			else
			{
				cout << " acsSetESR() failed with unknown error. " <<	endl;
				cout << " Error code: " << nRetCode;
			}// End of else
		}// End of outer if
}// End of method

// retrieveEvents() method is a member of TSAPIInterface class.
void TSAPIInterface:: retrieveEvents()
{
		// code to retrieve events from client queue goes here?
}
		

An application can determine the number of calls queued in for a specific ACD Split (or Hunt Group) by using the attQueryACDSplit() and cstaEscapeService() methods.

The attQueryACDSplit() method is used to prepare private data information that is passed through the cstaEscapeService() method to query ACD Split. The attQueryACDSplit() method takes two parameters as inputs:

  • The first parameter is privateData (i.e., the ATT private data buffer), and is passed as an output parameter.
  • The second parameter is device, which is of type DeviceID_t and contains the ACD Split number to be queried.
The sample code snippet below illustrates how to invoke the attQueryACDSplit() and cstaEscapeService() methods:
// <summary>
// Query ACD Split via cstaEscapeService().
// </summary>
// <param name="aAcsHandle"> An opened ACS Stream Handle.</param>

void QueryACDSplit(ACSHandle_t aAcsHandle)
{
	InvokeID_t invokeID = 1; // Application generated Invoke ID
	DeviceID_t huntgroupDeviceID = "49000"; // Device associated with ACD split
	RetCode_t retCode; // Return code for service requests
	ATTPrivateData_t privateData; // ATT private data buffer
	
	// encode private data using attQueryAcdSplit
	retCode = attQueryAcdSplit(&privateData, &huntgroupDeviceID);
	
	if (retCode == 0 ) 
	{
		retCode = cstaEscapeService(aAcsHandle, invokeID,
			(PrivateData_t*)&privateData);

		if (retCode != ACSPOSITIVE_ACK) 
		{
			// cstaEscapeService failed, write error handling code here.
		}
	}
	else
	{
		// attQueryAcdSplit failed, write error handling code here.
	}
}
		

For the cstaEscapeService() method, that is called with the private data encoded using attQueryACDSplit, a confirmation event "CSTAEscapeServiceConfEvent" (containing event type ATT_QUERY_ACD_SPLIT_CONF) is provided that provides the following information:
  1. availableAgents: Number of agents logged in to the specified ACD Split and available to receive a call.
  2. callsInQueue: Number of calls in queue for the specified ACD Split.
  3. agentsLoggedIn: Number of agents logged in to the specified ACD Split.
The sample code snippet below illustrates how to retrieve the information about number of available agents, calls in queue, and the number of logged-in agents at a specific ACD Split, from the CSTAEscapeServiceConfEvent event:
// <summary>
// Invoke this method to process CSTA Confirmation events. Call this method 
// after retrieving event (along with private data) using either 
// cstaGetEventPoll() or cstaGetEventBlock() when the 
// cstaEvent.eventHeader.eventClass is CSTACONFIRMATION.
// </summary>
// <param name="cstaEvent"> Pointer to CSTAEvent_t object that contains 
// event's information.</param>
// <param name="privateData"> Pointer to ATTPrivateData_t object that 
// contains private data information.</param>

void HandleCSTAConfirmationEvent(CSTAEvent_t* cstaEvent, ATTPrivateData_t* privateData)
{
// Check for event type.
switch(cstaEvent->eventHeader.eventType)
{
case CSTA_ESCAPE_SVC_CONF:
	{
		// Assuming the private data was negotiated during opening of ACS
		// Stream.

		// check the privateData length
		if ( privateData->length > 0)
		{
			// Event buffer that will contain the decoded 
			// private data information.
			ATTEvent_t attEvent;

			// Decode the private Data received.
			// Check to ensure that the private data 
			// is successfully decoded.
			if ( attPrivateData(privateData,&attEvent) == ACSPOSITIVE_ACK)
			{
				//checking the event type
				if ( attEvent.eventType == ATT_QUERY_ACD_SPLIT_CONF )
				{
					cout<<"Number of calls queued at the ACD Split :";
					cout<< attEvent.u.queryAcdSplit.callsInQueue;
					cout<<"Number of Agents logged on to the ACD Split :";
					cout<< attEvent.u.queryAcdSplit.agentsLoggedIn;
					cout<<"Number of Agents avaiable to receive a call :";
					cout<< attEvent.u.queryAcdSplit.availableAgents;
				}
			}
			else
			{
				// Error while decoding private data
				// handle error.
			}
		}
		else
		{
			// Event does not contain private data
		}
		break;
	}// End of case
	// Application can add other cases here for processing other events as 
	// needed.
}// End of switch
}// End of method

		

There is no direct method call to get a list of Agents logged into a specific ACD Split (or Hunt Group). There is, however, an indirect way for obtaining a list of Agents logged into a specific ACD Split. A TSAPI application can follow the steps mentioned below to obtain a list of Agents logged into a specific ACD Split:

  1. Obtain a list of all devices associated with the ACD Split: The Query Agent login service provides the deviceID (extension) associated with each ACD agent logged into a specific ACD Split. The Query Agent login service is a escape service that can be invoked using the cstaEscapeService() method, and involves passing private data encoded using the attQueryAgentLogin()method. In response to the cstaEscapeService() method request, TSAPI Service sends a CSTA_ESCAPE_SRV_CONF confirmation event with the private data event type set to ATT_QUERY_AGENT_LOGIN_CONF in the private data. After sending the confirmation event, the TSAPI Service sends a sequence of CSTAPrivateEvent (CSTA_PRIVATE) events. The private data received in CSTA_ESCAPE_SRV_CONF confirmation event also contains a private cross reference ID that the application can use to associate subsequent CSTAPrivateEvent events, with the original request, by matching with the private event cross reference ID contained in the private data received as part of CSTAPrivateEvent. The private data received as part of CSTAPrivateEvent also contains the count of total devices and a list of deviceIDs (extensions). The list can contain up to 10 deviceIDs of ACD agents logged into the ACD Split. When the count field in the private data of CSTAPrivateEvent is set to zero, it indicates that no more events will be sent to the application in response to the original escape service request. Upon receiving the CSTAPrivateEvent event, the application can store all the deviceIDs in a data structure (for e.g. array, list, etc.), so that the application can further query each device (see Step 2 below) using the deviceID to get the AgentID associated with the device.
  2. Obtain AgentID associated with each device: In this step, the application should query each device using a deviceID stored in the data structure (in Step 1 above) to get the AgentID associated with the device. The application can use the cstaQueryDeviceInfo() method for this purpose. The corresponding CSTAQueryDeviceInfoConfEvent(CSTA_QUERY_DEVICE_INFO_CONF) event provides the AgentID associated with the device.
The implementation procedure to obtain a list of Agents logged into a specific ACD Split is shown below:

  1. Call the attQueryAgentLogin() method to encode the private data and call the cstaEscapeService() method (with the encoded private data) to send the request to obtain the deviceIDs associated with the Agent(s) logged into a specific ACD Split.
    // <summary>
    // This method invokes the attQueryAgentLogin()
    // and cstaEscapeService() method to obtain the extension associated
    // with each ACD agent logged into a specific ACD Split.
    // </summary>
    // <param value="a_pAcsHandle">Handle returned by acsOpenStream()</param>
    // <param value="a_szHuntgroupID">contains the ACD Split number</param>
    
    void QueryAgentLogin(ACSHandle_t a_AcsHandle, char* a_szHuntgroupID)
    {
    
    ATTPrivateData_t privateData; // Private data buffer
    // Encode private data using attQueryAgentLogin() method
    RetCode_t nRetCode = attQueryAgentLogin(
    		(ATTPrivateData_t*)&privateData, // Private data buffer
    		(DeviceID_t*)a_szHuntgroupID // ACD Split number
    		);
    
    // check to ensure that private data is correctly encoded.
    if(nRetCode == 0)
    {
    	// Call cstaEscapeService() method using the private data encoded
    	// above.
    	nRetCode = cstaEscapeService(a_AcsHandle, // Handle to opened stream
    		0, // Library defined InvokeID used
    		(PrivateData_t*)&privateData // encoded Private data 
    		);
    
    	// Checking for the negative response
    	if ( nRetCode < 0)
    	{
    	cout<<" cstaEscapeService() failed with error. " << endl;
    	cout<<"Error Code:"<<nRetCode;
    	}
    	else
    	{
    	// request is successful, check CSTA_ESCAPE_SRV_CONF event.
    	}
    }
    }// End of method
    				
  2. Process the CSTA_ESCAPE_SRV_CONF event to retrieve the private event cross reference ID.
    // <summary>
    // Invoke HandleCSTAConfirmationEvent() method to process CSTA Confirmation 
    // events. Call this method after retrieving event, when the 
    // cstaEvent.eventHeader.eventClass is CSTACONFIRMATION.
    // </summary>
    // <param name="a_pCstaEvent"> Pointer to CSTAEvent_t object </param>
    // <param name="a_pPrivateData"> Pointer to ATTPrivateData_t object</param>
    
    void HandleCSTAConfirmationEvent(CSTAEvent_t* a_pCstaEvent, ATTPrivateData_t* a_pPrivateData)
    {
    // To hold the private event cross reference ID
    ATTPrivEventCrossRefID_t	privateEventRefID;
    // Check for event type.
    switch(a_pCstaEvent->eventHeader.eventType)
    {
    case CSTA_ESCAPE_SVC_CONF:
    	{
    	// Assuming the private data was negotiated during opening of ACS
    	// Stream.
    
    	// check the privateData length
    	if ( a_pPrivateData->length > 0)
    	{
    	// Event buffer that will contain the decoded 
    	// private data information.
    	ATTEvent_t attEvent;
    
    	// Decode the private data received.
    	// Check to ensure that the private data 
    	// is successfully decoded.
    	if ( attPrivateData(a_pPrivateData,&attEvent) == ACSPOSITIVE_ACK)
    	{
    	//checking the event type
    	if ( attEvent.eventType == ATT_QUERY_AGENT_LOGIN_CONF )
    	{
    	privateEventRefID = attEvent.u.queryAgentLogin.
    			privEventCrossRefID;
    	cout<<" The Private Event Cross Reference ID :" 
    			<< privateEventRefID;
    	// Use this private event cross reference ID to match the 
    	// subsequent CSTA_PRIVATE events.
    	}
    	}
    	else
    	{
    	// Error while decoding private data
    	// handle error.
    	}
    	}// End of if
    	else
    	{
    	// Event does not contain private data
    	}
    	break;
    	}// End of case
    	// Application can add other cases here for processing other events as 
    	// needed.
    }// End of switch
    }// End of method.
    				
  3. Process the CSTA_PRIVATE event to get the list of devices.
    // <summary>
    // Invoke HandleCSTAEventReport() method to process CSTA_PRIVATE events. 
    // Call this method when cstaEvent.eventHeader.eventClass is 
    // CSTAEVENTREPORT.
    // </summary>
    // <param name="a_pCstaEvent"> Pointer to CSTAEvent_t object.</param>
    // <param name="a_pPrivateData"> Pointer to ATTPrivateData_t object. 
    // </param>
    // <param name="a_PrivateEventRefID">ATTPrivEventCrossRefID_t object that 
    // contains private event reference ID as retrieved in CSTA_ESCAPE_SVC_CONF
    // event.</param>
    // <param name="a_DeviceList">Pointer that points to list of 
    // deviceIDs</param>
    // <return>Return 1 on success and 0 on failure.</return>
    static int nDeviceListIndex  = 0; // Index for storing DeviceIDs in 
    				 // DeviceList
    int  HandleCSTAEventReport(CSTAEvent_t* a_pCstaEvent, ATTPrivateData_t* a_pPrivateData, 
    			 ATTPrivEventCrossRefID_t a_PrivateEventRefID,DeviceID_t* a_DeviceList)
    {
    int nDeviceCount = 0; // To count total number of devices
    
    
    // Check for event type
    switch(a_pCstaEvent->eventHeader.eventType)
    {
    case CSTA_PRIVATE:
    	{
    	// check the privateData length
    	if (a_pPrivateData->length > 0)
    	{
    	// Event buffer that will contain the decoded 
    	// private data information.
    	ATTEvent_t attEvent;
    
    	// Decode the private Data received.
    	// Check to ensure that the private data 
    	// is successfully decoded.
    	if ( attPrivateData(a_pPrivateData,&attEvent) == ACSPOSITIVE_ACK)
    	{
    	//checking the event type
    	if ( attEvent.eventType == ATT_QUERY_AGENT_LOGIN_RESP )
    	{
    	if(a_PrivateEventRefID == attEvent.u.queryAgentLoginResp.
    					 privEventCrossRefID)
    	{
    	  nDeviceCount = attEvent.u.queryAgentLoginResp.list.
    					     count;
    	if(nDeviceCount == 0)
    	{
    	// No more devices present. 
    	// Post a message to execute the logic to get the 
    	// device information using cstaQueryDeviceInfo for 
    	// each of the devices added to the list a_DeviceList.
    	}
    	else
    	{
    	cout<<" Total Devices :" << nDeviceCount;
    	for(int nDeviceIndex = 0; nDeviceIndex < nDeviceCount;
    					nDeviceIndex++)
    	{
    	// Store all the devices
    	strcpy(a_DeviceList[nDeviceListIndex++],
    	(DeviceID_t)attEvent.u.queryAgentLoginResp
    	.list.device[nDeviceIndex]); // Make sure 
    	// that the array a_DeviceList is of sufficient size to store the maximum 
    	// number of devices returned, indicated by the possible number of agents 
    	// logged into ACD at a give time. 
    	}
    	}// End of else
    	}// End of if
    	}// End of if
    	}// End of if
    	else
    	{
    	// Error while decoding private data
    	// handle error.
    	return 0;
    	}
    	}// End of if
    	else
    	{
    	// Event does not contain private data
    	return 0;
    	}
    	break;
    	}// End of case
    }// End of inner switch
    return 1;
    }// End of method
    
  4. Call the cstaQueryDeviceInfo() method iteratively with each deviceID retrieved in Step c above to get the AgentID associated with each device.
    // <summary>
    // Query device info via cstaQueryDeviceInfo().
    // </summary>
    // <param name="a_AcsHandle"> Handle to opened ACS Stream.</param>
    // <param name="a_szDevice"> contains device ID.</param>
    void QueryDeviceInfo(ACSHandle_t a_AcsHandle, DeviceID_t a_szDevice)
    {
    
    RetCode_t retCode; // To store the method return code
    
    	// Call cstaQueryDeviceInfo method to obtain the AgentID associated 
    	//	with a device. 
    
    retCode = cstaQueryDeviceInfo(a_AcsHandle, // Handle to opened ACS Stream
    0, // Library generated InvokeID used
    (DeviceID_t*) a_szDevice, // DeviceID of device to be
    			// queried
    NULL // No private data sent with this request
    );
    
    	if( retCode < 0)
    	{
    	// Error while sending Query Device Info request
    	cout<<" Error Code: "<<retCode;
    	// handle error
    	} // End of If
    	else
    	{
    	// request is successful, check CSTA_QUERY_DEVICE_INFO_CONF event.
    	}	
    }// End of method.
    
  5. Process the CSTA_QUERY_DEVICE_INFO_CONF confirmation event to retrieve the associatedDevice parameter that represents the AgentID associated with the device.
    // <summary>
    // Invoke HandleCSTAConfirmationEvent() method to process confirmation 
    // events. Call this method when the cstaEvent.eventHeader.eventClass is 
    // CSTACONFIRMATION.
    // </summary>
    // <param name="a_pCstaEvent "> Pointer to CSTAEvent_t object.</param>
    // <param name="a_pPrivateData"> Pointer to ATTPrivateData_t object.</param> 
    
    void HandleCSTAConfirmationEvent(CSTAEvent_t* a_pCstaEvent, ATTPrivateData_t* a_pPrivateData)
    {
    	// Check for event type.
    	switch(a_pCstaEvent->eventHeader.eventType)
    	{
    	case CSTA_QUERY_DEVICE_INFO_CONF:
    	{
    	// Check for private data length
    	if (a_pPrivateData->length > 0)
    	{
    	// Event buffer that will contain the decoded 
    	// private data information.
    	ATTEvent_t attEvent;
    
    	// Decode the private Data received.
    	// Check to ensure that the private data 
    	// is successfully decoded.
    	if (attPrivateData(a_pPrivateData,&attEvent)==ACSPOSITIVE_ACK)
    	{
    	//checking the event type
    	if ( attEvent.eventType == ATT_QUERY_DEVICE_INFO_CONF )
    	{
    	// Check the associated class
    	if ( attEvent.u.queryDeviceInfo.associatedClass ==
    		ecLogicalAgent)
    	{
    	char* AgentID = attEvent.u.queryDeviceInfo.
    			associatedDevice;
    	cout<<"The AgentID: :"<<AgentID;
    	// a_pAgentList and a_AgentIndex are defined by the 	
    	// application. a_pAgentList will store all 
    	// AgentIDs retrieved in this method. 
    	// a_AgentIndex is an integer used as array index. 
    
    	strcpy(a_pAgentList[a_AgentIndex++],(DeviceID_t)
    	attEvent.u.queryDeviceInfo.associatedDevice);
    	}// End of if
    	else
    	{
    	// No Agent ID is Present.
    	}// End of else
    	} // End of if
    	}// End of if
    	else
    	{
    	// error while decoding private data
    	}
    	}// End of if
    	else
    	{
    	// No private data received.
    	}
    	break;
    	}// End of case
    	// Application can add other cases here for processing other events
    	// as needed.
    }// End of switch
    }// End of method
    
Once all the devices have been queried and their respective confirmation events received, the application can make use of the a_pAgentList that contains Agent IDs of all the Agents logged into specified ACD Split.

For more information on the attQueryAgentLogin(), cstaEscapeService() and cstaQueryDeviceInfo() methods, refer to the document titled "Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference 02-300544 Release 4.2 May 2008 Issue 4", available at http://www.avaya.com/devconnect.

A TSAPI application can use the acsQueryAuthInfo() method to determine the CTI login and password requirements dynamically before opening an ACS stream with a particular advertised service or Tlink. The acsQueryAuthInfo() method places the result of a query in a user-provided structure before returning, and there is no confirmation event for this method.

An application can use acsQueryAuthInfo() method to determine the authentication requirements for an advertised service dynamically and accordingly, on the basis of the response returned by the acsQueryAuthInfo() method, prompt the user to enter only the information required for authentication. This way the application can avoid prompting for both loginID and password, when the service is configured to use default user. Similarly, based on the response of the acsQueryAuthInfo() method, the application can take corrective action when the application can open a stream by only using the loginID provided by the service, or when the service requires the user to authenticate with an external authentication service before opening an stream.

For more information on the acsQueryAuthInfo() method, please refer to the section titled "ACS functions and confirmation events" in the document titled "Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, DocID: 02-300544, Release 4.2 May 2008 Issue 4", available on http://www.avaya.com/devconnect.

The sample code snippet given below demonstrates invoking the acsQueryAuthInfo() method:

// Call this method to get the CTI user loginID and password
// that needs to be supplied in the acsOpenStream() method.
// p_szServiceName: This is an input parameter that will contain the advertised
// service name or Tlink value.
// p_szLoginID: This is an output parameter that will be filled with 
// appropriate CTI user login ID.
// p_szPassword: This is an output parameter that will be filled with 
// appropriate CTI user password.

void GetLoginPassword(ServerID_t* p_szServiceName, 
LoginID_t* p_szLoginID,	Passwd_t* p_szPassword)
{
// To hold authentication information
ACSAuthInfo_t authInfo;

// Use acsQueryAuthInfo( ) to determine the login and password requirements
// when opening an ACS stream to a particular advertised service.
RetCode_t nRetCode = acsQueryAuthInfo(
	(ServerID_t*) p_szServiceName, // Tlink name
	&authInfo // To store authentication information
	);
if(nRetCode != ACSPOSITIVE_ACK)
{
	cout << " Error: acsQueryAuthInfo method failed.";
}
else
{
	switch(authInfo.authType)
	{
	case requiresExternalAuth:
		{
			// Authentication with an external authentication service
			// is required.
			break;
	}
	case authLoginIdOnly:
		{
			// loginID returned in authInfo.authLoginID.
			p_szLoginID = &authInfo.authLoginID;
			// Password will be ingnored, initializing with empty string.
			strcpy((char*)p_szPassword, "");
			break;
		}
	case authLoginIdIsDefault:
		{
			// The application can use authInfo.authLoginID value
			// for loginID and passwd will be ingnored.
			// Alternatively, the application cas also use a different user 
			// than authInfo.authLoginID, in this case 
			// the application must supply both loginID and passwd.
		}
	case needLoginIdAndPasswd:
		{
			// The application should request the user to enter both login ID 
			// and password in this case.
			cout << endl << " Please enter CTI User login ID: ";
			// Store login ID in output parameter
			cin >> *p_szLoginID;
			cout << endl << " Please enter CTI User password: ";
			// Store password in output parameter
			cin >> *p_szPassword;
			break;
		}
	case anyLoginId:
		{
			// Any login ID can be supplied
			strcpy((char*)p_szLoginID, "avaya");
			// passwd will be ignored
			strcpy((char*)p_szPassword, "");
			break;
		}
	}
}
// On return of this method, the calling method can use the p_szLoginID and 
// p_szPassword value to pass in acsOpenStream() method to open a 
// stream with Tlink specified by p_szServiceName.
// For the case of requiresExternalAuth, the application needs to make sure 
// that the user is successfully authenticated with the required external 
// authentication service before opening a stream.
}

Avaya TSAPI client libraries are supported on specific Windows and Linux operating system platforms. Under Windows the following 32 bit operating systems are supported:

  • Windows 2000
  • Windows 2003
  • Windows XP
  • Windows Vista
Note that 64 bit Windows operating systems are not supported through AE Services release 4.2 timeframe.

Under Linux, Red Hat Enterprise Linux 3.1 or later are supported.

For more information on installation and supported operating system platforms, refer "Avaya MultiVantage® Application Enablement Services TSAPI, JTAPI, and CVLAN Client and SDK Installation Guide 02-300543," available on http://www.avaya.com/devconnect.

The cstaMonitorCall() method is specifically designed to support a single call monitor whereas the cstaMonitorDevice() method will allow an application to monitor all the calls that utilize the monitored device.

In the case of the cstaMonitorCall() method, event reports are provided after the monitor request is acknowledged and events that occurred prior to the monitor request are not reported. For example, consider a simple call scenario where extension 40010 calls 40011. The callID for this call is 198. cstaMonitorCall() is then used to monitor callID 198. The Service Initiated, Originated, and Delivered events that occur before call is monitored will not be provided. In similar scenario, if cstaMonitorDevice() is used to monitor extension 40010 and then the call is initiated, the Service Initiated, Originated, and Delivered events will be provided.

These two methods are also different in the Call Cleared event reporting. In case of cstaMonitorDevice() method, only the Connection Cleared event is provided; the Call Cleared event is never provided. In case of the cstaMonitorCall() method, both the Connection Cleared and Call Cleared events are provided.

A call that is being monitored using the cstaMonitorCall() method may have a new call identifier assigned to it after a conference or transfer. In these cases, event reports continue for that call with the new call identifier. However in case of the cstaMonitorDevice() method, no further events for a call are reported when that call is transferred from the monitored device i.e., the monitored device ceases to participate in the call.

In the case of cstaMonitorCall() method, only Call Filter/Call Event Reports and Private Filter are supported. Agent Event Reports and Feature Event Reports are not provided. In the case of cstaMonitorDevice() method, Call Event Reports for station devices as well as Agent Event Reports for ACD Split devices are supported. Maintenance Event Reports are not provided for both the methods i.e., cstaMonitorCall() and cstaMonitorDevice() method.

For more information on the cstaMonitorCall() and cstaMonitorDevice() methods, refer section "Chapter 10: Monitor Service Group" in the document "Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference 02-300544", available on http://www.avaya.com/devconnect.

The attQueryTimeOfDay() method can be used to obtain the current time of day information from Communication Manager. The information returned contains the year, month, day, hour, minute, and second.

The application can use obtained date and time information for any purpose; for example event logging. Having date and time information that is aligned across multiple servers is helpful in troubleshooting. It is also possible to use NTP (Network Time Protocol) to more closely align the time of day clocks across multiple systems for this purpose.

The attQueryTimeOfDay() method is used to prepare private data information that is passed through the cstaEscapeService() method to query Communication Manager. The attQueryTimeOfDay() method takes one parameter: privateData (i.e., the ATT private data buffer). The attQueryTimeOfDay() method populates the privateData structure and returns the resulting populated structure through the passed in parameter.

The sample code snippet below illustrates how to invoke the attQueryTimeOfDay () and cstaEscapeService() methods:

// <summary>
// Query Communication Manager for date and time information.
// </summary>
// <param name="a_pAcsHandle"> An opened ACS Stream Handle.</param>
void GetTimeOfTheDay(ACSHandle_t* a_pAcsHandle)
{
  // ATT service request private data buffer 
  ATTPrivateData_t privateData;

  // To store method return value
  RetCode_t retCode;

  // encode private data using attQueryTimeOfDay()
  retCode = attQueryTimeOfDay(&privateData);

  if (retCode == 0 ) 
  {
    InvokeID_t invokeID = 101; // Application generated Invoke ID
    
    // Send a query for Time of Day service
    retCode = cstaEscapeService(*a_pAcsHandle, invokeID,
			(PrivateData_t*)&privateData);

    if (retCode != ACSPOSITIVE_ACK) 
    {
      // cstaEscapeService failed, write error handling code here.
    }
  }
  else
  {
    // attQueryTimeOfDay failed, write error handling code here.
  }
}

For the cstaEscapeService() method, that is called with the private data encoded using attQueryTimeOfDay, a confirmation event "CSTAEscapeServiceConfEvent" (containing event type ATT_QUERY_TOD_CONF) is provided that provides year, month, day, hour, minute, and second as of when Communication Manager handled the request.

The sample code snippet below illustrates how to retrieve the date and time information, from the CSTAEscapeServiceConfEvent event:


// <summary>
// Invoke this method to process CSTA Confirmation events. 
//
// This method is intended to be called after the application has used either 
// cstaGetEventPoll() or cstaGetEventBlock() to retrieve an event and the 
// cstaEvent.eventHeader.eventClass is CSTACONFIRMATION.
//
// The calling entity must pass the retrieved event along with any received 
// private data to this method.
//
// </summary>
// <param name="cstaEvent"> Pointer to CSTAEvent_t object that contains 
// event's information.</param>
// <param name="privateData"> Pointer to ATTPrivateData_t object that 
// contains private data information.</param>

void HandleCSTAConfirmationEvent(CSTAEvent_t* cstaEvent, ATTPrivateData_t* privateData)
{
  // Check for event type.
  switch (cstaEvent->eventHeader.eventType)
  {
  case CSTA_ESCAPE_SVC_CONF:
    {
	// Assuming the private data was negotiated during opening of ACS
	// Stream.

	// check the privateData length
	if ( privateData->length > 0)
	{
	  // Event buffer that will contain the decoded 
	  // private data information.
	  ATTEvent_t attEvent;

	  // Decode the private Data received.
	  // Check to ensure that the private data 
	  // is successfully decoded.
	  if ( attPrivateData(privateData,&attEvent) == ACSPOSITIVE_ACK)
	  {
	    //checking the event type
    if ( attEvent.eventType == ATT_QUERY_TOD_CONF )
	    {
		cout<< "Year : " << attEvent.u.queryTod.year;
		cout<< "Month : " << attEvent.u.queryTod.month;
		cout<< "Day : " << attEvent.u.queryTod.day;
		cout<< "Hour : " << attEvent.u.queryTod.hour;
		cout<< "Minute : " << attEvent.u.queryTod.minute;
		cout<< "Second : " << attEvent.u.queryTod.second;
	    }
           // else handle other attEvent.eveytType s as needed.
	  }
	  else
	  {
	    // Error while decoding private data
	    // handle error.
	  }
       } 
       else
       {
	  // Event does not contain private data
       }
       break;
     }// End of case
     // Application can add other cases here for processing other events as 
     // needed.
  }// End of switch
}// End of method

No. TSAPI does not provide any method through which an application can determine number of active monitors on a particular station extension.

The TSAPI service sends separate events for each monitored device that are participating in a call. For example, if the application is monitoring device 40010 and 40011, and a call is made from device 40010 to 40011, the application will receive two Delivered events, one for each monitored device.

Each of these events may provide different information specific to device for which the event is being reported. For example, in the above call scenario the first delivered event (for 40011) will contain 'Alerting' in the Local Connection Information whereas the second delivered event (for 40010) will contain 'Connected'. Each event is tagged with a monitor ID (monitorCrossRefID) which allows the application to track which device monitor the event is associated with.

For more information on the monitorCrossRefID, perform a search for "monitorCrossRefID" in the document "Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference 02-300544", available on http://www.avaya.com/devconnect. Additionally, you can refer tutorial titled "Application Initialization using Avaya AE Services TSAPI SDK for Windows", available on http://www.avaya.com/devconnect.

As stated in the TSAPI for Avaya Communication Manager Programmer's Reference, TSAPI SetDoNotDisturb turns on the Send All Calls (SAC) feature for a user station. This feature was designed to give a short notification ring on the called number and then the call is redirected according to the coverage path provisioned for the station. For details on provisioning call coverage see the Administering Avaya Aura Communication Manager documentation available on the Avaya support portal at www.avaya.com/support.

The Do Not Disturb feature on Communication Manager is a hospitality feature used mostly in hotels. By default when this feature is enabled either through a button or FAC via the phone, the call does not go through to the called number. The default behavior for DND is to provide a tone to the calling party. If you wish the call go to coverage, provisioning changes are required. Bring up a SAT session on Communication Manager. Type the command 'change system-parameters features'. Go to page 4 and change a setting called "Controlled Termination Restriction (Do Not Disturb)". By default this set to 'tone'. Change the setting to 'coverage'. Once this is done, submit the form. Now when DND is enabled, the call will go to assigned coverage station(s). There is no indication of call arrival at the initial called number as this feature redirects the call immediately to the station set up in the associated coverage path.

When Special Application 8481 (SA8481) is enabled on Communication Manager (CM), it allows a CTI application, that is making an outbound call request, to replace the actual calling party number with a new calling party number. To do this, the application must place specially formatted data into the private data parameter that is used to pass User-to-User Information (UUI). For example, a TSAPI application would place this data into the "userInfo" private data parameter when making a call request.

Initially, only ISDN/H.323 trunks were supported with SA8481, but starting with CM 6.0.1, SA8481 was enhanced to support SIP trunks as well. For SA8481 to work with SIP trunks, applications must provide one of two new values, 0x10 (for hex) or 0x14 (for ASCII), as the third byte in the specially formatted data. The new values with also work with ISDN/H323 trunks. For reference, the older values were 0x00 (for hex) and 0x04 (for ASCII).

Below are examples of the data format used to invoke SA8481, along with descriptions of each byte.

Example 1: This example shows the format used to send a new calling party number for an outbound call over a SIP trunk. Note the third byte of the data below is set to one of the new values previously described.

7e 0e 10 0c 00 21 39 37 30 32 32 32 31 32 33 34

All the data above is sent as private data; however, the first three bytes of this format are used to repeat data that would appear in the Adjunct Switch Application Interface (ASAI) UUI header:

7e – this byte must be "7e", which represents the ASAI UUI IE identifier
0e – is the total length of the UUI IE in hex
10 – is the Protocol Descriptor (this can be either 10 for hex, or 14 for ASCII)

The next three bytes represent the following:

0c – is the length of the new calling party number
00 – is the Presentation Indication (this can be either 00 for non-restricted, or 01 for restricted)
21 – is the existing encoding of Numbering Plan Information/Type of Number (NPI/TON) byte as used in ISDN/H.323

The remaining bytes represent the new calling party number using hex digits 0x30 through 0x39:

39 37 30 32 32 32 31 32 33 34 – in this example, the application is sending “9702221234” as the new calling party number

When SA8481 is invoked for a call over a SIP trunk, both a new calling party number AND UUI can be sent. However, if the call is going out over an ISDN/H.323 trunk, then either a new calling party number OR UUI can be sent, not both. If an application does provide both a new calling party number and UUI for a call over an ISDN/H.323 trunk, then the new calling party number has precedence, and the UUI provided by the application will be ignored/not included in any call messages generated by CM.

Example 2 below repeats Example 1, but now UUI has been added.

Example 2: This example shows the format used to send both a new calling party number and UUI for an outbound call over a SIP trunk:

7e 12 10 0c 00 21 39 37 30 32 32 32 31 32 33 34 03 01 02 03

Note, the first 16 bytes are the same as those shown for Example 1. Only the value for byte 2 has modified since the additional UUI data (highlighted) has caused the total length of data to increase.

The final set of bytes are for the UUI data:

03 – is the length of the UUI data
01 02 03 – is the actual UUI data in hex since 0x10 (hex) was used for byte 3 (in this example, the application is sending "1 2 3" as UUI data)

Notes:

  1. New applications being developed should use the new values, 0x10 and 0x14, to invoke SA8481.
  2. If an application sends the specially formatted data to invoke SA8481, but SA8481 is not enabled on CM, then the calling party number is not replaced, and the entire contents of the specially formatted data are treated as UUI data.
  3. When SA8481 is invoked for a call over a SIP trunk from CM to Session Manger (SM) and the corresponding CM SIP signaling group has the "Peer Server" field set to “SM”, the new calling party number is sent in the "Alternate-CLI" SIP header. An adaptation must be applied on either Session Manager or the SBCE to parse the "Alternate-CLI" data and populate the appropriate headers (i.e., "PAI", "From" and "Contact") with the new calling party number. If the CM SIP signaling group does not have the "Peer Server" field set to "SM", then CM will automatically place the new calling party number into the appropriate SIP headers, and an adaptation on SM or SBCE is not required. Please refer to the following PSN for more details: https://download.avaya.com/css/public/documents/101035177.

There may be a brief period, immediately after a call is answered, where the media path of the call is unstable. This will occur when a call involves a SIP trunk and Direct IP-IP (shuffling) is enabled. In older releases (see below) of Communication Manager, attempting a Single Step Conference at this stage could cause the call to drop or to end up with no audio.

In order to address this issue, an update was added to CM 7.0.1.1, CM 6.3.15 and 6.3.115. This update causes Communication Manager to reject a Single Step Conference request during this period with the error code INVALID_OBJECT_TYPE (18).

If an application receives an error of INVALID_OBJECT_TYPE to a Single Step Conference request, it should wait for a short period (200ms is recommended) and try again. The second attempt will, most likely, succeed.

In some environments, the extra delay in starting the recorder may be unacceptable. In these cases, a workaround would be to disable shuffling on the appropriate signaling group(s) or network region(s).

For further information, see PSN020242u which is available on support.avaya.com

Yes. Selective Listen Hold (SLH) – also referred to as Selective Listen Disconnect prevents the flow of voice and DTMF signals coming from a specified party from being received by another party in the call. In many cases blocking that pathway is valuable functionality. One use of this functionality is with a PCI-DSS application to prevent a contact center agent from hearing personal information supplied by a party in the call. However, if a recording device that is using DMCC Multiple Registrations, is receiving the agent’s audio stream, when SLH is invoked to reconfigure the audio the agent is receiving, the recording application is also blocked from receiving the voice and DTMF information sent by the far end party. This may or may not be expected by the call recording application. Another case could be that the Multiple Registrations application is doing analytics on the audio stream; when SLH is invoked, the analytics application may be prevented from receiving audio or DTMF events unexpectedly and undesirably. Since multiple applications may be involved at a customer site (one using Multiple Registrations and the other invoking SLH), but both operating on the same party in the call, the MR application may be unaware that the interaction is occurring. If being in full control of the receipt of all of the audio and DTMF information occurring in a call is required by the application, then the guidance in the DevConnect White Paper Recommended Guidance for DMCC Applications Utilizing Call Media should be reviewed for further information about how to properly design for this interaction.

Basic Call control

When calling attSingleStepConference() use participationType=PT_SILENT.

A call arrives at an extension (40010) and is answered. That extension is being monitored and when the ESTABLISHED event is received attSingleStepConference() is called with the connectionID of the ESTABLISHED event, an extension to conference in (deviceToBeJoin=40011), and a participationType=PT_ACTIVE. The conference is established. The agent at the original extension (40010) tries to manually transfer the call to a VDN. The transfer will not succeed. No event will be received when the agent tries to complete the transfer (i.e. presses the transfer button for the second time).

When participationType=PT_SILENT is used, the conferenced extension (40011) does not count when Communication Manager determines if the call can be transferred to a VDN.

To send UUI you need to use two different functions: The function attV6MakeCall() prepares the private data structure with data to be sent to the switch. The function cstaMakeCall() sends request to the switch. attV6MakeCall() is for private data version 6.

Sample code:
// return codes
static RetCode_t cstaRC = 0;
static RetCode_t pdRC = 0;

ATTPrivateData_t PrivateData;
ATTUserToUserInfo_t uui;
DeviceID_t destRoute;
Boolean priority;
// set the uui here
// set the destRoute here
// set the priority here

/* encode the private data structure */
pdRC = attV6MakeCall(&PrivateData, &destRoute, priority, &uui);

DeviceID_t callingID;
DeviceID_t calledID;
// set the callingID here
// set the calledID here

/* use TSAPI to make the call */
cstaRC = cstaMakeCall(acsHandle, invokeID, &callingID, &calledID, (pdRC == 0) ? (PrivateData_t *)&PrivateData : NULL);

Call Classifier Circuit Pack is required when using predictive dialing. The call classifier is used to analyze the call for certain conditions (e.g. tones) that are reported to the application. When cstaMakePredictiveCall is requested,

  1. If a call classifier port cannot be allocated, the classified (predictive dial) call fails with a RESOURCE cause.
  2. For a switch classified call, when the Call Classification After Answer Supervision option is set to 'n', the call classifier is allocated prior to call origination, or quickly thereafter. If this option is set to 'y' and the call has originated over an (ISDN only) trunk and when the call is answered, then a call classifier is allocated. In both cases, a call classifier is needed.

For more details, please refer to the Switched Classified Call section in Avaya Call Center, Release 5.0, Automatic Call Distribution (ACD) Guide, 07-602568, Release 5.0, January 2008 available on http://www.avaya.com/support.

There are some setup requirements for collecting UserEnteredCode (UEC), as described below:

  1. Administer a VDN and a vector on Communication Manager with a "Collect Digits" step and route command to a second VDN. The purpose of this VDN is to collect the UEC and redirect the call to the second VDN.
  2. Administer a second VDN and vector to receive the redirected call from the first VDN. The purpose of this second VDN is to report the UEC to the TSAPI service. The second VDN must be monitored by a cstaMonitorCallsViaDevice service request from at least one client. This VDN should redirect the call to its destination. The destination can be a station extension, an ACD split or hunt group, a destination selected by a adjunct routing step or another VDN.

Once this setup is complete and a call is redirected from the first VDN to the second VDN, the UEC will be available as a private data member in all the events received by the TSAPI monitor on the second VDN. The following code snippet shows how to extract this information when the application receives the Delivered event.

if (attEvent.eventType == ATT_DELIVERED)
{       
	ATTDeliveredEvent_t deliveredEvent = attEvent.u. deliveredEvent;
	if (deliveredEvent.userEnteredCode.indicator == UE_ENTERED)
	{
		char UEC[ATT_MAX_USER_CODE] = {0x00, };
		strcpy (deliveredEvent.userEnteredCode.data, UEC);
	}
}
				

For more detailed information, please refer to the section titled How to Collect userEnteredCode (UEC) in the document titled Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4, available on http://www.avaya.com/devconnect.

The EnablePending flag is supported in the privateData parameter starting with Private Data Version (PDV) 6. Ensure that the application negotiates the correct PDV in the acsOpenStream function.
For information about negotiating private data versions, please see the section titled Requesting private data defined under acsOpenStream() from Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4.

Once the PDV version is negotiated, follow these steps:

  1. Set the private data to be sent: The attSetAgentState function can be used to appropriately set the private data as shown by the code sample below.
    Note:The last parameter to the function attSetAgentState is for the EnablePending flag.
    ATTPrivateData_t privateData;
    RetCode_t retcode;
    retcode = attSetAgentState (&privateData, WM_AUTO_IN, 0, TRUE);
    if(retCode < 0){
    /* Some kind of failure, need to handle this ... */
    }
    								
  2. Set the agent state: Call the cstaSetAgentState method and pass the private data to it as shown by the code snippet below:
    ACSHandle_t acsHandle; 	 //An opened ACS Stream Handle
    InvokeID_t invokeID = 1; 	 //Application generated Invoke ID
    DeviceID_t device = "12345"; //Device associated with ACD Agent
    AgentMode_t agentMode = AM_LOG_IN; //Requested Agent Mode
    AgentID_t agentID = "50001";    //Agent login identifier
    AgentGroup_tagentGroup = "11111"; //ACD split to log Agent into
    retcode = cstaSetAgentState (acsHandle, invokeID, &device, agentMode, &agentID, &agentGroup, agentPassword, (PrivateData_t *)&privateData);
    								
For more details, please refer to the section titled Sample Code - Set Agent State from Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4 available on the Avaya DevConnect portal (www.avaya.com/devconnect).

Avaya's TSAPI implementation follows the CSTA specification. The CSTA specification allows vendors implementing the specification to use Escape Services for sending vendor specific requests. The services in the Escape category allow an application to request a private service not defined by the CSTA standard.

To use Escape Services, the following steps need to be followed:

  1. Set the parameters for the private request: The TSAPI SDK provides appropriate functions for setting private request parameters. For example, to query if a station is busy or idle, the private data function attQueryStationStatus is provided. The following code snippet shows how to request parameters:
    DeviceID_t deviceID = '12345';
    ATTPrivateData_t privateData;
    RetCode_t retcode;
    retcode = attQueryStationStatus(&privateData, deviceID );
    
    if(retCode < 0){
    /* Some kind of failure, need to handle this ... */
    }
    					
  2. Invoke the Escape Service method: The Escape Service can then be invoked as shown by the code snippet below:
    ACSHandle_t acsHandle; // An opened ACS Stream Handle
    InvokeID_t invokeID = getNextInvokeID(); // Application generated Invoke ID
    
    retcode = cstaEscapeService	(acsHandle, invokeID, 					(PrivateData_t*) &privateData);
    
    if (retcode != ACSPOSITIVE_ACK){
    /* Some kind of failure, need to handle this ... */
    }
    					
  3. Check for the confirmation event: A response to the Escape Service request is sent as a confirmation event with the event type set appropriately. Return values provided in the response are available in the private data of the confirmation event. The application needs to extract these values in appropriate structures depending upon the request. In the example response to the query above, the response contains the number of calls in queue, number of agents logged in and number of agents available to receive calls. The following code snippet shows how to extract these values from the confirmation event:
    CSTAEvent_t cstaEvent; 	  // CSTA event buffer
    unsigned short eventBufSize; // CSTA event buffer size
    short availableAgents;	  // number of available agents
    short callsInQueue;		  // number of calls in queue
    short agentsLoggedIn;	  // number of agents logged in
    
    eventBufSize = sizeof(CSTAEvent_t);
    privateData.length = ATT_MAX_PRIVATE_DATA;
    retcode = acsGetEventBlock(acsHandle, (void *)&cstaEvent, &eventBufSize, (PrivateData_t *)&privateData, NULL);
    
    if (retcode != ACSPOSITIVE_ACK){
    	/* Some kind of failure, need to handle this ... */
    	}
    
    else if ((cstaEvent.eventHeader.eventClass == CSTACONFIRMATION) && (cstaEvent.eventHeader.eventType == CSTA_ESCAPE_SVC_CONF))
    	{
    		if (privateData.length > 0) {
    			/* Confirmation contains private data */			
    			if (attPrivateData(&privateData, &attEvent) != 				CSPOSITIVE_ACK){
    				/* Decoding error */
    			}
    			else if (attEvent.eventType == 						ATT_QUERY_ACD_SPLIT_CONF)
    			{
    				queryAcdSplitConf = 									(ATTQueryAcdSplitConfEvent_t *)
    					&attEvent.u.queryAcdSplit;
    				availableAgents = 									queryAcdSplitConf.availableAgents;
    				callsInQueue = 
    					queryAcdSplitConf.callsInQueue;
    				agentsLoggedIn = 										queryAcdSplitConf.agentsLoggedIn;				}
    		}
    		else {
    		/* Error - no private data in confirmation event */
    		}
    	}
    }
    						
For more details, please refer the document Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4 available on the DevConnect portal (www.avaya.com/devconnect).

To monitor an ACD/hunt group, some configuration is required on the AE Services server and Communication Manager. First, ensure that security database is enabled on AE Services server and the ACD/hunt group is added as an ACD device in the device list.

For more information refer Avaya MultiVantage® Application Enablement Services Administration and Maintenance Guide Release 4.2 02-300357 Issue 10 May 2008.

On Communication Manager, the hunt-group/ACD to be monitored needs to be modified. Use the 'change hunt-group' command, and set or select the check box for ACD.

Once the above task is completed, applications can get the call queue status using the escape service function attQueryACDSplit().

The Query ACD Split service provides the number of ACD agents available to receive calls through the split, the number of calls in queue, and the number of agents logged in. The number of calls in the queue does not include direct-agent calls.

The following is a sample code snippet for Query ACD Split service:

ACSHandle_t acsHandle;		// An opened ACS Stream Handle
InvokeID_t invokeID = 1;		// Application generated Invoke IDDeviceID_t deviceID = "12345";			// Device associated with ACD splitRetCode_t retcode;				// Return code for service requests

CSTAEvent_t cstaEvent;		// CSTA event buffer
unsigned shorteventBufSize;	// CSTA event buffer size
ATTPrivateData_tprivatedata; 	// ATT private data buffer
ATTEvent_t attEvent; 		// ATT event buffer
ATTQueryAcdSplitConfEvent_t 	// Query ACD Split confirmation
*queryAcdSplitConf; 		// event pointer

retcode = attQueryAcdSplit(&privatedata, &deviceID);
if (retcode < 0 )
{
/* Some kind of failure, need to handle this ... */
}

retcode = cstaEscapeService(acsHandle,invokeID,(PrivateData_t*) &privateData);

if (retcode != ACSPOSITIVE_ACK)
{
/* Some kind of failure, need to handle this ... */
}
				
Once the escape service request for getting the call queue status is sent to the TSAPI service, the service returns the information as a confirmtion event which is asynchronous in nature. Applications must be set to receive events and extract the event information (refer the FAQ titled "What are the steps required to receive events from an open ACS stream in a TSAPI application?"). The following code snippet shows how to get the call in the queue from the CSTA_ESC_SVC_CONF comfirmation event.
CSTAEvent_t cstaEvent; 	  	// CSTA event buffer
unsigned short eventBufSize; 	// CSTA event buffer size
short availableAgents;	  	// number of available agents
short callsInQueue;		  	// number of calls in queue
short agentsLoggedIn;	  	// number of agents logged in

eventBufSize = sizeof(CSTAEvent_t);
privateData.length = ATT_MAX_PRIVATE_DATA;
retcode = acsGetEventBlock(acsHandle, (void *)&cstaEvent, &eventBufSize, (PrivateData_t *)&privateData, NULL);

if (retcode != ACSPOSITIVE_ACK)
{
	/* Some kind of failure, need to handle this ... */
}

else if ((cstaEvent.eventHeader.eventClass == CSTACONFIRMATION) &&           (cstaEvent.eventHeader.eventType == CSTA_ESCAPE_SVC_CONF))
{
	if (privateData.length > 0)
	{
		/* Confirmation contains private data */			
		if (attPrivateData(&privateData, &attEvent) != CSPOSITIVE_ACK)
	{
			/* Decoding error */
		}

		else if (attEvent.eventType == ATT_QUERY_ACD_SPLIT_CONF) 
		{
			queryAcdSplitConf = (ATTQueryAcdSplitConfEvent_t *)
						&attEvent.u.queryAcdSplit;
			availableAgents = queryAcdSplitConf.availableAgents;
			callsInQueue = queryAcdSplitConf.callsInQueue;
			agentsLoggedIn = queryAcdSplitConf.agentsLoggedIn;
		}
	}
	else 
	{
		/* Error - no private data in confirmation event */
	}
}
					

When a TSAPI application opens an ACS stream with the acsOpenStream function, the application will not automatically start getting TSAPI events. The application needs to perform the following steps in order to receive the events and extract relevant information from the events.

Please note that the steps mentioned here are for applications based on a Microsoft Windows platform.

  1. Register the window with TSAPI service:
    The acsEventNotify() function allows a Win32 application to request that a application defined message to be posted to its application message queue when an incoming ACS event is available. The function's parameters associate the Window object and ACS stream. Once the application invokes this function with the appropriate values, the TSAPI service starts sending the application defined message to the application message queue with the appropriate event class and type information.

    This function only enables the notification of an incoming event. Use acsGetEventPoll() or acsGetEventBlock () to actually retrieve the complete event information.

    //define the custom message that will be received by the application.
    #define WM_ACSEVENT WM_USER + 99
    
    long FAR PASCAL
    WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	// declare local variables...
    	switch (msg)
    	{
    		case WM_CREATE:
    		// post WM_ACSEVENT to this window whenever an ACS event
    		// arrives
    		acsEventNotify (acsHandle, hwnd, WM_ACSEVENT, TRUE);
    		// other initialization, etc...
    		return 0;
    
    		case WM_ACSEVENT:
    		// wParam contains an ACSHandle_t	
    		// HIWORD(lParam) contains an EventClass_t
    		// LOWORD(lParam) contains an EventType_t
    		// dispatch the event to user-defined
    		// invoke a routine to get the event information from
    		// the ACS stream
    		processACSEvent();
    		return 0;
    
    		// process other window messages...
    	}
    return DefWindowProc (hwnd, msg, wParam, lParam);
    						
  2. Extract the event information on notification:
    There are two ways to extract or receive event information, as given below:
    1. Blocking Mode:
      The acsGetEventBlock() function is used when an application wants to receive an event in a Blocking mode. In the Blocking mode, the application will be blocked until there is an event from the ACS stream that matches the parameter acsHandle. The acsOpenStream() service request returns acsHandle that identifies the ACS stream that was opened. TSAPI sets this value so that it is unique to the ACS stream. Once acsOpenStream() is successful, the application must use this acsHandle in all other function calls to TSAPI on this stream. If acsOpenStream() is successful, TSAPI guarantees that the application has a valid acsHandle. If acsOpenStream() is not successful, then the function return code gives the cause of the failure. If acsHandle is set to zero (0), then the application will block until there is an event from any ACS stream opened by this application. The function will return after the event has been copied into the application's data space.
    2. Non-Blocking Mode:
      The acsGetEventPoll() function is used when an application wants to receive an event in a Non-Blocking mode. In the Non-Blocking mode, the oldest outstanding event from any active ACS stream will be copied into the applications data space and control will be returned to the application. If no events are currently queued for the application, the function will return control immediately to the application with an error code indicating that no events were available.
  3. The following code snippet shows how to receive event information:
    void processACSEvent ()
    {
    
    	ACSHandle_t acsHandle;		// An opened ACS Stream Handle
    	CSTAEvent_t cstaEvent;		// CSTA event buffer
    	unsigned short eventBufSize;	// CSTA event buffer size
    	ATTPrivateData_tprivateData;	// ATT service request private 						// data buffer
    	RetCode_t retcode; // Return code for service requests
    
    	// for Blocking mode, 
    	retcode = acsGetEventBlock(acsHandle, (void *)&cstaEvent, 			    &eventBufSize, (PrivateData_t *)&privateData, NULL);
    
    	/* for non-blocking mode use acsGetEventPoll function, the return 
    	 * code ACSERR_NOMESSAGE indicate there are no messages available 
    	 */
    
    	if (retcode != ACSPOSITIVE_ACK)
    	{
    		/* Some kind of failure, need to handle this ... */
    	}
    
    	/* following code is abbreviated handling for a confirmation 	 * events. 
    	 */
    
    	if (cstaEvent.eventHeader.eventClass == CSTACONFIRMATION) 
    	{
    		switch (cstaEvent.eventHeader.eventType)
    		{
    			case CSTA_MAKE_CALL_CONF:
    		// verify InvokeID
    		// Provide additional handling of event
    		;;
    			default:
    			// unexpected message, report to error logs
    		;;
    	}
    	}
    }
    						
For more details, please refer Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4.

If two VDNs are routing calls to a single ACD split and the application is not monitoring the VDNs, the steps defined below can be used to determine the specific VDN that routed the call if the monitors are on the answering stations:

  1. Use 'cstaMonitorDevice' function to monitor the destination extension(s) where the VDNs route the call (i.e. the members of the hunt group, or the appropriate agents).
  2. Once the call is ringing at the destination device, the application receives the 'Delivered' event. The following code shows how to extract the VDN's extension from the 'Delivered' event.
CSTAEvent_t cstaEvent; 	  // CSTA event buffer
unsigned short eventBufSize; // CSTA event buffer size
short vdn_addr;	 	  // Address of VDN

eventBufSize = sizeof(CSTAEvent_t);
privateData.length = ATT_MAX_PRIVATE_DATA;
retcode = cstaMonitorDevice(acsHandle, (void *)&cstaEvent, &eventBufSize, (PrivateData_t *)&privateData, NULL);

if (retcode != ACSPOSITIVE_ACK)
{
	/* Some kind of failure, need to handle this ... */
}

else if ((cstaEvent.eventHeader.eventClass == CSTAUNSOLICITED) &&                          
         (cstaEvent.eventHeader.eventType == CSTA_DELIVERED))
{
	CSTAUnsolicitedEvent cstaNewEvent = cstaEvent.event.cstaUnsolicited;
	DeviceID_t deviceid = cstaNewEvent.u.delivered.calledDevice.deviceID;
	// deviceid now contains the extension of the VDN that routed the call.
}
					

No an application cannot use Single Step Conference to conference an extension that already has a bridged appearance of a member of the call, instead the application needs to use cstaAnswerCall() to answer the call.

When an application uses attSingleStepConferenceCall() method to conference an extension that already has a bridged appearance of a member of the call, a CONFERENCE_MEMBER_LIMIT_EXCEEDED error is returned to the application indicating Generic System Resource Availability. This is because the call (in the form of bridged appearance) with the same call identifier already exists on the extension. Instead of using the Single Step Conference request, to get the correct behavior, the application needs to send an answer request using the cstaAnswerCall() method containing the callID and the station extension that the application wants to add to the call.

After the bridged device is connected to the call by answering the call using cstaAnswerCall() method, the call can be disconnected from the device using cstaClearConnection() method. In this case, if the bridged call is still active with other endpoints still on the call then the device automatically becomes bridged again, however, there is no DELIVERED event generated.

When an extension needs to be added to a call, the application needs to make appropriate method call to get the correct behavior. An application can decide which method to use (attSingleStepConferenceCall() or cstaAnswerCall()) by getting the snapshot of the device using cstaSnapshotDeviceReq() method. If there is already a call (with same callID) in bridged state then use cstaAnswerCall() otherwise use attSingleStepConferenceCall().

Adjunct Routing

The call is disconnected because the VDN does not have a wait step following the adjunct routing step. An example of this situation would be where the last step of a VDN is adjunct routing link X where X is the CTI link number. When a call arrives at the VDN extension it is answered but it is immediately disconnected. The VDN should have a wait-time Y secs hearing Z step following the adjunct routing link X step. Y must be enough time to allow the route request to get to the AE Services server and have the AE Services server supply a route using the cstaRouteSelectInv() function. Generally, 5 seconds should be sufficient for the route to be returned. Z should either be silence or ringback depending on what you want the caller to hear while Communication Manager is waiting to get the route from the AE Services server.

This is an AE Services server licensing issue. The error code, 52, refers to PERFORMANCE_LIMIT_EXCEEDED error. Adjunct routing requires a TSAPI Advanced User license to be provisioned in the AE Services server. An error value of 52 indicates that a TSAPI license, either the basic or advanced, was not available either because none was provisioned or the licenses were all in use at the time of the route request. The solution to this problem is to increase the appropriate license count by either releasing the licenses that are currently in use or to get additional licenses. Please contact the sales or devConnect support team for acquiring AE Services licenses depending on where the AE Server is being used.

User Authentication

The AE Services server can be administered to authenticate users via the User Service, the local Linux user accounts, or a Microsoft Active Directory Service. The User Service is the default authentication authority. When using the User Service for authentication, the login and password passed to acsOpenStream() must be a valid CTI User and password which has been administered on the AE Services server. See Chapter 6: Alternative TSAPI Service Authentication Methods of the ?Avaya MultiVantage Application Enablement Services 3.0 Administration and Maintenance Guide? , June 2005, for more information on how to use the local Linux user accounts or Microsoft Active Directory Service as the authentication authority. If you want to use the Security Database to limit which devices a given user may control, that user must be added to the User Service regardless of which authentication authority you choose. I.e. if you are authenticating users against the local Linux user accounts or a Microsoft Active Directory Service you will also have to add that user to the User Service as a CTI User.

Using a web browser, go to https://<myAES>:8443/MVAP/forms/user/userHome.jsp where <myAES> is the name or IP address of your AE Services server. Enter the username and password of the User Management Administrator. The default User Management Administrator username/password is avaya/avayapassword. Once you have logged in as the User Management Administrator select the User Management link. After selecting the User Management link a second time, select the Add User link. Enter the appropriate information in all required fields marked with an asterisk (*). Set the CT User field to Yes and then press the Apply button. The new user is now added.

This application expects the user to be a Computer Telephony (CT) user with unrestricted access (or user as permissions to access at least the calling stations). Login to CT Administration page and make sure the user has CT user privileges with unrestricted access. Also, check if the stations used for the TSAPI test are Phantom (CTI) extensions.

The Application Enablement Services (AES) Security Database (SDB) governs authorization for user (application) control of devices (including ACD). Configuration is required on AES server to monitor / control an ACD and the sample application to run properly. In general, when developing an application which monitors ACD, there are two alternative configurations.

  • Disable SDB.

    Security database (SDB) is enabled when AES is installed (it is enabled on the AES simulator as well).

    To disbale SDB, Go to AES's CTI OAM Admin > Administration > TSAPI Configuration: deselect (or un-check) 'Enable SDB' checkbox.

    Make sure to restart the TSAPI service (via the CTI OAM Admin > Maintenance > Service Controller page).

  • With SDB enabled on AES server, the CTI user should have "Unrestricted Access".

    Follow these steps:

    • Check SDB is enabled.
      Security database (SDB) is enabled when AES is installed (it is enabled on the AES simulator as well). If not, to enable SDB. Go to AES's CTI OAM Admin > Administration > TSAPI Configuration: select (or check) 'Enable SDB' checkbox. Make sure to restart the TSAPI service (via the CTI OAM Admin > Maintenance > Service Controller page).
    • Add devices to SDB
      To Add devices (the objects that will be monitored or controlled) via the AES Administrator OA&M Web Interface, go to AES's CTI OAM Admin > Administration > Security Database > Devices > Add Device. Select Device Type as 'ACD' if you wish to control access to particular ACD/hunt-groups. Select 'VDN' to control access to a device type of VDN
    • Create CTI User
      This is optional if one or more CTI user already exist.
      To add a new user, start the AES OA&M Web page and login with the avaya login. Then select User Management > User Management > Add User.

      Set the User Id, Common Name, Surname, User Password and Confirm Password fields. Set CT User to "yes" and push the "Submit" button at the bottom of the page. Use the user ID you have created for your application development

    • Set unrestricted access to the CTI User.
      Go to AES's CTI OAM Admin > Administration > Security Database > CTI Users > List all users
      Select the CTI user and click 'Edit'
      On 'Edit CTI user' page, click button 'Enable' in front of label 'Unrestricted Access'.
      If button caption is 'Disable' then the user already have unrestricted access.

Device Authorization

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which does not have unrestricted access. The deviceID which was passed to cstaMonitorDevice() contains either an extension which does not exist on the Communication Manager associated with the open ACS stream, or the extension is a VDN. If the desired extension is a VDN use cstaMonitorCallsViaDevice() instead of cstaMonitorDevice(). In addition to allowing VDNs to be monitored, cstaMonitorCallsViaDevice() will enable event reporting on calls at the specified device to follow the call as it gets routed to other destinations.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which has unrestricted access. The deviceID which was passed to cstaMonitorDevice() contains either an extension which does not exist on the Communication Manager associated with the open ACS stream, or the extension is a VDN. If the desired extension is a VDN use cstaMonitorCallsViaDevice() instead of cstaMonitorDevice(). cstaMonitorCallsViaDevice() can only be used on VDN and ACD split devices . In addition to allowing VDNs to be monitored, cstaMonitorCallsViaDevice() will enable event reporting on calls at the specified device to follow the call as it gets routed to other destinations.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which did not have the appropriate permissions to control the deviceID which was passed to cstaMonitorDevice(). In this case, the specific CTI User does not have a worktop or a Device/Device group. See the How can I tell which devices a specific CTI User has permission to control? FAQ for more details.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which did not have the appropriate permissions to control the deviceID which was passed to cstaMonitorDevice(). In this case, the specific CTI User has a worktop but does not have a Device/Device group. However, the deviceID for which control is being requested is not part of the worktop. See the How can I tell which devices a specific CTI User has permission to control? FAQ for more details.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which did not have the appropriate permissions to control the deviceID which was passed to cstaMonitorDevice(). In this case, the specific CTI User does not have a worktop but does have a Device/Device group. However, the deviceID for which control is being requested is not part of the Device/Device group. See the How can I tell which devices a specific CTI User has permission to control? FAQ for more details.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which did not have the appropriate permissions to control the deviceID which was passed to cstaMonitorDevice(). In this case, the specific CTI User does have a worktop and a Device/Device group. However, the deviceID for which control is being requested is not part of either the worktop or the Device/Device group. See the How can I tell which devices a specific CTI User has permission to control? FAQ for more details.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which has unrestricted access. The deviceID which was passed to cstaMonitorCallsViaDevice() contains an extension which does not exist on the Communication Manager associated with the open ACS stream, or the extension is not a VDN or ACD split.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which did not have the appropriate permissions to control the deviceID which was passed to cstaMonitorCallsViaDevice(). In this case, the specific CTI User does not have a Call/Device group. See the How can I tell which devices a specific CTI User has permission to control? FAQ for more details.

The loginID and passwd parameters supplied when calling acsOpenStream() represent a specific CTI User on the AE Services server which did not have the appropriate permissions to control the deviceID which was passed to cstaMonitorCallsViaDevice(). In this case, the specific CTI User has a Call/Device group. However, the deviceID for which control is being requested is not part of the Call/Device group. See the How can I tell which devices a specific CTI User has permission to control? FAQ for more details.

To check which devices the specific CTI User has permission to control use a web browser and go to https://<IP-address-Hostname-of-AE-Services> where IP-address-Hostname-of-AE-Services is the name or IP address of your AE Services server. Enter the username and password to access the Web OA&M interface e.g craft/craft01. Once you have logged in, select the following series of links from the left hand menu: Security, Security Database, CTI Users, List All Users (note these instructions are for release 5+ of AE Services; on earlier releases check the product documentation for how to access the CTI Users page). Choose the desired User ID and then press the Edit button.

The page that is displayed (see the example) will contain a line which states Unrestricted Access with an accompanying checkbox. If the box is checked, then the selected user has unrestricted access to all extensions on Communication Manager. If the box is unchecked, then the selected user does not have unrestricted access. Without unrestricted access the user will have limited permissions. Permissions will then be granted based on the following table.

TSAPI Function Governing Access Group(s) Access Group Description
cstaGroupPickupCall
cstaMakeCall
cstaMakePredictiveCall
cstaSetMsgWaitingInd
cstaSetDoNotDisturb
cstaSetForwarding
cstaSetAgentState
cstaSnapshotDeviceReq
Worktop Call Origination and Termination Restricts access to Call Control Services.
cstaMonitorDevice Worktop Device / Device Restricts access to Monitoring Services ? Event Notification ceases when a call leaves the device. The device cannot be a VDN.
cstaMonitorCallsViaDevice Call / Device Restricts access to Monitoring Services ? Event Notification continues when a call leaves the device. The device must be a VDN or ACD.
cstaMonitorCall
attSingleStepConferenceCall
Call / Call Restricts access to Monitoring Services - Event Notification is allowed if the call ID is known. Users either have or do not have this permission; there is no actual device group associated with this permission.
cstaRouteRegisterReq Allow Routing on Listed Device Restricts access to Routing Services.

The first column indicates the specific API function being used, the second column indicates which access group(s) must include the device being controlled for permission to be granted. Note that when the Governing Access Group(s) column contains both the Worktop and another access group (Call Origination and Termination or Device / Device) the device being controlled does not have to be in both.

For more information regarding adding devices, and placing associating devices with CT Users see the TSAPI Configuration and the Security Database section of the Avaya Aura Application Enablement Services Administration and Maintenance Guide.

This result is returned for four reasons.

  1. The request was received over a link that is not an ADJ-IP link.
  2. The request identified a station that was not a SIP 4620CC or 96XX station type.
  3. Page 6 of the station form for the identified station must have the "Type of 3PCC Enabled" field set to "Avaya". By default it is "none"
  4. The phone must have Advanced SIP Telephony (AST) mode enabled. Use the phone's internal menu (mute-c-r-a-f-t-#) to access the SIP settings to verify or change the setting.

For ASAI operations to work the following must also be true:

The firmware in the station set must be a minimum of:

  • 16XX: SIP16CC_1_0_11_5_b2002S.bin
  • 96XX: SIP96xx_2_0_3_0_b1S.bin
Control of non-Avaya SIP devices is not supported.

While some ASAI requests work on 4620CC phones, not all do, and none are not officially supported.

The error 'TSERVER_PBX_ID_NOT_IN_SDB' corresponds to an attempt being made to open a stream to a CTI-LINK or OAM name (Tserver/PBX ID) when the name is not in the Security Data Base. This means that the switch connection name specified by the application does not match the Security Database entry for any T-link (aka, switch connection). For example, if the switch name in the Security Data Base (SDB) is 'CMSIM' and the application is sending the switchname as 'CMSMI', a 'TSERVER_PBX_ID_NOT_IN_SDB' error will occur.

The UNRECOGNIZED_OPERATION_REJECTION response is provided in two situations. The first is when an unrecognized service request (message) is received by the TSAPI service on AE Services. The second is when a TSAPI request with a zero or negative invoke ID is received by the TSAPI service on AE Services. In both cases the application developer should carefully check the transmitted message for correctness as compared to the private data version negotiated, message structure and values sent in the request.

One cause may be that there is a provisioning error in Communication Manager related to the station you are logging the agent into. By enabling ASAI MST tracing and attempting the login, do you see an error response indicating “CAUSE local pvt netwk |cv pvt netwk serv local usr:11. Agent not member of split”? If the station is an H.323 station make sure that the SAT ‘change off-pbx-telephone station-mapping’ form for the station extension is not provisioned for OPS. For a SIP station, OPS should be provisioned. If the device is a SIP station make sure that the station type on the station form is set to one of the SIPCC station types.

If you are certain that you are sending a valid station or agentID, make sure that Expert Agent Selection is enabled on the ‘change system-parameters features’ form (this is on page 11 in Communication Manager Release 7).

CALL CENTER SYSTEM PARAMETERS

EAS
	Expert Agent Selection (EAS) Enabled? y 
                      

Yes, a TSAPI application can get the list of devices that it can control by using the cstaGetDeviceList() API. This API returns only those devices which are provisioned for the CTI user whose credentials were supplied while opening the stream.

Please note that the following configuration is required for the API to work correctly:

  1. Security Database (SDB) should be enabled: For the cstaGetDeviceList() API to work correctly, the user should ensure that SDB is enabled for the TSAPI service. If the SDB control is disabled, then refer to the section titled "Enabling the Security Database" in Chapter 6 of the document titled "Avaya MultiVantage® Application Enablement Services Administration and Maintenance Guide Release 4.2, Doc-Id: 02-300357, Issue 10 May 2008" available on http://www.avaya.com/devconnect to understand how to enable the SDB.
  2. 'Unrestricted access' should be disabled: The CTI user (used while opening the stream) must have 'Unrestricted access' set to 'disabled'. If 'Unrestricted access' is not disabled, then disable it and provision appropriate permissions on various devices. Please refer to the section titled "About Granting Additional Permissions" in Chapter 6 of the document titled "Avaya MultiVantage® Application Enablement Services Administration and Maintenance Guide Release 4.2, Doc-Id: 02-300357, Issue 10 May 2008" available on http://www.avaya.com/devconnect to know more about how to provision permissions for a CTI user on various devices.
Parameters required for the cstaGetDeviceList() method are:
  1. ulAcsHandle: Handle returned by the acsOpenStream() method.
  2. invokeID: Handle used by the application for matching a service request with its corresponding confirmation event.
  3. nIndex: Index refers to the starting position from where the list of devices will be returned. A CTI user can have privileged access to a large number of devices. However, this method returns only a limited (defined by CSTA_MAX_GET_DEVICE and set to 20) number of devices in any single CSTAGetDeviceListConfEvent event. Hence, this method needs to be called multiple times to retrieve the complete list of devices when the list to be returned contains more than CSTA_MAX_GET_DEVICE (20) devices. The application should specify a value of '-1' for the first time to get the list of devices from the beginning. Specifying some other positive value, for example '5', will indicate that the application is interested in getting the next CSTA_MAX_GET_DEVICE list of devices starting from the fifth position. The index value is reset back to -1 in the confirmation event that contains the last batch of devices, indicating all the devices have been returned.
  4. eServiceLevel: This parameter indicates the service level for which the application wants the list of devices. The value of the eServiceLevel parameter and the administration settings on the OAM page affect the number of devices returned when the cstaGetDeviceList() method is used. The administration settings can be done on the OAM page i.e., CTI OAM Administration -> Administration -> Security Database -> CTI Users -> Edit CTI User. The levels are listed below:
    1. CSTA_HOME_WORK_TOP: This value will allow the application to receive the devices associated with "Worktop Name" on the specified page. This includes the Primary Device ID for the worktop and any of the devices in the Secondary Device Group for the worktop. The user can control these devices in addition to the devices in the "Call Origination and Termination" list. The user can monitor these devices in addition to the devices in the "Device/Device" and "Call/Device" lists.
    2. CSTA_AWAY_WORK_TOP: This value will allow the application to receive the list of devices that are associated with worktop other than the "Home worktop".
    3. CSTA_DEVICE_DEVICE_MONITOR: This value will allow the application to receive the devices associated with the "Device/Device" list on the specified page. The user can add a monitor on these devices.
    4. CSTA_CALL_DEVICE_MONITOR: This value will allow the application to receive the devices associated with the "Call/Device" list on the specified page. The user can use the cstaMonitorCallsViaDevice() API on these devices.
    5. CSTA_CALL_CONTROL: This value will allow the application to receive the devices associated with the "Call Origination and Termination" list on the specified page.
    6. CSTA_ROUTING: This value will allow the application to receive the devices associated with the "Allow Routing on Listed Device" list on the specified page. The user can use the cstaRouteRegisterReq()API on these devices.
    7. CSTA_CALL_CALL_MONITOR: This value is not supported by the cstaGetDeviceList() method i.e., when CSTA_CALL_CALL_MONITOR is provided as the value for this parameter, then the TSAPI Service returns the ACSUniversalFailureConfEvent: TSERVER_BAD_SDB_LEVEL error. The application should use the cstaQueryCallMonitor() method to use this value.

The sample code snippet below demonstrates the use of the cstaGetDeviceList()method for obtaining the list of devices.
ACSHandle_t ulAcsHandle; 	// Handle returned by the acsOpenStream() method.
RetCode_t nRetCode;     	// used to store the return code of method. 

CSTALevel_t eServiceLevel = CSTA_CALL_CONTROL; 	// This parameter indicates the
 						// class of service for which
		   				// the application wants the
						// list of devices. 
long nIndex =  -1; 	// -1 indicates that the application is interested in 
			// getting the list of devices from the beginning.
			    
nRetCode = cstaGetDeviceList (
				ulAcsHandle,  	 // ACS Stream's handle.
				0,  	      	 // using library generated invokeID
				nIndex,       	 // Index should be set to -1 the first time 
						 // this method is called. Set to the index 
						 // value returned in the confirmation event 
						 // for getting the next batch of devices. 
 			eServiceLevel // class of Service
				  );	 
// check the return code
if (nRetCode < 0)
{
		if (nRetCode == ACSERR_BADHDL)
  	{
			cout <<" ulAcsHandle is Invalid";
			cout <<" Error Code: "<<nRetCode;
		} // End of if

		else
		{
			// some other error.
			cout <<" Error Code : "<< nRetCode << endl;
			// handle error.
		}// End of else
	}// End of if

// The list of devices is returned in the confirmation event of the 
// cstaGetDeviceList() method.
						

The following code snippet shows how to retrieve the device list from the confirmation event of the cstaGetDeviceList() method.
CSTAEvent_t cstaEvent;			// Assuming the event has been extracted by using
 					// either cstaGetEventBlock or 
				    	// cstaGetEventPoll() and the event data is present 
				    	// in cstaEvent.

// Checking the confirmation event for cstaGetDeviceList request
	if (cstaEvent.eventHeader.eventClass == CSTACONFIRMATION &&
			cstaEvent.eventHeader.eventType == CSTA_GET_DEVICE_LIST_CONF) 
{	
	// The index value that application needs to use in 
	// cstaGetDeviceList() method for getting the next batch of 
  	// devices, when the list to be returned contains more than 
	// CSTA_MAX_GET_DEVICE (20) devices.
	int index = cstaEvent.event.cstaConfirmation.u.getDeviceList.index;

	// Total count of the devices returned
	int nDeviceCount = cstaEvent.event.cstaConfirmation.
				u.getDeviceList.devList.count;
cout << "Devices List :\n";

      for (int ndeviceIndex = 0; ndeviceIndex < nDeviceCount ; ndeviceIndex++)
      {
		char* device = cstaEvent.event.cstaConfirmation.u.getDeviceList.
					devList.device[ndeviceIndex];
		cout<&ltdevice<<endl;
	}// End of for
}// End of if
							

There are multiple reasons that this error may be returned.

  1. There is a limit on the number of monitors that can be established in Communication Manager against a station. This limit varies by release but is four up through Release 7 where it was increased to eight. A monitor on a station is referred to as a domain-control. A domain control on a station is created through DLG, CVLAN for each application that makes a request for one. TSAPI multiplexes requests by all DMCC, TSAPI and JTAPI applications using a common AE Services server across a single link to Communication Manager and thus only consumes one domain-control per AES (per station).
  2. There is already an operation in progress acting on the referenced station. The request may be processed if it is re-sent by the application.
  3. 3) The CTI Link is not configured as a ADJ-IP link in Communication Manager. This case can be particularly confusing because H.323 monitors work when this configuration mistake has occurred. If this is the case, delete the CTI link on Communication Manager and re-create it with type ADJ-IP.
This error is shown as OutstandingReqLimitExceededException in a DMCC Trace.

Private Data

When opening the stream acsOpenstream() must be called with the privateData argument set to a pointer to an ATTPrivateData_t structure. This structure must contain the correct information to negotiate a specific version(s) of private data. If you have provided a NULL pointer as this argument, no private data will be carried in any events.

The switch encodes messages according to ASN.1 Basic Encoding Rules (BER). This is a variable length encoding protocol which depends on the size and number of parameters being passed. Applications need to decode this data to before attempting to use the private data. The attPrivateData() function is used to do the decoding.

See the ConferenceTransfer sample code for an example of how to use attPrivateData() to decode the private data.

To receive Universal Call Identification (UCID) information in the events, the following system parameters must be correctly set.

Type the command 'change system-parameters features' on Avaya Site Administrator command window. Enable the following features on the CM in order to get UCID in service initiated event:

  • Create Universal Call ID (UCID) to 'y' (Setting to 'y' indicates that UCID will be generated for each call)
  • UCID network Node ID to 1 (or any number between 1 to 32767 and unique to the switch in the network)
  • Send UCID to ASAI to 'y' (Setting to 'y' enable transmission of UCID information)

Type the command 'change trunk-group N' on Avaya Site Administrator command window and enable the 'Send UCID' field from page 3 for each trunk group that is used for communication between CM systems. This field specifies whether or not the trunk should transmit Universal Call IDs. Sending UCIDs in a network of CMs allows an application server that interworks with all of them to realize it already has handled a call when it is transferred to an agent on another switch.

Every TSAPI application should validate that the application has successfully negotiated the requested private data version with the TSAPI service. The TSAPI application sends the requested private data version information in the acsOpenStream method. The application needs to check the private data information, received back in the AcsOpenStreamConfEvent event received from the TSAPI service, to ensure that the requested private data version has been successfully negotiated. The steps for checking the private data information are outlined below:

  1. Check that the length of the private data received is greater than 0.
  2. Check that the 'vendor' field of the private data is set to 'ECS'.
  3. Check that the first byte of the 'data' field of the private data is set to indicate private data encoding (see below for sample code).
  4. Check that the Private Data Version (PDV) number stored at the second byte of the 'data' field of the private data matches the private data version number requested by the application in acsOpenStream method.
The code snippet below illustrates how the application can do these checks.
ACSHandle_t acsHandle;		// Handle for the ACS Stream
CSTAEvent_t cstaEvent;		// CSTA event buffer required for retrieving the event Structure
unsigned short eventBufSize;	// CSTA event buffer size
PrivateData_t privateData;
char requestedversion[] = "7";	// PDV version requested in acsOpenStream

// Method for retrieving the entire response event structure

RetCode_t retcode = acsGetEventBlock (acsHandle, (void *) &cstaEvent, &eventBufSize, (PrivateData_t *) &privateData, NULL);
		
// acsOpenStream is successfully completed
if (cstaEvent.eventHeader.eventClass == ACSCONFIRMATION && 
	cstaEvent.eventHeader.eventType == ACS_OPEN_STREAM_CONF)
{
	// If any of the 'if' conditions is satisfied then 
	// either PrivateData is not correctly set or the requested version is
	// not supported by the TSAPI service

	// check if the private data length is greater than zero
	if (privateData.length <= 0)
	{
		// handle error condition
		// return error
	}
	
	// compare the vendor string 
	if (strcmp(privateData.vendor, ECS_VENDOR_STRING) != 0)
	{
		// handle error condition
		// return error
	}
	// check the one byte discriminator 
	if (privateData.data[0] != PRIVATE_DATA_ENCODING)
	{
		// handle error condition
		// return error
	}
	// Compare the PDV number with the requested PDV
	if (strcmp(privateData.data[1], requestedversion) != 0)
	{
		// handle error condition
		// return error
	}
	else
	{	
		// The application has correctly negotiated the Private Data
		// and requested version is supported by the TSAPI Service.
	}
}
					
On successful negotiation of Private Data, the application can start sending new service requests to the AE Services server.

Private Data received from the AE Services server is in an encoded format. A TSAPI application should follow these steps for decoding the Private Data.

  1. When an event (Confirmation or Unsolicited), is retrieved from the queue using either acsGetEventPoll or acsGetEventBlock, the application should first check the length of the Private Data returned by the method.
  2. The application should then pass the Private Data to attPrivateData for decoding. This function will return the Private Data in a structure defined as ATTEvent_t.
  3. Finally, the application should check the event type and extract the information.
The sample code below illustrates the usage of the attPrivateData method.
// The application must specify a pointer to a private data buffer as
// a parameter to either the acsGetEventBlock () or acsGetEventPoll ()
// request. Upon return, the application passes the address
// to attPrivateData () for decoding

PrivateData_t privateData;	
ATTEvent_t att_event;		// ATT_Event Buffer to hold private data
ACSHandle_t m_acsHandle;		// Handle for the already open ACS Stream
CSTAEvent_t cstaEvent;		// CSTA event buffer required for retrieving	// the Event Structure
unsigned short eventBufSize; 	// CSTA event buffer size

eventBufSize = sizeof(CSTAEvent_t);
privateData.length = ATT_MAX_PRIVATE_DATA;
		
// acsGetEventBlock(...) API is used for retrieving the Event Structure for
// any event received. The cstaEvent buffer will receive the event Structure // upon return.

retcode = acsGetEventBlock(m_acsHandle, (void *)&cstaEvent, 
		&eventBufSize, (PrivateData_t *)&privateData, NULL);

if (cstaEvent.eventHeader.eventClass == CSTACONFIRMATION && 	cstaEvent.eventHeader.eventType == CSTA_QUERY_AGENT_STATE_CONF)
{
	// Check to ensure that the event structure contains some Private Data 	// information
	if (privateData.length > 0)
	{
		// att_event will contain the private data information. 
		// Check the return code to ensure that no error occurred while
 		// decoding the Private Data
		if (attPrivateData((ATTPrivateData_t *)&privateData, &att_event) ==ACSPOSITIVE_ACK)
		{	
			// retrieving the private parameter talk state of Agent
			// version 5 is used for retrieving talk state, as the 		
			// same structure is retained in PDV 8 for retrieving talk
				int talk_state = att_event.u.v5queryAgentState.talkState;
		}
	}
}
			

Private Data allows a PBX or a switch (i.e., Communication Manager) to extend the base set of TSAPI capabilities. The CSTA specification allows exchanging additional information using Private Data for using the extended features provided by the vendor (e.g.. Avaya). This additional information could be part of either a CSTA request or a response.

A Private Data Version (PDV) defines a fixed set of these capabilities. More specifically, PDV defines a set of escape services and private event parameters for CSTA events. Chapter 5 of Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, DocID: 02-300544, release 4.2 May 2008 contains more information on this which will enable application developers to know exactly which services and private data items are available for a specific PDV.

In order to use these Private Data capabilities, a TSAPI application needs to negotiate PDV with AE Services TSAPI service during initialization. A TSAPI application can provide a range of acceptable Private Data Versions when requesting a new TSAPI session using the acsOpenStream API. Having the ability to negotiate a specific PDV or range of PDV ensures that an application written for an earlier release of the TSAPI SDK will continue to operate with newer AE Services releases.

The different Private Data Versions available are:

TSAPI Release Private Data Versions Supported
Avaya Computer Telephony PDV 2 through 6
Application Enablement Services 3.0 PDV 2 through 6
Application Enablement Services 3.1 PDV 2 through 7
Application Enablement Services 4.0 PDV 2 through 7
Application Enablement Services 4.1 PDV 2 through 8
Application Enablement Services 4.2 PDV 2 through 8
Note: Information about Private Data Versions supported for subsequent releases of the AE Services server can be found using the Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference.

Private Data Version is negotiated when an application opens a new TSAPI session with the TSAPI service using the acsOpenStream method. To request a specific version, or range of versions (i.e., providing a range of 3 - 8) of Private Data, an application allocates buffer space for working with Private Data. The application is required to use a special function (attMakeVersionString) to convert the version string into the format required by the acsOpenStream function. The application must then pass Private Data Version negotiation information in the Private Data parameter of the acsOpenStream method as shown in the sample code snippet below.

When a TSAPI application specifies a range of private data versions for negotiation, the TSAPI service will select the highest supported version (from the provided range) and return the selected version to the application. The negotiated version of Private Data can then be obtained from the ACSOpenStreamConfEvent event.

The following code snippet shows how to request the desired PDV for Avaya's implementation of TSAPI services.

PrivateData_t privateData;	// The application uses this parameter to provide a
 				// pointer to a data structure that contains any 
				// implementation-specific initialization.

/* Define variables to hold Stream handle */
ACSHandle_t acsHandle;

char * loginID;		// login id of the user requesting access to the
             		// advertised TSAPI service.

char * appname = "TSAPI APP";	// The application provides a pointer to a
				// null terminated string of maximum size
				// ACS_MAX_APPNAME. This string contains an
				// application name.

char * passwd;		// Password of the user given in loginID

char * version;		// version say  "TS2", An application uses this
			// parameter to specify the TSAPI version.

ServerID_t advertisedName;	// The application provides a null-
				// terminated string of maximum size
				// ACS_MAX_SERVICEID. This string
				// contains the name of an
				// advertised service (in ASCII format).

strcpy((char*) advertisedName,  "AVAYA#SWITCH#CSTA#SERVERNAME");

//PrivateData.vendor: should be set to 'version' as follows
strcpy(privateData.vendor,"VERSION");

// privateData.data: should be set to a one byte discriminator
// PRIVATE_DATA_ENCODING followed by an ASCII string identifying the version 
// of the private data 

privateData.data[0]=PRIVATE_DATA_ENCODING;

// A special function is used to convert version string into the format 
// required by the acsOpenStream function.

// The application can send a range (say "3-8") which specifies that 
// the application is willing to work with the provided range of private data
// versions. The AE Services server picks the highest version it can support
// and returns that to the application in the ACSOpenStreamConfEvent.

if (attMakeVersionString("3-8", &privateData.data[1]) > 0)
{
	// Length of privateData should be set to total length of 
	// privateData.data
	// Additional 2 bytes are added to the length of privateData.data[1]
	// for the following reasons:
	// One byte needed for leading discriminator and 
	// one byte for trailing NULL.
 
	privateData.length=strlen(&privateData.data[1])+ 2;
}
else
{
	// If the attMakeVersionString fails, set the privateData.length to 0
	// Note that private data will not be available to the application
	// for using the extended features of private data version.
	privateData.length = 0;
	// handle error 
	return ; // assuming application needs to use the extended features
}

RetCode_t rc= acsOpenStream(&acsHandle,
				 APP_GEN_ID,		// application wants control
							// over setting invoke IDs
				 (InvokeID_t)0,		// (arbitrary) app sends '0' as
							// the Invoke ID
				 ST_CSTA,		// required parameter
				 &advertisedName,	// TLINK name such as
 							// "AVAYA#SWITCH1#CSTA#
							// SERVERNAME1"
				(LoginID_t *)loginID,	// authentication login
				(Passwd_t *)passwd,	// and password
				(AppName_t *)appname,
				 ACS_LEVEL1,		// required parameter
				 (Version_t *)version,	// reqd parameter set to
							// "TS2"
				 (WORD)0,		// send queue size
				 (WORD)5,		// send extra bufs
				 (WORD)50,		// receive queue size
				 (WORD)5,		// receive extra bufs
				 (PrivateData_t*)&privateData 	// buffer of
			 					// private data
				 );

// Note that the Open Stream confirmation event acsOpenStreamConfEvent  
// contains the actual private data version negotiated and assigned to this
// stream.
		
Note: The TSAPI service checks whether the requested version is supported. If the requested private data version(s) is not supported, then the AE Services TSAPI service does not send any private data information in the acsOpenStreamConfEvent. For further information on this, refer to the FAQ document available at http://www.avaya.com/devconnect -> FAQs -> AE Services TSAPI FAQ -> How can a TSAPI application check whether the Private Data Version requested by the application is correctly negotiated with AE Services server's TSAPI service?

For more information on the various features of the TSAPI Service that can be accessed using Private Data, refer to the section titled Requesting private data in Chapter 5: Avaya TSAPI Service Private Data in the document titled Avaya MultiVantage® Application Enablement Services TSAPI for Avaya Communication Manager Programmer's Reference, 02-300544, Release 4.2, May 2008, Issue 4.

Universal Call Identifier (UCID) is a unique call identifier that can be transported between PBXs across ISDN, H.323 and SIP based trunked networks. UCID is a random number generated by the first PBX (e.g. Communication Manager) handling the call when the PBX is provisioned for UCID and the call has no UCID value. As represented by TSAPI, a valid UCID is a null-terminated ASCII character string. The UCID can be obtained from various CSTA unsolicited events such as Delivered, Established, etc., or from CSTA confirmation events such as the confirmation event for the Make Call service, etc.

UCID generation on Communication Manager needs to be specifically enabled on the system, and is obtained in TSAPI as private data information in the events and confirmation messages. To learn about the settings required on Communication Manager to utilize UCID, refer to the FAQ document "What settings are required on Communication Manager to receive Universal Call Identification (UCID) information in events?", available at http://www.avaya.com/devconnect -> FAQs -> AE Services TSAPI FAQ.

The following C++ code snippet demonstrates how to extract UCID from the Delivered Event:

// <summary>
// Invoke this method to process Unsolicited events. To prepare input
// parameters for this method, call one of the two methods 
// i.e. cstaGetEventPoll() or cstaGetEventBlock() to retrieve event and
// private data information. Call this method when the 
// cstaEvent.eventHeader.eventClass is CSTAUNSOLICITED.
// </summary>
// <param name="cstaEvent"> Pointer to CSTAEvent_t object that contains 
// event's information.</param>
// <param name="privateData"> Pointer to ATTPrivateData_t object that 
// contains private data information.</param>

void HandleCSTAUnsolicitedEvent(CSTAEvent_t* cstaEvent, ATTPrivateData_t* privateData)


{
 // Check for event type.
 switch(cstaEvent->eventHeader.eventType)
 {
	case CSTA_DELIVERED:
	{  
		// Delivered event received
		cout << " Incoming call detected" << endl;
		// Assuming the private data was negotiated during opening of ACS
 		//Stream
		// check the privateData length
		if ( privateData->length > 0 ) // privateData present, let's decode
		{
			// Event buffer that will contain the decoded 
			// private data information.
			ATTEvent_t attEvent;
			// Decode the private Data received.
			// Check to ensure that the private data
			// is successfully decoded.
			if ( attPrivateData(privateData, &attEvent) == ACSPOSITIVE_ACK )
			{
				// checking the event type
				if ( attEvent.eventType == ATT_DELIVERED )
				{
					// extract the Universal Call Identifier (UCID)
					char* UCID = attEvent.u.deliveredEvent.ucid;
					cout << " The UCID is: " << UCID;
				} // End of if
			} // End of if
			else
			{
				// Error while decoding the private data.
				// handle error here.
			}
		}// End of outer if
		else
		{
			// The event does not contain 
			// the private Data.
		}
		break;
	}// End of case
	// Application can add other cases here for processing other events as 
	// needed.
	}// End of switch
}// End of method

Licensing

GENERIC_SUBSCRIBED_RESOURCE_AVAILABILITY(41) generally means that you do not have a valid available license to perform the operation that you attempted. See the ?What kind of licensing do I need to use TSAPI on AE Services?? FAQ for further information.

The TSAPI basic license is on number of stations monitored and/or controlled. If the application performs call control on a station that is NOT already monitored, then an additional license would be needed during the call control operation. For two separate TSAPI client applications monitoring the same station through the same AE Services, only one license is needed. Single Step Conference will consume a TSAPI Basic User License for the duration that the added party remains in a call subsequent to being added by Single Step Conference, regardless of there already being a monitor on that extension.

The error message you have encountered is a generic message indicating the requested service has not been subscribed to. Check your Communication Manager System-parameters customer-options form, and make sure either the ASAI Link Core Capabilities or the Computer Telephony Adjunct Links is enabled.

The class A CT license corresponds to the basic level, and is associated with the ASAI Link Core Capabilities customer option. The class B CT license corresponds to the advanced level, and is associated with the Computer Telephony Adjunct Links customer option.

In a Single Step Conference call, if one party drops out, a TSAPI license remains actively assigned to the call, and each active call consumes a license. This leads to a high license usage.

If a regular conference call is used to build the three way call before the monitored party drops out, a TSAPI license does remain with the call, thus only one license per monitored party is consumed.

Yes. For a Single Step Conference in TSAPI, a license will be needed for monitoring the party that is added to the conference. Additional TSAPI licenses may already be in use if the controlling device is being monitored, or TSAPI makeCall was used to establish some other portion of the call. Single Step Conference can not be used unless TSAPI is monitoring the controlling station, or makeCall was used to establish the call. Typically, a SSC scenario requires two TSAPI basic licenses. If additional SSC requests are issued to add more parties to the call, each added party will consume an additional TSAPI basic license.

A TSAPI Advanced User License is needed if the application wants to use any of the following features:

  • Adjunct Routing (RouteSelect, RouteSelectInv)
  • Answer Machine Detection
  • Selective Listening (Hold and Retrieve)
  • Switch Classified Outbound Calls (MakePredictiveCall)
  • ISDN Redirecting Number
  • Phantom Calls
  • CTI Stations

One TSAPI Advanced License is required for each Communication Manager that the AE Services uses to perform any of these features. There are three types of TSAPI Advanced License. The type required depends of the platform upon which the Communication Manager is running:

Platform License
S88xx VALUE_AES_AEC_LARGE_ADVANCED
S87xx VALUE_AES_AEC_LARGE_ADVANCED
S85xx VALUE_AES_AEC_MEDIUM_ADVANCED
S84xx VALUE_AES_AEC_SMALL_ADVANCED
S83xx VALUE_AES_AEC_SMALL_ADVANCED
Midsized Business Template
(MBT)
VALUE_AES_AEC_MEDIUM_ADVANCED

See also the "TSAPI Service (including JTAPI) licensing" section of "Avaya MultiVantage Application Enablement Services Overview" 02-300360 Release 4.2 May 2008 Issue 5

The TSAPI acquired licenses will get released automatically the moment TSAPI is no longer involved in the task. For simple scenarios like a CSTAMakeCall, the 'task' ends when the TSAPI party involved in the call is no longer involved in the call. In this case, the license will get released once the call has ended. For complex scenarios like Single Step Conference (SSC), the 'task' ends only when all the parties disconnect from the Single Step Conference Call. In SSC the license goes with the call and is released only after all the parties disconnect from the call.

When 'cstaMonitorDevice' is used to monitor the device, then the license is acquired when the application initiates a monitor on a specific device and will not be released until the application does a 'cstaMonitorStop' on the same device. If multiple applications monitor a common device, the license is acquired when the first application does the monitorDevice and released when the last application releases the monitor. If there are active TSAPI calls in progress when the MonitorStop is done, the license is not released until the conditions in the first paragraph are met.

There is no license known as a Transient license. Transient license is a term used for a TSAPI license, which is consumed by the AE Services server for a short duration and then released. For example, when a party is added to a conference, an additional TSAPI license is consumed for the duration that the party is involved in the conference. Once this added party drops out of the conference, the additional TSAPI license is released. Another example of a Transient license could be a TSAPI license used for the AgentState query.

The TSAPI Basic User license is often referred to as either an "agent-based license" or a "station based license". It is intended for applications that wish to monitor a call or a station. There are several TSAPI functions that require a TSAPI Basic User license. This license resides on the AE Services server.

The table below shows the TSAPI functions included in AE Services Release 3.X and later), which consumes a TSAPI Basic User license.

Basic TSAPI Functions License Required (AE Services Version)
cstaAlternateCall
cstaAnswerCall
cstaChangeMonitorFilter
cstaClearCall
cstaClearConnection
cstaConferenceCall
cstaConsultationCall
cstaDeflectCall
cstaHoldCall
cstaMakeCall
cstaMonitorCall
cstaMonitorCallsViaDevice
cstaMonitorDevice
cstaMonitorStop
cstaPickupCall
cstaGroupPickupCall
cstaQueryAgentState
cstaQueryDeviceInfo
cstaQueryDoNotDisturb
cstaQueryForwarding
cstaQueryMsgWaitingInd
cstaReconnectCall
cstaRetrieveCall
cstaSetAgentState
cstaSetDoNotDisturb
cstaSetForwarding
cstaSetMsgWaitingInd
cstaTransferCall
TSAPI Simultaneous Users (3.x and later)

The following table shows the TSAPI function introduced in AE Services version 4.1 and the corresponding TSAPI license required for this function.

Basic TSAPI Function License Required (AE Services Version)
cstaQueryLastNumber TSAPI Simultaneous Users (4.1 and later)

There are some private data encoding functions that are used along with the cstaEscapeService() function. These private data encoding functions are included in AE Services Release 3.X and later and consume a Basic TSAPI User License, as shown in the following table.

Private Data Encoding Functions License Required (AE Services Version)
attSetAdviceOfCharge
attSetBillRate
attSingleStepConferenceCall
attQueryStationStatus
attQueryAcdSplit
attQueryAgentLogin
attQueryAgentState
attQueryCallClassifier
attQueryDeviceName
attQueryTimeOfDay
attQueryTrunkGroup
attQueryUCID
attSendDTMFTone
TSAPI Simultaneous Users (3.x and later)
The following table shows the private data encoding function introduced in AE Services version 4.1 onwards and the corresponding TSAPI license required for this function.

Private Data Encoding Function License Required (AE Services Version)
attSingleStepTransferCall TSAPI Simultaneous Users (4.1 and later)

The TSAPI Advanced User license is intended for the applications that access TSAPI advanced features such as launch calls (predictive dialing applications) or route calls. In AE Services release 3.0 the TSAPI Advanced User license is termed as TSAPI Simultaneous Advanced Users license. AE Services release 3.1 onwards the TSAPI Advanced User license name is changed to AES ADVANCED SMALL SWITCH (VALUE_AEC_SMALL_ADVANCED), AES ADVANCED MEDIUM SWITCH (VALUE_AEC_MEDIUM_ADVANCED), and AES ADVANCED LARGE SWITCH (VALUE_AEC_LARGE_ADVANCED) licenses. These licenses categories are based on the switch size. Either of these licenses or the TSAPI Simultaneous Advanced Users license is required for TSAPI Advanced functions. There are several TSAPI Advanced functions, as listed in the following table, which require a TSAPI Advanced User license in addition to TSAPI Basic User licenses. This license resides on the AE Services server.

TSAPI Advanced Functions License Required (AE Services Version)
cstaMakePredictiveCall
cstaRouteSelect
cstaRouteSelectInv
cstaRouteRegisterCancel
cstaRouteRegisterReq
cstaRouteEndInv
cstaRouteEnd
TSAPI Simultaneous Advanced Users (3.0) or
AES ADVANCED SMALL SWITCH (3.1 and later) or
AES ADVANCED MEDIUM SWITCH (3.1 and later) or
AES ADVANCED LARGE SWITCH (3.1 and later)

There are couple of private data encoding functions that are used along with cstaEscapeService() function which utilizes a TSAPI Advanced User License as shown in the table below:

Private Data Encoding Functions License Required (AE Services Version)
attSelectiveListeningHold
attSelectiveListeningRetrieve
TSAPI Simultaneous Advanced Users (3.0) or
AES ADVANCED SMALL SWITCH (3.1 and later) or
AES ADVANCED MEDIUM SWITCH (3.1 and later) or
AES ADVANCED LARGE SWITCH (3.1 and later)

For more information on the licenses currently installed on the AE Services server, refer to the FAQ titled "How can the availability of TSAPI or DMCC licenses be confirmed?" available on http://www.avaya.com/devconnect.

Other

First set up PrivateData structure using attSendDTMFToneExt() and then use cstaEscapeService() to send the request to the TSAPI Service.

Sample code:

// return codes
static RetCode_t cstaRC = 0;
static RetCode_t pdRC = 0;

ATTPrivateData_t PrivateData;
short toneDuration;
short pauseDuration;
ConnectionID_t sender;
char tones[ATT_MAX_TONES];
// set the toneDuration here
// set the pauseDuration here
// set the sender here
// set the tones here

/* encode the private data structure */
pdRC = attSendDTMFToneExt(&PrivateData, &sender, NULL, tones, toneDuration, pauseDuration);

if (pdRC == 0)
{
cstaRC = cstaEscapeService(acsHandle, invoke_id, (PrivateData_t *)&PrivateData);
}

cstaMonitorCall() is used to monitor a call from cradle-to-grave. Consider the following scenario:

Extension 40010 calls 40011. The callID for this call is 1891. cstaMonitorCall() is then used to monitor callID 1891. 40010 places the call on hold. A CSTAHeldEvent is reported. 40010 the places a new call to 40012. The callID for this call is 1892. 40010 then transfers the original call (callID=1891) to the new call (callID=1892). When this happens a CSTACallClearedEvent will be reported followed by a CSTATransferredEvent. A CSTAMonitorEndedEvent will not be reported. Inside of the CSTATransferredEvent the primaryOldCall structure will contain a callID=1891 and the secondaryOldCall structure will contain a callID=1892. The CSTAMonitorEndedEvent does not get reported because the call is still ?alive?. It has merely been transferred and has a new callID (1892). Consequently, events will now be reported on callID 1892. The CSTAMonitorEndedEvent will only be reported when the call is completely finished. I.e. if the call gets conferenced or transferred again, and a new callID is assigned, events will be reported on the new callID. Only when all parties on the call have dropped will the CSTAMonitorEndedEvent be reported.

Chapter 4 TSAPI Configuration and Settings in the "Avaya Multi-Vantage Application Enablement Services Administration and Maintenance Guide Release 4.0", document 02-300357 issue 6 dated Feb 2007 (http://support.avaya.com/elmodocs2/AES/4.0/02_300357_6.pdf) covers this configuration information. Note that the TSAPI clients use the Tlink Name to communicate with the server, and the Tlink Name will be unique for each CM connection as it uses the name of the switch connection as part of its name.