Imperia is the name I’ve given to my UPnP Control Point API that supports Windows Desktop, Windows Surface (WinRT) and Windows Phone 8. This project arose because I was interested in leveraging my C# skills on a Windows Phone 8 project, I setup a developer account at Microsoft and installed the Phone SDK as part of Visual Studio 2012 on a Windows 8 machine that I have.
After building some rudimentary little test projects and verifying that they ran and actually did something on a real physical phone I decided to play around with my Sonos music system and see if I could do something apparently easy – adjust the volume on a Sonos player using my Lumia 920.
I knew nothing about UPnP and certainly nothing about writing software for UPnP, I assumed that there was stuff in the .Net Framework for interacting with UPnP devices on a network and that writing a volume control app would be just a matter of working with the API and doing some trial and error work; how wrong I was!
There is no built in support for UPnP control on Windows Phone 8, Windows Surface or in fact Windows Desktop. There is an aging COM component that can be accessed from managed code but that component is closely bound to the conventional Windows platform running on Intel processors – that component simply cannot be used on ARM processors like those used on phones and tablets.
So after spending time exploring how UPnP actually works and scrutinizing the published standards documents I decided I’d create a simple class library that support basic device discovery and that I’d initially focus my efforts on Windows 8 desktop.
After studying the various specifications and creating a simple test console app, I was able to discover all devices on my home network and become aware of devices being added (switched on) to the network.
I enriched and tidied the test code and created a clean implementation of some SSDP support classes, SSDP incidentally stands for Simple Service Discovery Protocol. I then refactored my test project so that I had a simple test app resting upon my more formal SSDP layer and after running a few tests to make sure all was well decided to create a Surface and Phone 8 version of the test app – this is where I began to realize the challenges of writing code for multiple Windows platforms.
The .Net frameworks available for Desktop, Surface and Phone 8 are different, some classes that are present on one platform might be absent from another or even where classes are present on all platforms some methods might be available only one or two of the three platforms, this was a logistical challenge that soon became a core design issue for me.
After spending time assessing the scale of these differences and the overall scale of the challenge I decided to adopt a formal policy of insisting on the UPnP API exposing an identical looking and behaving set of classes irrespective of platform.
I created a single source repository and multiple projects – one for desktop, one for Surface and one for Phone. Each project simply links to this common source and each project has its own C# conditional compilation symbols allowing me to write platform specific implementations of methods wherever this became necessary. I therefore have a single Visual Studio solution with three projects defined in it and rebuilding this solution rebuilds the class library assemblies for each platform.
There were a lot of challenges and several important aspects of UPnP needed their own platform specific implementations in areas like the GUI dispatcher, Web IO, XML processing, SOAP and so on, these are all different across the platforms and so in these cases methods have been created that are identical for these platforms but which internally provide differing implementation code with conditional compilation symbols playing a key role.
I’ll be writing more about these challenges and the steps I took to address them in some future posts, but I’ve now reached a stage where a core UPnP framework has been created that offers identical syntax and semantics across all three platforms and support a great deal of control point functionality .
The goal I set has been achieved – its now possible to write specific controller code to a single API with that code being fully source code portable across all platforms only the GUI code differs allowing one to write MVVM controller apps for any UPnP device.
My experimental Sonos controller App runs on all three platforms and the source is fully portable with all platform specific implementation stuff “hidden” inside the UPnP layers – I can now easily control the volume, bass and treble and select various radio stations on both my phone and my surface only the View code differs.