This is the fourth article in the WSDAPI 101 series. You’ll learn the most by starting at the beginning, although it’s not required to understand the content in this article.
WSDAPI 101 Part 3 was all about that cool adapter layer that sits between your application and the underlying generic WSDAPI objects. So now that we know how that adapter layer works, it’s time to talk about the generic messaging components.
How are these interfaces organized?
Before we dive into specifics, it’s important to understand how the most important WSDAPI interfaces are organized.
This diagram illustrates the five top-level WSDAPI interfaces, and how they relate to messaging and discovery. So far, WSDAPI 101 has been focused almost entirely on the top row of objects: IWSDDeviceProxy, IWSDServiceProxy, and IWSDDeviceHost. The first two interfaces are what you use when you want to control a device (e.g., tell a webcam to take a picture) and the last is the interface you use to create a virtual device.
I haven’t touched on the second row at all, but I’ll note them briefly at the end of this post and will explain them in detail in another article.
One last point is that only two of these five interfaces have anything to do with generated code (IWSDServiceProxy and IWSDDeviceHost). Don’t take this to mean that you’ve only learned 40% of WSDAPI so far–instead, take it to mean that these two interfaces constitute the vast majority of all WSDAPI calls you’re likely to make. In reality, we’ve already covered the majority of concepts in the WSDAPI world.
We’ll go through the interfaces in the order they’re presented above.
Client-side control: IWSDDeviceProxy and IWSDServiceProxy
If you’re using WSDAPI, odds are good that you’re building a client-side control program. For these types of applications, the IWSDDeviceProxy and IWSDServiceProxy interfaces are the two WSDAPI objects you’ll use most.
IWSDDeviceProxy presents a client-side representation of the DPWS device to which you’re connecting. It has two purposes: 1) to allow callers to retrieve metadata that describes the device and its services, and 2) to generate IWSDServiceProxy objects.
IWSDServiceProxy is the client-side representation of an individual service on a DPWS device. The service proxy is what gets wrapped in generated code, and is responsible for performing the basic messaging to a service hosted on a device. As you can see in the diagram, you may spin off multiple service proxies for a given device, as that device may host multiple services.
Service-side control and discovery: IWSDDeviceHost
WSDAPI allows you to build devices and to host services. The only interface you need is IWSDDeviceHost–it hosts any service objects you create, publishes WS-Discovery on your behalf, and automatically responds to any metadata requests that come in. So if you have an IWSDDeviceHost, you do not need an IWSDiscoveryPublisher (nor do you have to devise a way to handle metadata).
Unlike generated code on the client side, you won’t ever have to deal directly with generated code on the device host side. The red squares in the diagram above are called stubs, and are used automatically by the device host to translate generic function calls into strongly typed service method calls. The only interaction you should ever have with these stubs is to register them with the device host using IWSDDeviceHost::RegisterPortType or with IWSDDeviceHost::AddDynamicService.
Client-side discovery: IWSDiscoveryProvider
IWSDiscoveryProvider is used to search for services on the network, and to listen as services arrive and leave the network. It can’t be used to get metadata (you need an IWSDDeviceProxy for that) nor can it be used to control services (you need IWSDServiceProxy). More on IWSDiscoveryProvider in a later article.
Service-side discovery: IWSDiscoveryPublisher
IWSDiscoveryPublisher gives you manual control to publish a service on a network, and to respond to queries from WS-Discovery clients. IWSDiscoveryPublisher doesn’t serve metadata for you, nor does it host any services. The IWSDDeviceHost has an IWSDiscoveryPublisher built in, so you don’t need to create one if you already have a WSDAPI device host. More on IWSDiscoveryPublisher in a later article.
One last note on object creation
You may be asking yourself, “this is great, but how do I create these objects?” Well, don’t fear–it’s really straightforward. In all cases, you can create the object with the appropriate WSDAPI factory function; in nearly all cases, these are of the form WSDCreate??? where ??? is the base object name, sans the interface prefix. So WSDCreateDeviceProxy will get you an IWSDDeviceProxy. The only exception is the IWSDServiceProxy, which can only be generated with IWSDDeviceProxy::GetServiceById and IWSDDeviceProxy::GetServiceByType.
Stay tuned for WSDAPI 101 Part 5, where I’ll describe the end-to-end flow for assembling an application on WSDAPI, from the WSDL, to the generated layer, and on to the actual application code!