UPnP(Universal Plug and Play) is a set of networking protocols promoted by the UPnP Forum. If you have no idea what it is, this article from Microsoft may help. It was written in 2001, which describes an intelligent home that is still attractive currently.
I will analysis the architecture of UPnP in this article.
1 The Brief Architecture
UPnP is composed of several steps, including discovery, description, control, eventing and presentation.
- Discovery: during this step, service providers (called 'devices') and service users (called 'control points') discover each other.
- Description: devices use XML to describe their information and services before being used.
- Control: control points use SOAP to control devices.
- Eventing: subscribers will be informed when devices' states change.
- Presentation: devices are able to use browsers to present themselves. (This won't be discussed in this article.)
Before analysing the first four steps, we have to know that step 0 of UPnP requires each device and control point in a network which enables multicast.
The multicast address 239.255.255.250:1900 is used by UPnP.
2 Discovery
Discovery can be done using SSDP, which runs over HTTP based on UDP.
When a new device joins in, it multicasts the following message:
NOTIFY * HTTP/1.1
Host:239.255.255.250:1900
Cache-control:max-age=1800
Location:http://192.168.0.1:49152/des.xml
Nt:upnp:rootdevice
Nts:ssdp:alive
Usn:uuid:de5d6118-bfcb-918e-0000-00001eccef34::upnp:rootdevice
Here,
- Host: MUST be
239.255.255.250:1900
. The multicast address and port are reserved for SSDP by IANA (Internet Assigned Numbers Authority). - Cache-control: The integer following
max-age=
specifies the number of seconds the advertisement is valid, which indicates that the device need to resend this notification before expiration. - Location: A URL to the UPnP description of the device.
- Nt: Notification Type.
- Nts: Notification Sub Type. Must be ssdp:alive.
- Usn: Unique Service Name, which identifies a unique instance of a device or service.
Similarly, a control point also multicasts a message when joining in:
M-SEARCH * HTTP/1.1
Host:239.255.255.250:1900
Man:"ssdp:discover"
Mx:5
ST:ssdp:rootdevice
- Man: MUST be
"ssdp:discover"
, the quotes here SHOULD be kept. - Mx: maximum wait time in seconds. MUST be greater than or equal to 1 and SHOULD be less than 5.
- ST: Search Target, the device that you want to search.
The response from a device is like:
HTTP/1.1 200 OK
Cache-control:max-age=1800
Ext:
Location:http://192.168.0.1:2345/xx.xml
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
ST:ST:urn:schemas-upnp-org:service:ContentDirectory:1
USN:uuid:60b2e186-b084-44af-ac09-1c64ea1bb364::urn:schemas-upnp-org:service:ContentDirectory:1
3 Description
Description is based on HTTP.
Many tags can be used to describe a device. You can get a complete list from UPnP Forum. Here is an example:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>1</minor>
</specVersion>
<device>
<deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType>
<friendlyName>Kitchen Lights</friendlyName>
<manufacturer>OpenedHand</manufacturer>
<modelName>Virtual Light</modelName>
<UDN>uuid:cc93d8e6-6b8b-4f60-87ca-228c36b5b0e8</UDN>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType>
<serviceId>urn:upnp-org:serviceId:SwitchPower:1</serviceId>
<SCPDURL>/SwitchPower1.xml</SCPDURL>
<controlURL>/SwitchPower/Control</controlURL>
<eventSubURL>/SwitchPower/Event</eventSubURL>
</service>
</serviceList>
</device>
</root>
specVersion
tag defines the architecture on which the device is implemented. So we only discuss the device tag:
- deviceType: UPnP device type, MUST be
"urn:schemas-upnp-org:device:deviceType:v"
. - friendlyName: short description for end user.
- manufacturer: manufacturer's name.
- modelName: model name.
- UDN: Unique Device Name, universally-unique identifier for the device.
- serviceList: contains services descibed in the following.
Each service contains:
- serviceType: UPnP service type.
- serviceId: service identifier.
- SCPDURL: URL for service description.
- controlURL: URL for control.
- eventSubURL: URL for eventing.
A service description is like this:
<?xml version="1.0" encoding="utf-8"?>
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
<specVersion>
<major>1</major>
<minor>1</minor>
</specVersion>
<actionList>
<action>
<name>SetTarget</name>
<argumentList>
<argument>
<name>NewTargetValue</name>
<relatedStateVariable>Target</relatedStateVariable>
<direction>in</direction>
</argument>
</argumentList>
</action>
<action>
<name>GetTarget</name>
<argumentList>
<argument>
<name>RetTargetValue</name>
<relatedStateVariable>Target</relatedStateVariable>
<direction>out</direction>
</argument>
</argumentList>
</action>
<action>
<name>GetStatus</name>
<argumentList>
<argument>
<name>ResultStatus</name>
<relatedStateVariable>Status</relatedStateVariable>
<direction>out</direction>
</argument>
</argumentList>
</action>
</actionList>
<serviceStateTable>
<stateVariable sendEvents="no">
<name>Target</name>
<dataType>boolean</dataType>
<defaultValue>0</defaultValue>
</stateVariable>
<stateVariable sendEvents="yes">
<name>Status</name>
<dataType>boolean</dataType>
<defaultValue>0</defaultValue>
</stateVariable>
</serviceStateTable>
</scpd>
actionList
contains actions. serviceStateTable
contains state variables.
Every action has a name
and a list of argument
s. Arguments also have a name
, a direction
(in
or out
for input or output arguments) and a related state variable. The state variable is used to determine the type of the argument, and as such is a required element. This can lead to the creation of otherwise unused state variables to define the type for an argument.
4 Control
Control messages are also expressed in XML using the SOAP.
Here is an example:
POST /control/url HTTP/1.1
HOST: hostname:portNumber
CONTENT-TYPE: text/xml; charset="utf-8"
CONTENT-LENGTH: length of body
USER-AGENT: OS/version UPnP/1.1 product/version
SOAPACTION: "urn:schemas-upnp-org:service:serviceType:v#actionName"
<?xml version="1.0"?>
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
<argumentName>in arg value</argumentName>
</u:actionName>
</s:Body>
</s:Envelope>
Here, actionName
and argumentName
must be correlated to the description.
The result of invocation is also expressed in XML:
HTTP/1.1 200 OK
CONTENT-TYPE: text/xml; charset="utf-8"
DATE: when response was generated
SERVER: OS/version UPnP/1.1 product/version
CONTENT-LENGTH: bytes in body
<?xml version="1.0"?>
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:actionNameResponse xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
<argumentName>out arg value</argumentName>
</u:actionNameResponse>
</s:Body>
</s:Envelope>
5 Eventing
Control points listen to state changes in devices. We only consider unicast eventing.
Subscription and Unsubscription
URL for subscription is given in the desription of services. Here is an example:
SUBSCRIBE publisher path HTTP/1.1
HOST: publisher host:publisher port
USER-AGENT: OS/version UPnP/1.1 product/version
CALLBACK: <delivery URL>
NT: upnp:event
The response may be:
HTTP/1.1 200 OK
DATE: when response was generated
SERVER: OS/version UPnP/1.1 product/version
SID: uuid:subscription-UUID
CONTENT-LENGTH: 0
TIMEOUT: Second-1800
Two fields need to be noticed:
- SID: subscription identifier.
- TIMEOUT: actual duration until subscription expires.
Renewing a subscription with SID:
SUBSCRIBE publisher path HTTP/1.1
HOST: publisher host:publisher port
SID: uuid:subscription UUID
Unsubscription is similar:
UNSUBSCRIBE publisher path HTTP/1.1
HOST: publisher host:publisher port
SID: uuid:subscription UUID
Eventing Message
We directly analyse the data packet:
NOTIFY delivery path HTTP/1.1
HOST: delivery host:delivery port
CONTENT-TYPE: text/xml; charset="utf-8"
NT: upnp:event
NTS: upnp:propchange
SID: uuid:subscription-UUID
SEQ: event key
CONTENT-LENGTH: bytes in body
<?xml version="1.0"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<variableName>new value</variableName>
</e:property>
</e:propertyset>
e:property
repeats once for each variable name and value in the event message.
SEQ is the event sequence number and begins from 0.
To acknowledge receipt of this event message, a subscriber MUST respond within 30 seconds, including expected transmission time:
HTTP/1.1 200 OK
However, if a subscriber does not respond within 30 seconds, the publisher MUST keep the subscription active until the subscription expires or is cancelled.
6 Implementation
UPnP is not complicated. Thankfully, some SDKs can be found in UPnP Forum: http://upnp.org/sdcps-and-certification/resources/sdks/.
References
- UPnP Hacks: UPnP background http://www.upnp-hacks.org/upnp.html
- UPnP Device Architecture version 1.1 http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
- Writing a UPnP Service http://burtonini.com/computing/gupnp-docs/server-tutorial.html