Friday, May 23, 2008

Setting Presence using the UCMA

Using the UCMA there are actually 2 ways in setting the presence.

The first one found in the Microsoft samples is as an automaton. This means that you tell the OCS server that your presence won't change. This is usefull for creating bots. They are normally always online.

But what is your application isn't always online. What if you only want your bot to be online during business hours.

So I will focus on setting the presence not as an automaton.

First you have to register your end-point.

Let's define some constants. The real change here is "expireType". which is set to user and not endpoint!

Constansts

public const string CategoryPublicationContentType = "application/msrtc-category-publish+xml";
public const string ContainerMemberContentType = "application/msrtc-setcontainermembers+xml";

public const string PresenceBlobUser = "<publish xmlns=\"http://schemas.microsoft.com/2006/09/sip/rich-presence\"><publications uri=\"{0}\"><publication categoryName=\"state\" instance=\"0\" container=\"{1}\" version=\"{2}\" expireType=\"user\"><state xmlns=\"http://schemas.microsoft.com/2006/09/sip/state\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"aggregateState\"><availability>{3}</availability></state></publication></publications></publish>";

public const string ContainerMembership = "<setContainerMembers xmlns=\"http://schemas.microsoft.com/2006/09/sip/container-management\"><container id=\"{0}\" version=\"{1}\"><member action=\"add\" type=\"sameEnterprise\" /></container></setContainerMembers>";

public const int PresenceContainer = 7000;

public enum PresenceState
    {
        Online = 3500,
        DoNotDisturb = 9500,
        Offline = 18500
    }

 

Next is setting up the presence container.

public void SetupPresenceContainer()
        {
            SipEndpoint endpoint = _endPoint;

            if (endpoint != null)
            {
                ContentType contentType = new ContentType(Constants.ContainerMemberContentType);

                string ContainerACL = String.Format(Constants.ContainerMembership, Constants.PresenceContainer, _presenceContainerVersion);

                byte[] body = Encoding.UTF8.GetBytes(ContainerACL);
                SipServiceRequest request = new SipServiceRequest(endpoint, contentType, body);

                request.BeginService(SetupContainerCallback, request);
            }
        }

private void SetupContainerCallback(IAsyncResult ar)
        {
            SipServiceRequest request = ar.AsyncState as SipServiceRequest;
            try
            {
                request.EndService(ar);
            }
            catch (FailureResponseException e)
            {
                string s = e.ResponseData.GetMessageBodyString();
                s.IndexOf("curVersion");
                string s2 = s.Substring(s.IndexOf("curVersion") + 12, 10);
                string[] array = { "\"" };
                string[] s3 = s2.Split(array, 2, StringSplitOptions.None);
                _presenceContainerVersion = int.Parse(s3[0]);
                SetupPresenceContainer();
            }
            catch (RealTimeException )
            {
            }
        }

 

Now it's time to set our Presence

public void PublishPresenceState(PresenceState availability)
        {
             if (_endPoint != null)
            {
                int availabilityValue = (int)availability;
                ContentType contentType = new ContentType(Constants.CategoryPublicationContentType);
                string presenceBlob = String.Format(Constants.PresenceBlobUser, ConnectionSettings.Uri, Constants.PresenceContainer, _presenceVersion, availabilityValue);
                byte[] body = Encoding.UTF8.GetBytes(presenceBlob);
                SipServiceRequest request = new SipServiceRequest(_endPoint, contentType, body);
                request.BeginService(PublishPresenceStateCallback, request);
            }
        }

 

private void PublishPresenceStateCallback(IAsyncResult ar)
        {
            SipServiceRequest request = ar.AsyncState as SipServiceRequest;

            try
            {
                request.EndService(ar);
            }
            catch (PublishSubscribeException e)
            {
                // This exception is most likely due to a version conflict. Parsing the Response body
                // to retrieve the current version, and publish again.
                string s = e.ResponseData.GetMessageBodyString();
                s.IndexOf("curVersion");
                string s2 = s.Substring(s.IndexOf("curVersion") + 12, 10);
                string[] array = { "\"" };
                string[] s3 = s2.Split(array, 2, StringSplitOptions.None);
                _presenceVersion = int.Parse(s3[0]);
                PublishPresenceState(_presence);
            }

            catch (RealTimeException)
            {
             }
        }

 

For more information contact sip:marc.wetters@e-office.com

3 comments:

Unknown said...

Thanks for the post Marc,
I tried it but looks like the presence is not correctly set (i.e. when I try to retrieve it I don't get the same value I set).

Can you give me some more infos about the presence container?
Paolo

Unknown said...

Hi Marc,
What should '_presenceContainerVersion' be set to? And hence, what does '/setContainerMembers/container/@version' represent in the XML?
Thanks.

Marc Wetters said...

Hi Joe

_presenceContainerVersion can be initialy set to 1.
Each time you change the PresenceContainer Memeberschip the version is changed.

Hope this anwsers your question
Marc

working at e-office