On this page....
Archives
<September 2008>
SunMonTueWedThuFriSat
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

Feed your aggregator (RSS 2.0)
Search
Categories
About

My LinkedIn profile

Powered by: newtelligence dasBlog 2.1.8102.813

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2012, Christian Bækdorf

Send mail to the author(s) E-mail



Sign In
# Sunday, September 21, 2008
| Main | DSL Tools and Visual Studio 2008 Isolate... »

In this small tutorial I will show how to create a simple UPnP hosted device containing a simple HelloWorld service using C# and the Windows UPnP framework.

Windows UPnP is available in Windows XP, Vista and 2008 Server, but not in Windows 2003 Server. If you want UPnP on Windows 2003, have a look at the Intel UPnP stack.

I will not explain the basic concepts of UPnP, so if you don’t feel familiar with basic UPnP concepts it might be at good idea to look at some of the documentation at UPNP.ORG or MSDN.

Intel has some great tools for working with UPnP and I will be using these during the tutorial, so it would a good idea to install then if you want to go through the steps. They can be downloaded from Intel’s website, pick Intel® Tools for UPnP Technologies (Build 2777) and the .NET 2.0 CLR edition.

Designing/specifying the service

First steps is to create a services description, this is just like an interface for the service – specifying methods, properties and events. This is done in an XML file, see paragraph 2.3 of UPnP Device Architecture 1.0 for a detailed description of the XML format.

For this example we will just create a simple “HelloWorld” service that can return a simple text message, so we will have a services description as shown below:

<?xml version="1.0" encoding="utf-8"?>

<scpd xmlns="urn:schemas-upnp-org:service-1-0">

  <specVersion>

      <major>1</major>

      <minor>0</minor>

  </specVersion>

  <actionList>

      <action>

        <name>HelloWorld</name>

        <argumentList>

            <argument>

              <name>message</name>

              <direction>out</direction>

              <retval />

              <relatedStateVariable>Message</relatedStateVariable>

            </argument>

        </argumentList>

      </action>

  </actionList>

  <serviceStateTable>

      <stateVariable sendEvents="no">

        <name>Message</name>

        <dataType>string</dataType>

      </stateVariable>

  </serviceStateTable>

</scpd>

Specifying this service could be done using any text editor or by using the Intel Service Author application which comes a part of the Intel tools for UPnP.

Designing/specifying the device

Next we need to create a device specification; this is a specification of the services that should be published and other meta-information related to the devices and services. This will also be represented by an XML file, see paragraph 2.1 of UPnP Device Architecture 1.0 and Creating a Device Description on MSDN for a detailed description of the XML format.

Sample device description:

<?xml version="1.0"?>

<root xmlns="urn:schemas-upnp-org:device-1-0">

  <specVersion>

    <major>1</major>

    <minor>0</minor>

  </specVersion>

  <device>

    <deviceType>urn:schemas-mycompany-net:device:MyDevice:1</deviceType>

    <presentationURL></presentationURL>

    <friendlyName>MyDevice</friendlyName>

    <manufacturer>My Company</manufacturer>

    <manufacturerURL>http://www.mycompany.net</manufacturerURL>

    <modelDescription>Just some sample stuff</modelDescription>

    <modelName>My Device X</modelName>

    <modelNumber>X</modelNumber>

    <modelURL>http://www.mycompany.net</modelURL>

    <serialNumber>0000001</serialNumber>

    <UDN>uuid:RootDevice</UDN>

    <UPC>00000-00001</UPC>

    <serviceList>

      <service>

        <serviceType>urn:schemas-mycompany-net:service:MyService:1</serviceType>

        <serviceId>urn:upnp-mycompany-net:MyService:1</serviceId>

        <controlURL></controlURL>

        <eventSubURL></eventSubURL>

        <SCPDURL>MyService.xml</SCPDURL>

      </service>

    </serviceList>

  </device>

</root>

where MyService.xml is containing the services description.

Creating an application to get the device up and running

To get the device up and running we need an executable application where we can implement the service and register the device with the Windows UPnP host. For this purpose I will use a standard C# Console application.

Add the device description and service description files to the console application, mark then as “Content” and “Copy if newer”.

It is necessary to disable the use of Visual Studio host process when debugging, otherwise the application will fail when debugging (some COM related issue).

Next we need to add some references to the UPnP COM type libraries ("upnpcont.exe" and "upnp.dll" typical found in “c:\windows\system32”) for the Windows UPnP framework.

Now we are ready to implement the service, this is done by adding a plain C# class:

    [ComVisible(true)]

    [ClassInterface(ClassInterfaceType.AutoDispatch)]

    public class MyService

    {

        private string m_Message;

 

        public string Message

        {

            get { return m_Message; }

            set { m_Message = value; }

        }

 

        public string HelloWorld()

        {

            return "Hello World, time is " +

                DateTime.Now.ToString();

        }

    }

The service class should match the service description; have the same methods and properties. It also needs to be COM visible and implement the COM IDispatch interface.

Next we need a device control class which acts as a factory for instantiating the service class. This class is also a plain C# deriving from the interface IUPnPDeviceControl.

    public class MyDeviceControl : IUPnPDeviceControl

    {

        private MyService m_Service;

 

        public object GetServiceObject(string bstrUDN, string bstrServiceId)

        {

            return m_Service;

        }

 

        public void Initialize(string bstrXMLDesc, string bstrDeviceIdentifier, string bstrInitString)

        {

            m_Service = new MyService();

        }

    }

Finally we need to fill out the Main method with the code for registering the device control class with the Windows UPnP framework. See Registering a Hosted Device With the Device Host on MSDN for more information for more information.

Note that we need to make a call to CoInitializeSecurity to get the COM Interorp to work. For details abort this see the downloadable code.

    static void Main(string[] args)

    {

        try

        {

            int result = Win32.CoInitializeSecurity(IntPtr.Zero, -1,

                IntPtr.Zero, IntPtr.Zero,

                Win32.RpcAuthnLevel.Default, Win32.RpcImpLevel.Impersonate,

                IntPtr.Zero, Win32.EoAuthnCap.None, IntPtr.Zero);

            if (result != 0)

            {

                Console.WriteLine("CoInitializeSecurity failed.");

                return;

            }

 

            string descDoc = File.ReadAllText("DeviceDescription.xml");

            object myDeviceControl = new MyDeviceControl();

 

            IUPnPRegistrar registrar = (IUPnPRegistrar)new UPnPRegistrarClass();

 

            string deviceId = registrar.RegisterRunningDevice(

                descDoc, myDeviceControl, "Init string...",

                Directory.GetCurrentDirectory(), 3200);

 

            Console.WriteLine("Ready, press any key to stop...");

            Console.ReadLine();

 

            registrar.UnregisterDevice(deviceId, 1);

        }

        catch (Exception ex)

        {

            Console.WriteLine(ex.ToString());

        }

    }

Testing the UPnP device and service

Now we can build and start the program

To test the UPnP device and service we will use Intel Device Spy for UPnP, this way we can test the HelloWorld method without having to implement a UPnP client.

If our new UPnP device is running, we should see it in the UPnP Device Spy with the name MyDevice and should be able to find the service and HelloWorld method. Try invoking the HelloWorld method by right-clicking it.

Downloadable code

You can download the sample code here: MyUPnP-Tutorial-01.zip (33,37 KB)

Sunday, September 21, 2008 11:53:09 AM (Romance Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [148]  |