Relationship metadata

The Devices Profile for Web Services isn’t exactly a Profile in all senses of the word.  Yes, it does select and constrain underlying specifications like SOAP and WS-Discovery, but it also does very un-profile things like define schema.

One of the things that it defines is Relationship Metadata, which gives devices a way to express how their many functions are organized.

First, a brief refresher on how a DPWS device is organized: every device has a Host service, which is responsible for WS-Discovery and serving up device-level metadata, and it has zero or more Hosted services, which do the things that you expect from a device: printing, scanner, toasting bread, etc.  The Relationship metadata is used to describe these services.

The Relationship section is divided into two parts: zero or one Host sections, and zero or more Hosted sections.  Each of these sections has exactly the same schema, even if it’s the Host section—because remember, the Host service is a service, too.  Those of you who like to see it in XML will appreciate this:

    <wsx:MetadataSection>
        [<dpws:Host>…</dpws:Host>]?
        [<dpws:Hosted>…</dpws:Hosted>]*
    </wsx:MetadataSection

Here’s the interesting point: devices may omit the Host entry in the metadata.  That doesn’t mean that the Host service doesn’t exist—clearly it does since it served up the metadata.  It’s just that the device doesn’t have anything to say in its metadata that you didn’t already know when you discovered the device.
The same is not quite true for Hosted services—they really do need to be included, because if they’re not included in metadata, they’re not really part of the Device (they’re just other services hosted on the same piece of plastic).

Lastly, there’s a weird rule that the device must include at least one of Host or Hosted metadata.  This is really only included because this entire metadata section is optional, so the statement is that if you include this metadata, you have to include something inside it.

Once that’s clear, the contents are fairly self-explanatory.
        <wsa:EndpointReference>…</wsa:EndpointReference>
        <dpws:Types>…</dpws:Types>
        <dpws:ServiceId>…</dpws:ServiceId>
         ...

EndpointReference is this particular service’s endpoint: for a Host service, this is the address advertised at the discovery layer (“urn:uuid:…”); a Hosted service is recommended to use a physical address (“https://...”).

Types are regular service types: Host services have to include dpws:Device, Hosted services include whatever they want.

ServiceId is a little difficult to understand at first—why do we need another ID if we already have the Endpoint Reference?  Consider the case of a printer with two print heads: one black/white laser head, and one color inkjet head (bear with me—it’s just an example).  One way to organize this device is to expose these print heads as different services.  If you’re using physical addressing for your services, your black/white service will have an ID of “https://192.168.0.1/PrintService0” and your color service will have an ID of “https://192.168.0.1/PrintService1”.  Let’s say a user configures his PC to automatically select the black/white service; and then the printer get a new IP address and the Endpoint References change.  How does the PC find the black/white service again?  It can do this with Service IDs, which remain constant even though the Endpoint References may change when IPs change.

So that’s what relationship metadata is all about.  It looks fairly intimidating (and the schema is complicated, as schema usually is) but the concepts are straightforward.