Cisco Unified Communication Tools

CUPI For Users .NET Wrapper Library

Version   1.0.4 BETA VERSION - this will be an ongoing project for some time as objects and capabilities are added to the library.  Feedback and contributions are more than welcome.
Last Update   10/12/2012
Statistics   Requires Visual Studio 2010, 2012 or MonoDevelop (for Mac/Linux) with the .NET 4.0 framework and a Connection server capable of serving up CUPI functionality.  The library was built against Connection 8.5, however most functions will work for older versions as well. 
Compatibility   Unity Connection 8.5.1 or later for all functionality.
Support   NOT TAC supported
Related CUPI For Users Java Wrapper Library provides access to user settings and messages for Java applications.

Connection Notification SDK for .NET provides access to getting events on mailbox status updates at the server level

REST for Admins .NET SDK. wraps much of the administrator API (CUPI) interface, much of the CUMI (for messages) and CUTI (for using the phone as a recording device) is also included. 

CUPI For Users is designed to allow for applications that need to get at user's voice mail settings (greetings, voice names, private lists, transfer options) and voice messages using the credentials of an individual user (i.e. the user authenticates as themselves). 

This library is the one used to develop the Connection CoPilot iPhone/iPad application and will work with Mono on Linux, Mac, iOS and Android projects as well as your Windows desktop applications in Visual Studio - it contains no platform specific references in it.

Training videos:

Getting started with the Connection CUPI For Users:  Adding the library to your project, attaching to Connection, getting version information, fetching user, greeting, private list and other data as well as reviewing messages. CUPI For Users .NET library intro - 45 Minutes
Using Fiddler for viewing HTTP traffic: Quick intro to using Fiddler to watch HTTP/S traffice going into and out of your development platform so you can see what's happening with the various Connection REST interfaces. Using Fiddler - 6 minutes
Building an iPhone Application in C# using the CUPI for Users.NET wrapper and MonoTouch.  Informal walk through showing how I build the ConnectionCoPiolot iPhone applicaiton using the .NET wrapper library with MonoTouch for iOS. CUPI on iPhone with Mono - 60 minutes

The library itself can be fetched using a SubVersion client pointed to the public repository here:

https://jlindborg.dvrdns.org/svn/CSharpStuff/CUPIClient

The read-only login is "RESTUser" and the password is "cisco". 

The repository includes both the ConnectionCUPIClientFunctions library itself as well as a small CUPIClientCLITest application used as a test harness as well as the unit tests used during development.  The ConnectionCUPIClientFunctions project is all you need to add to your C# project in Windows, Linux, Mac or iOS project to leverage it.

Usage Samples

The following are some highlights of the types of things you can do with the CUPI for Users wrapper library - the project code has more extensive examples in the CLI sample program and the unit tests included with it.

NOTE: Error handling and logging have been stripped out of these examples to keep the code clear and simple.  Copy and paste these into a production application at your peril!

Logging into Connection

 oServer = new ConnectionServer("192.168.0.198", "jlindborg", "ecsbulab");
Console.WriteLine("Logged into: " + oServer.ToString());
if (oServer.Version.IsVersionAtLeast(8,6,2,0)==false)
{
    Console.WriteLine("Version of Connection={0} and 8.6.2 or later is required",oServer.Version);
}

Getting Logged In User Info

  User oUser = new User(oServer);

//dumps out the user alias, display name and primary extension
Console.WriteLine(oUser.ToString());

//dumps out all properties on the user object
Console.WriteLine(oUser.DumpAllProps());

Resetting User Pin

res = User.ResetPin(oServer,"112233");

Getting User Mailbox Info

 //get mailbox information (size, limits, mounted etc...)
MailboxInfo oMailbox = new MailboxInfo(oServer);
Console.WriteLine(oMailbox.DumpAllProps());

Show Messages

 List<UserMessage> oMessages;

//get all unread voice messages (up to 20 at a time) sorted by newest messages first.
WebCallResult res = UserMessage.GetMessages(oServer, out oMessages, 1, 20,
        MessageSortOrder.NEWEST_FIRST,MessageFilter.Type_Voice | MessageFilter.Read_False);

//write out message info for each one - includes subject, sender and time sent
if (res.Success)
{
    foreach (UserMessage oTempMsg in oMessages)
    {
        Console.WriteLine(oTempMsg.ToString());
    }
}

Showing All Alternate Extensions

 List<AlternateExtension> oAlternateExtensions;

res = AlternateExtension.GetAlternateExtensions(oServer, out oAlternateExtensions);

//output all alternate extensions - what's returned will depend on the user's COS
//settings - admin added alternate extensions may or may not be included.

if (res.Success)
{
    foreach (AlternateExtension oTempExt in oAlternateExtensions)
    {
        Console.WriteLine(oTempExt.ToString());
    }
}

Adding and Removing an Alternate Extension

 //Adding an alternate extension can be restricted by the user's class of service so expect that this
//call can fail.

AlternateExtension oAltExt;
res = AlternateExtension.AddAlternateExtension(oServer, "1234", out oAltExt);

if (res.Success)
{
    Console.WriteLine(oAltExt.DumpAllProps());

    //delete the alternate extension you just added.
    res = oAltExt.Delete();
}

Showing Greetings

 //get all greetings - this should always get all 7 greetings
List<Greeting> oGreetings;
res = Greeting.GetGreetings(oServer, out oGreetings);

foreach (Greeting oTempGreeting in oGreetings)
{
    //outputs the greeting type, if its enabled and what it's set to play
    Console.WriteLine(oTempGreeting.ToString());
}

Enabling and Disabling a Greeting

 //get just the alternate greeting
