Skype for Business – A Developer’s Guide : Part 4 – UCMA
I’ve put together a series of 4 short videos, aimed at developers who are coming to Skype for Business development for the first time and want to know what’s possible. The videos show some of what you can do with some of the APIs and SDKs Microsoft make available with Skype for Business.
In this video I cover UCMA, the Unified Communications Managed API, and use it to build an IVR system, complete with hold music, DTMF tones, and conferencing functionality!
Watch the whole series: Skype for Business: A Developer’s Guide
Hello, my name’s Tom Morgan. I write about Skype for Business development on my blog, thoughtstuff.co.uk. I’ve put together a short 4-part video series, designed for developers who are just getting started in Skype for Business development, or are curious about what’s possible.
There are 4 videos in the series. The first video covered the history of Skype for Business, showed some screenshots and listed different types of development tools. The second video looked at the Client SDK using a worked example to illustrate what’s possible. In the third video I looked at UCWA, the Unified Communications Web API, to build a simple chat experience.
In this final video I want to look at UCMA, the Unified Communications Managed API. I’m going to use this to show you how easy it is build an IVR using Skype for Business.
So, in case you don’t know, an IVR is the thing you get when you call a call centre and get put in a queue and you get told to press 1 to do this, press 2 to do that. Interactive Voice Response. Obviously, when you’ve got Skype for Business you can route your phone numbers and have a customer care number that is routed to a UCMA application and you can have that UCMA application take that and then deliver an IVR experience very very easy, and I’m going to show you exactly how to do that in this example that I have, using Visual Studio.
So, let’s make a start. What I have here is a really simple Console Application in Visual Studio and coming into the Main here what I’m doing is creating this new class LyncServer. What I’ve done for you is I’ve split various parts of the solution into different classes so you can see how they work, how they interplay, how the different sections hang together.
The first thing we’re going to look at is this LyncServer class. So, looking at this class, there’s a Start method, and really the first interesting thing here is setting up this Collaboration Platform and calling StartupAsync on it. Now, Collaboration Platform is part of the Microsoft RTC DLL, and that comes with the UCMA SDK. Looking here, it’s this DLL here, this Microsoft.Rtc.Collaboration one. And that gives you these objects here.
Now, the collaboration platform is really just the basis of UCMA, in which you start off with and on which things happen. With UCMA applications you can register when you set them up and create them, when you register them with the Skype for Business server you give them one or more endpoints. And endpoint is like a contact in your Skype for Business environment – it’s how your users might interact with that application and if you were setting it up to go a particular phone number, you would get a SIP address as part of that endpoint, and that’s your identifier to give to the server so that it knows when a call comes in on this number it needs to go through to this endpoint, and then this application. So, what I’m doing as part of the collaboration platform here, is I’m calling this RegisterForApplicationEndpointSettings method. Now, you can more than one endpoint in an application, we’ve only got one here but you could have more – you can imagine a situation in which you have an application which has many endpoints, each of which do different things. The method here takes this call back function, to be called whenever a new endpoint is discovered. So that’s probably a good place to go next.
So when the collaboration platform is set up, this will get called for the new endpoint, which you can see, and all I’m really doing here is, here I’m establishing it, so I’m really just setting it up and getting it going, but one thing I do that’s interesting is register for incoming calls. Now, if you remember from the introductory video, you have a conversation, and within a conversation you have multiple modalities, things like Instant Message, Audio/Video, Desktop Share, that kind of thing. And you can set up your application to deal with one or more of those different types of modalities, and you do that by registering different methods to be triggered for new incoming calls of that type. In this example I’m only registering for audio/video calls, and all I’m saying here is “register for audio video, and when it happens call this method here: OnIncomingCall”. So, at that point, that means that when everything is all set up and running any incoming calls will drop through to this method here. Now, because I want to keep the functionality separate among these different classes I’m not going to do anything here apart from raise this event back to the Main method. That’s where this comes in there, this event that I created. So, on this incoming call, what I’m doing here is…so, there’s a little dance you have to do with audio/video calls. The reason for that is that you’ve got the AudioVideo call, which is fine, and it’s got lots of useful information in it about the To and the From, the different servers it passed through, the different Properties of that call and all that kind of stuff, but the actual one thing we’re really interested in is what’s called the Flow. And the Flow is the actual content of that call. To give a similar example, in an Instant Message call the Flow is just the actual messages being sent between two or more people, the actual IMs, none of the other stuff, that’s all encapsulated in the Call object, it’s the Flow that’s the actual data. And it’s the same with the audio / video stuff, it’s the Flow that we’re really interested in. Now, the flow between people doesn’t get set up until the call gets accepted. So at this point we have an incoming call, but we haven’t actually accepted that call yet, it’s still ringing if you like. Because it might be that we don’t want to accept every single incoming call, there might be rules in place to reject or redirect, transfer or do something, so it’s not a given that the Flow is going to be set up. Now, we are accepting the call here, what we’re going to do just beforehand is register for an event to say “I am accepting this call, but tell me when the Flow starts to be set up”, then when you have the Flow object, subscribe to changes in its state. Because really, what we really care about is when the Flow is Active. So, as soon as the Flow is Active, which is done down here, as soon as there is an active Flow, get a handle on it and then I’m passing it over to this new class, the IVRMenu class over here and it’s going to call this really badly-named StartWithWelcome method. So, let’s drop into there now to see what’s happening.
So, we’ve got StartWithWelcome. So, we’ve got the flow. One of the things which every good IVR should have is speed synthesis, text to speech. That’s all built into UCMA, you don’t have to do any kind of magic to it, it’s really really easy, you just take the speech synthesizer, connect it here, and you attach it to your Flow. There’s a method called AttachFlow and you pass it the Flow, this is the Flow that’s come from the audio/video call. And, once you’ve done that you can create a new speech synthesizer and have it say whatever you want. This one here says “Welcome to NorDove” because it’s for a previous talk I did, what I might say is “Welcome to ThoughtStuff” if I’m creating an IVR for my blog, which is a bit weird, you might want it to say “Welcome to ThoughtStuff”. This is the bit that’s going to speak it, and the next thing I’m going to do is speak out the menu options, because every good IVR should have a menu, and the other thing you really want with IVRs is what’s called DTMF tones. DTMF tones are when you press the keypad on your phone and it makes the noise, so that the computer at the other end knows which key you pressed – those are DMTF tones. And you can attach and read tones in UCMA really easily as well with what’s called a Tone Controller, which is here, and again you attach it to the Flow, and just register for ToneReceived. So, this ToneReceived then forms the basis of the if..then..else part of the IVR, the switching part. So, come through to SpeakMenuOptions. Now, all I’m going to do is speak out some options. I’ve set up 3 different things to do, now they’re not particularly things you want to do in an IVR, but they do highlight 3 very different things you can do in UCMA that I think are worth pointing out. So I’m speaking these three things: 1 to hear the time, 2 to join a conference, or 3 to hear some music. Now, that’s fine, once that user presses one of those options, and again there’s nothing in here for dealing with if the user doesn’t press anything after a certain amount of time, or presses the wrong thing, or if they press a hash or start, or anything like that.
So, we’ve got ToneReceived, which is going to be triggered as soon as they press something. There’s an expectation in IVRs that as soon as you press something, whatever was talking stops. So if we were previously talking about the menu then we want to cancel doing that, and that’s the reason I’m now using SpeakAsync rather than Speak because I want it to start speaking but then I still want this to be able to work, to be able to operate and receive events.
So this is my switch statement for the three different cases. So let’s take case one first – speaking the time. Now, that’s really simple, it’s right there on the screen, it’s exactly as you’d expect it to be. The reason I’ve included it is the potential it gives you. Yes I’m just reading the time but this could be doing anything. Right now, this is really just .NET code that’s no different from doing a Console.Write, you’re doing a Synthesizer.Speak. So you could look up information from back-end systems, web-servers or a database, whatever it is. You could have the user type in their order number, look up a status, you can do whatever you want here, you don’t need to know very much about UCMA, you can just use your knowledge of .NET development to really create an amazing IVR, a custom IVR solution for your organisation. Because here, this is just .NET and it’s just speaking out text. There’s also voice recognition built into UCMA, which I’m not covering. It’s not that much more complicated, but it’s just an extra level of having to provide the kind of responses you’re expecting, so that UCMA has got a fighting chance of working out what it is that the user is saying.
I’m going to do case 3 next and then come back to case 2. So case 3 is playing music. Now, UCMA allows you to play music to your users, because that’s a key feature of IVRs – being able to play bad music to users. The way it does it is quite clever though, because what I’ve got here is a ContinuousMusicPlayer which is a class I wrote, up here. It’s a singleton class, which is interesting and I’ll come back to that in a minute. But what it does really, you create a WMA file source, it does have to be a WMA file, and you have to go through preparing it, but then you create a Player, set the source, and you start playing. What I’ve done here is I’ve attached a State Changed event which says, if it’s stopped just start it again. That means I get a continuous looping player of music. What I can do over in the IVR code now is get a handle to that player object, and attach that to the Flow, using the same AttachFlow method. What that will do is take that player and attach it to the flow, so that becomes what the user hears. Now, what’s kind of powerful about this is that one Player can be attached to many different calls, and that means that when you scale this out you’re not creating a Player per call, so you can handle really large volumes of calls really easily with a single player playing a single file, if you don’t mind that users get dropped in halfway through a looping file. Now sometimes you want to play a recorded file like an announcement or a special offer, or whatever it is in which case you would want to set up a new Player each time. But for cases where it’s just hold music you want to drop people into this is a really good way of achieving some performance improvement. So, that’s continuous music playing.
Finally, this thing about joining conferences. Now there were some bits and pieces as we’ve gone through this which I’ve missed out and I haven’t covered. One of them is back in LyncServer, it’s this CreateConference. And what I did, when the Lync Server started up is I did this it as well, what I’m doing is creating a conference in Skype for Business, and I’m joining the application into that conference. So I’m just starting up this conferencing space, currently has no-one in it. But then every time a user presses 2, what I’m doing is adding them into that conference and I’m just taking the Flow, actually I’m taking the parent Call object and I’m dropping them into the conference by transferring the user into the conference.What that means is that if 2 people phone up and both press 2, they will both be dropped into the conference and they’ll be able to talk to each other. So, it’s not really a thing you’d want to do with your IVRs, although I think that might be quite fun if they started doing that every now and again – but it shows you how easy is to spin up a conference, and it might be that you spin up a conference, you invite some subject matter experts into it, and then you drop the user into it. Or you drop the user into it based on other parameters, if you need to collaborate with them for something, or whatever it is, it’s actually really really easy to take incoming calls and move them around the system, even transferring them to different people, or transferring them conferences and them moving them around like that.
So that’s been a really quick run through about how you put together an IVR system. Hopefully it’s shown you that it’s not as complicated as it would first appear, as you would think it might be. And actually, a lot of the constructs are not complicated, and they make sense to .NET developers, Java developers or anyone, you don’t need to be massive subject matter experts. Something like an IVR solution, you can really make it customisable for your organisation, or for your particular scenario or situation, and you’ve got these extra things built in, like DTMF tones and speech synthesis which really make it quite powerful without too much effort.
So hopefully that’s been helpful. I encourage you look through the code yourself and try it out, and build on it. The code is all on GitHub, the address for the code is on the screen now. Also there is a link to a blog post which goes into this in a bit more detail, really what I’ve already said, it just covers with a bit more surrounding information. If you’re still interested in Skype for Business development this is the end of the series but there are plenty of other blog posts on my site, thoughtstuff.co.uk. You can also follow me on Twitter, I’m @tomorgan. Thank you very much for listening to this video, and if you’ve watched all the videos in the series, thank you very much for watching them all.