Greeting oGreeting;
res = Greeting.GetGreeting(oServer, GreetingTypes.Alternate.ToString(), out oGreeting);

//this is how you would update the enabled status of the greeting. This enables the
//alternate greeting for 24 hours
res=oGreeting.UpdateGreetingEnabledStatus(true, DateTime.Now.AddDays(1));

//This disables the greeting. If you try this on the standard or error greetings it will
//fail since disabling those greetings is illegal

res = oGreeting.UpdateGreetingEnabledStatus(false);

Getting Greeting Stream Files from a Greeting

 //get just the alternate greeting
Greeting oGreeting;
res = Greeting.GetGreeting(oServer, GreetingTypes.Alternate.ToString(), out oGreeting);

//get the greeting streams defined for the alternate greeting
List<GreetingStreamFile> oStreamFiles;
oStreamFiles = oGreeting.GetGreetingStreamFiles();

//if there are no custom recordings in any language for this greeting the stream files returned
//will be null
if (oStreamFiles != null)
{
    Console.WriteLine(oStreamFiles.Count.ToString());

    //for each language wav file found for the greeting, save it off as a uniquely
    //names wav file using a new GUID
    foreach (GreetingStreamFile oStream in oStreamFiles)
    {
        res=oStream.GetGreetingWAVFile(string.Format(@"c:\tempfolder\{0}.wav", Guid.NewGuid()));
    }
}

Updating a Greeting for a User from a Local WAV File

 //get just the alternate greeting
Greeting oGreeting;
res = Greeting.GetGreeting(oServer, GreetingTypes.Alternate.ToString(), out oGreeting);

//you can pass the language code directly as 1033 (for US English) or you can use the
//LanguageCodes class and cast it to an int to make your code a little more readable

res=oGreeting.SetGreetingWavFile((int) LanguageCodes.EnglishUnitedStates, @"c:\MyNewGreeting.wav");

Using the Phone to Record a Greeting

 //use telephone as media device - establish a connection to extension 1003
PhoneRecording oPhone;
oPhone = new PhoneRecording(oServer,"1003");

//record a new stream
res = oPhone.RecordStreamFile();

//play the stream we just recorded for confirmation
res=oPhone.PlayStreamFile();

//get just the off hours greeting
Greeting oOffHoursGreeting;
res = Greeting.GetGreeting(oServer, GreetingTypes.OffHours.ToString(), out oOffHoursGreeting);

//set it's US English recording to the recording we just made
res=oOffHoursGreeting.SetGreetingRecordingToStreamFile((int)LanguageCodes.EnglishUnitedStates,
                oPhone.RecordingResourceId);

Showing Transfer Options

 //get all the user's transfer option
List<TransferOption> oTransferOptions;
res = TransferOption.GetTransferOptions(oServer, out oTransferOptions);

foreach (TransferOption oTempOption in oTransferOptions)
{
    //outputs the transfer type, if its enabled and what it's action is
    Console.WriteLine(oTempOption.ToString());
}

Editing Transfer Options

 //get just the alternate transfer option
TransferOption oAltOption;
res = TransferOption.GetTransferOption(oServer, TransferOptionTypes.Alternate.ToString(), out oAltOption);

//update the transfer option to be enabled indefinitely.
oAltOption.UpdateTransferOptionEnabledStatus(true);

//set the transfer option to ring the phone for x1234 5 times and not play the "please wait while
//I transfer your call" prompt.

oAltOption.Extension = "1234";
oAltOption.PlayTransferPrompt = false;
oAltOption.TransferRings = 5;
oAltOption.Action = (int)TransferActionTypes.Transfer;

//apply the changes to the option
res = oAltOption.Update();

Showing Private Lists for a User

 //get all the private lists for the user
List<PrivateList> oLists;
res = PrivateList.GetPrivateLists(oServer, out oLists);

foreach (PrivateList oTempList in oLists)
{
    //outputs the display name, ID and alias of the list
    Console.WriteLine(oTempList.ToString());

    //get all mebers of the list and display them indented
    List<PrivateListMember> oMembers;
    res=oTempList.GetMembersList(out oMembers);

    foreach (PrivateListMember oTempMember in oMembers)
    {
        //outputs the member name, alias and type (subscriber, list, contact)
        Console.WriteLine("--->" + oTempMember.ToString());
    }
}

Adding and Removing a Private List for a User

PrivateList oNewList;

//create a new private list in next available slot called "Test Add List"
res=PrivateList.AddPrivateList(oServer, "Test Add List", 0,out oNewList);

//removing the list is done like this
res = oNewList.Delete();

Adding Members to a Private List

 //get list #3 - this assumes you know there is a list #3 to be fetched
PrivateList oList;
res = PrivateList.GetPrivateList(out oList, oServer, "", 3);

//find all the addressable targets that have names that start with "J"
//the search is not case sensitive and will always return all types (subscribers, public lists, contacts
//and private lists)

List<AddressableTarget> oTargets;
res = AddressableTarget.GetAddressableTargets(oServer, "name startswith J", out oTargets);

//add all subscribers and public lists that were returned from the search. It may also return contacts and
//private lists, we're ignoring those here.
foreach (AddressableTarget oTarget in oTargets)
{
    if (oTarget.Type.Equals(AdddressableTargetTypes.SUBSCRIBER.ToString()))
    {
        res=oList.AddMemberUser(oTarget.ObjectId);
    }
    else if (oTarget.Type.Equals(AdddressableTargetTypes.DISTRIBUTIONLIST.ToString()))
    {
        res=oList.AddMemberList(oTarget.ObjectId);
    }
}