1:DLNA简述:
DLNA是Digital Living Network Alliance(数字生活网络联盟)的缩写。其宗旨是Enjoy your music, photos and videos, anywhere anytime,他是由索尼、英特尔、微软等发起成立、目的在于解决个人电脑,消费电器,移动设备在内无线网络和有线网络的互联互通,使得数字媒体和内容服务的无限制的共享和增长成为可能。目前主流的智能网络设备通信解决方案主要是DLNA Airplay和新出的Miracast。
DLNA制定了一系列标准并包含实现相关标准所需要的一系列协议栈(如HTTP SSDP XML SOAP UPnP UDP TCP/IP等等),他不仅可用于WIFI,还支持Bluetooth等多种通信协议,这里只讨论在局域网LAN下使用WIFI连接的智能设备与客户端之间的协议编程。
首先简单介绍一下客户端和智能设备在DLNA标准定义下的角色。当手机端仅实现将网络资源(图片,视频,音频)投射至电视,音响等时,手机端扮演的是控制点Control Point,而电视、音响或者机顶盒则扮演的是渲染设备或播放设备。当手机端将本地资源(图片,视频,音频)投射至电视,音响等时,我们需要在手机端搭建服务器。本地搭建服务器有两种方式:使用Platinum 和 使用GCDWebServer/WebDAV来实现。要实现这些功能,必须保证这些设备在同一个局域网的相同网段下,即共享同一个网关Internet Gateway。
DLNA标准包括多项协议及标准,其中最重要的部分是UPnP。对于我们目前的需求UPnP就能满足全部要求。
2:UPnP简述
通用即插即用(英语:Universal Plug and Play,简称UPnP)是由“通用即插即用论坛”(UPnP™ Forum)推广的一套网络协议。该协议的目标是使家庭网络(数据共享、通信和娱乐)和公司网络中的各种设备能够相互无缝连接,并简化相关网络的实现。UPnP通过定义和发布基于开放、因特网通讯网协议标准的UPnP设备控制协议来实现这一目标。
UPnP这个概念是从即插即用(Plug-and-play)派生而来的,即插即用是一种热拔插技术。详情请看UPnP中文文档 UPnP协议图如下:
我们从UPnP中文文档,可大致可得出UPnP方案有下面的流程
1.寻址:UPnP 网络互连的基础是基于DHCP或AutoIP的 IP 寻址。这也是p2p协议的基础,就相当于获取身份标识的ID(身份 证)。
2.发现:如果获取了一个 IP 地址,则 UPnP 网络的第 1 步是发现。在将一个设备添加到网络上之后,UPnP 发现协议允许该设备向网络中的控制点宣告其服务。同样,当一个控制点被添加到网络后,UPnP 发现协议允许该控制点在网上搜索
感兴趣的设备。这两者处理上都需要HTTPMU协议支持。ssdp协议是支撑发现的基础。3.描述:UPnP 网络中的第 2 步是描述。控制点在发现一个设备之后仍然对其知之甚少。为了使控制点了解到更多关于设备及其能力的信息或与设备进行交互,则控制点必须取得来自该设备在发现消息中所提供之 URL 的设备描述。描述的基础是发现,如果没有发现获取到设备的最基础的信息,得不到location中的设备描述url,也就没有设备能力这一说。
4.控制:UPnP 网络中的第 3 步是控制。当一个控制点取得设备描述后,该控制点可将动作发至一个设备的服务。为此,控制点将一条适当的控制消息发至服务的控制 URL(在设备描述中提供)。控制消息同样利用简单对象访问协议(SOAP)通过 XML 来表达。
5.事件:UPnP 网络的第 4 步是事件触发。针对服务的 UPnP 描述包括一个服务响应的动作列表,以及一个对服务器运行时状态进行展示的变量列表。在这些变量变更时服务会发布更新,一个控制点可以预订接收此信息。服务通过发送事件消息来发布更新。事件消息包含一个或多个状态变量名和这些变量的当前值。这些消息同样通过 XML 来表达,并采用通用事件通知架构(GENA)格式。
6.展示:UPnP 网络中的第 5 步是展示。如果设备有用于展示的 URL,那么控制点就可以通过此 URL 取得一个页面,在浏览器中加载该页面,并且根据页面的功能,支持用户控制设备和/或浏览设备状态。每一项完成的程度取决于展示页面
和设备的具体功能。
2.1寻址
既然基于互联网那么必须要有寻址,寻址的过程就是设备获取ip地址的过程,这个里面一般都使用DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),即路由动态的分配一个没有使用的ip地址给设备。详情请看UPnP中文文档
UPnP 技术是架构在 IP 网络之上。因此拥有一个网络中唯一的 IP 地址是 UPnP 设备正常工作的基础。UPnP 设备首先查看网络中是否有 DHCP 服务器,如果有,那么使用 DHCP 分配的 IP 即可;如果没有,则需要使用LLA技术来为自己找适合的IP地址。
另外,在 UPnP 运行过程中,UPnP 设备都需要周期性检测网络中是否有 DHCP 服务器存在,一旦发现有 DHCP 服务器,就必须终止使用 LLA 技术获取的 IP 地址,改用 DHCP 分配的 IP 地址。
2.2发现
支持DLNA的智能设备加入组网并进行搜索其他设备的过程称为设备发现。当一个新的CP (Control Point)加入一个局域网时,为了获取当前网段里都有哪些智能设备,CP需要遵循SSDP向默认多播IP和端口发送获取信息的请求。
SSDP:Simple Sever Discovery Protocol,简单服务发现协议,这是一个工作在UDP上的HTTP协议(http的扩展协议M-SEARCH),此协议为网络客户提供一种无需任何配置、管理和维护网络设备服务的机制。此协议采用基于通知和发现路由的多播发现方式实现。协议客户端在保留的多播地址:239.255.255.250:1900(IPV4)发现服务,(IPv6 是:FF0x::C)同时每个设备服务也在此地址上上监听服务发现请求。如果服务监听到的发现请求与此服务相匹配,此服务会使用单播方式响应。
常见的协议请求消息有两种类型,第一种是服务通知,设备和服务使用此类通知消息声明自己存在;第二种是查询请求,协议客户端用此请求查询某种类型的设备和服务。
iOS中使用GCDAsyncUdpSocket发送和接受SSDP请求、响应及通知,安卓也需要用类此框架来完成
所以我们发现设备也有两种方法
1:主动通知方式:当设备加入到网络中,向网络上所有控制点通知它所提供的服务,通知消息采用多播方式。
2:搜索——响应方式:当一个控制点加入到网络中,在网络搜索它感兴趣的所有设备和服务,搜索消息采用多播方式发送,而设备针对搜索的响应则是使用单播方式发送。
发现流程图如下:
发现设备:搜索请求消息字符串:
NSData * sendData = [[self getSearchString] dataUsingEncoding:NSUTF8StringEncoding];
[_udpSocket sendData:sendData toHost:ssdpAddres port:ssdpPort withTimeout:-1 tag:1];
其中:getSearchString为:
[NSString stringWithFormat:
@"M-SEARCH * HTTP/1.1\r\nHOST: %@:%d\r\nMAN: \"ssdp:discover\"\r\nMX: 3\r\nST: %@\r\nUSER-AGENT: iOS UPnP/1.1 mccree/1.0\r\n\r\n",
ssdpAddres,
ssdpPort,
serviceType_AVTransport];
-----
ssdpAddres --> @"239.255.255.250";
ssdpPort --> 1900;
serviceType_AVTransport -->@"urn:schemas-upnp-org:service:AVTransport:1";
设备返回字符串:
HTTP/1.1 200 OK
Location: http://192.168.124.43:1266/
Cache-Control: max-age=1800
Server: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.4.2
EXT:
USN: uuid:skyworth&208B3756FFED&192.168.124.43::urn:schemas-upnp-org:service:AVTransport:1
ST: urn:schemas-upnp-org:service:AVTransport:1
Date: Thu, 24 Jan 2019 02:38:18 GMT
2.3描述
控制点发现设备之后仍然对设备知之甚少,仅能知道UPnP类型,UUID和设备描述URL。为了进一步了解设备和服务,需要获取并解析XML描述文件。
描述文件有两种类型:设备描述文档(DDD)和服务描述文档(SDD)
设备描述文档:设备描述文档是对设备的基本信息描述,包括厂商制造商信息、设备信息、设备所包含服务基本信息等。设备描述采用XML格式,可以通过HTTP GET请求获取。
服务描述文档:为了实现简单的投屏和控制(播放、暂停、停止、快进)操作并不需要解析服务描述文件。所有动作均为UPnP规范动作,服务描述文档是对服务功能的基本说明,包括服务上的动作及参数,还有状态变量和其数据类型、取值范围等。
描述流程图如下:
我们通过向步骤2拿到的location发送get请求
get:http://192.168.124.43:1266/
返回信息如下:
<html>
<head></head>
<body>
{type:1 name:root xml:"
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0">
<specversion>
<major>
1
</major>
<minor>
0
</minor>
</specversion>
<device>
<devicetype>
urn:schemas-upnp-org:device:MediaRenderer:1
</devicetype>
<friendlyname>
YuemeTV
</friendlyname>
<manufacturer>
GeniusGitHub
</manufacturer>
<manufacturerurl>
https://github.com/geniusgithub
</manufacturerurl>
<modeldescription>
GeniusGitHub AV Media Renderer Device
</modeldescription>
<modelname>
Genius Software
</modelname>
<modelurl>
https://github.com/geniusgithub
</modelurl>
<modelnumber>
20130520
</modelnumber>
<serialnumber />
<udn>
uuid:skyworth&208B3756FFED&192.168.124.43
</udn>
<dlna:x_dlnadoc xmlns:dlna="urn:schemas-dlna-org:device-1-0">
DMR-1.50
</dlna:x_dlnadoc>
<servicelist>
<service>
<servicetype>
urn:schemas-upnp-org:service:AVTransport:1
</servicetype>
<serviceid>
urn:upnp-org:serviceId:AVTransport
</serviceid>
<scpdurl>
/AVTransport/skyworth&208B3756FFED&192.168.124.43/scpd.xml
</scpdurl>
<controlurl>
/AVTransport/skyworth&208B3756FFED&192.168.124.43/control.xml
</controlurl>
<eventsuburl>
/AVTransport/skyworth&208B3756FFED&192.168.124.43/event.xml
</eventsuburl>
</service>
<service>
<servicetype>
urn:schemas-upnp-org:service:ConnectionManager:1
</servicetype>
<serviceid>
urn:upnp-org:serviceId:ConnectionManager
</serviceid>
<scpdurl>
/ConnectionManager/skyworth&208B3756FFED&192.168.124.43/scpd.xml
</scpdurl>
<controlurl>
/ConnectionManager/skyworth&208B3756FFED&192.168.124.43/control.xml
</controlurl>
<eventsuburl>
/ConnectionManager/skyworth&208B3756FFED&192.168.124.43/event.xml
</eventsuburl>
</service>
<service>
<servicetype>
urn:schemas-upnp-org:service:RenderingControl:1
</servicetype>
<serviceid>
urn:upnp-org:serviceId:RenderingControl
</serviceid>
<scpdurl>
/RenderingControl/skyworth&208B3756FFED&192.168.124.43/scpd.xml
</scpdurl>
<controlurl>
/RenderingControl/skyworth&208B3756FFED&192.168.124.43/control.xml
</controlurl>
<eventsuburl>
/RenderingControl/skyworth&208B3756FFED&192.168.124.43/event.xml
</eventsuburl>
</service>
</servicelist></device>
</root>"}
</body>
</html>
2.4控制
根据收到设备描述文档(DDD)和服务描述文档(SDD),通过解析DDD获取 <controlURL> 控制点可以知道该设备上某个服务的控制点地址。再通过解析 DDD 中 <action> 中的 <name> 和 <argumentList> 获取该服务动作的动作名称,参数要求。控制点向 controlURL 发出服务调用信息,表明动作名称和相应参数来调用相应的服务。
UPdP网络中,控制点和服务之间使用简单对象访问协议(Simple Object Access Protocol,SOAP)
控制点和服务之间使用简单对象访问协议(Simple Object Access Protocol,SOAP)的格式。SOAP 的底层协议一般也是HTTP。在 UPnP 中,把 SOAP 控制/响应信息分成 3 种: UPnP Action Request、UPnP Action Response-Success 和 UPnP Action Response-Error。SOAP 和 SSDP 不一样,所使用的 HTTP 消息是有 Body 内容,Body 部分可以写想要调用的动作,叫做 Action invocation,可能还要传递参数,如想播放一个网络上的视频,就要把视频的URL传过去;服务收到后要 response ,回答能不能执行调用,如果出错则返回一个错误代码。
一个控制的过程包含 控制地址、控制说明、控制执行、控制响应。
控制流程图如下:
以一个视频播放为例:
设置视频播放地址url
设置当前播放视频动作统一名称为 SetAVTransportURI 。 需要传递参数有
- InstanceID:设置当前播放时期时为 0 即可。
- CurrentURI: 播放资源URI
- CurrentURIMetaData: 媒体meta数据,可以为空
- Header_SOAPACTION: “urn:upnp-org:serviceId:AVTransport#SetAVTransportURI”
http://192.168.124.43:1266/AVTransport/skyworth&208B3756FFED&192.168.124.43/control.xml
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<s:Body>
<u:SetAVTransportURI>
<InstanceID>0</InstanceID>
<CurrentURI>http://pic2.nipic.com/20090506/2256386_141149004_2.jpg</CurrentURI>
<CurrentURIMetaData><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/" xmlns:sec="http://www.sec.co.kr/"><item id="filePath" parentID="0" restricted="1"><upnp:class>object.item.imageItem</upnp:class><dc:title>
IMAG1466</dc:title><dc:creator>Unknown Artist</dc:creator><upnp:artist>Unknown Artist</upnp:artist><upnp:albumArtURI>http://IP:PORT/filePath</upnp:albumArtURI><upnp:album>Unknown Album</upnp:album><res protocolInfo="http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01700000000000000000000000000000">http://IP:PORT/filePath</res></item></DIDL-Lite></CurrentURIMetaData>
</u:SetAVTransportURI>
</s:Body>
</s:Envelope>
//返回response
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:SetAVTransportURIResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1" />
</s:Body>
</s:Envelope>
视频开始播放
播放视频动作统一名称为 Play 。 需要传递参数有
- InstanceID:设置当前播放时期时为 0 即可。
- Speed:播放速度,默认传 1 。
- Header_SOAPACTION: “urn:upnp-org:serviceId:AVTransport#Pause”
http://192.168.124.43:1266/AVTransport/skyworth&208B3756FFED&192.168.124.43/control.xml
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<s:Body>
<u:Play>
<InstanceID>0</InstanceID>
<Speed>1</Speed>
</u:Play>
</s:Body>
</s:Envelope>
//response
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:PlayResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1" />
</s:Body>
</s:Envelope>
视频停止播放
暂停视频动作统一名称为 Pause 。 需要传递参数有
- InstanceID:设置当前播放时期时为 0 即可。
- Header_SOAPACTION: “urn:upnp-org:serviceId:AVTransport#Pause”
http://192.168.124.43:1266/AVTransport/skyworth&208B3756FFED&192.168.124.43/control.xml
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<s:Body>
<u:Stop>
<InstanceID>0</InstanceID>
</u:Stop>
</s:Body>
</s:Envelope>
//response
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:StopResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1" />
</s:Body>
</s:Envelope>
获取视频音量
http://192.168.124.43:1266/RenderingControl/skyworth&208B3756FFED&192.168.124.43/control.xml
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1">
<s:Body>
<u:GetVolume>
<InstanceID>0</InstanceID>
<Channel>Master</Channel>
</u:GetVolume>
</s:Body>
</s:Envelope>
//response
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetVolumeResponse xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1">
<CurrentVolume>100</CurrentVolume>
</u:GetVolumeResponse>
</s:Body>
</s:Envelope>
设置视频音量
http://192.168.124.43:1266/RenderingControl/skyworth&208B3756FFED&192.168.124.43/control.xml
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1">
<s:Body>
<u:SetVolume>
<InstanceID>0</InstanceID>
<Channel>Master</Channel>
<DesiredVolume>5</DesiredVolume>
</u:SetVolume>
</s:Body>
</s:Envelope>
//response
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:SetVolumeResponse xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1" />
</s:Body>
</s:Envelope>
设置视频快进快退
http://192.168.124.43:1266/AVTransport/skyworth&208B3756FFED&192.168.124.43/control.xml
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:AVTransport:1">
<s:Body>
<u:Seek>
<InstanceID>0</InstanceID>
<Unit>REL_TIME</Unit>
<Target>00:01:44</Target>
</u:Seek>
</s:Body>
</s:Envelope>
//response
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:SeekResponse xmlns:u="urn:schemas-upnp-org:service:AVTransport:1" />
</s:Body>
</s:Envelope>
2.5事件
服务运行时,可能改变有些状态信息变量的值,这就产生了一个事件,这是需要及时地更新给控制点。因此控制点可以通过订阅操作,让服务通过发送事件消息来发布更新。
服务运行过程中,该服务的 服务描述文件SDD 中 状态变量 <stateVariable> 发生了变化并且该变量的 <sendEvents> 属性为 yes 时,将会产生一个事件(Event)消息。如该状态变量的 <multicast> 属性为 yes ,则该服务把这个事件消息向整个网进行多播(Multicast)。如果为 no 或者不存在这个属性,则通过单播(Unicast)给订阅者发送消息。
单播事件消息的订阅及推送是遵循通用事件通知结构(General Event Notification Architecture,GENA)协议。协议中,控制点通常是个订阅者(Subscriber),它向服务提供者(通常是某个设备上的服务)发送订阅消息(SUBSCRIBE),建立订阅关系,然后可以继续更新订阅消息(Renewal),或者最后退订消息(Cancel)。另外,UPnP对GENA进行了一些扩展,如在事件消息中增加了一个key,来表示事件的顺序。
当服务器上的状态变量发生变数时,通过单播给订阅者发送通知。单播通过 HTTP 协议发送。需要在本地运行一个 HTTP Server 来接受请求。接收事件消息成功后,只需要简单返回一个 HTTP/1.1 200 OK 作为回应即刻。
iOS端运行HTTP Server可以通过 GCDWebServer(一个轻量 iOS/OSX GCD的服务器框架)来实现
订阅请求
SUBSCRIBE /dev/88024158-a0e8-2dd5-ffff-ffffc7831a22/svc/upnp-org/AVTransport/event HTTP/1.1
HOST: 192.168.1.243:46201
USER-AGENT: iOS/9.2.1 UPnP/1.1 SCDLNA/1.0
CALLBACK: <http://192.168.1.100:5000/dlna/callback>
NT: upnp:event
TIMEOUT: Second-3600 // 订阅期限
成功响应
HTTP/1.1 200 OK
Server: Linux/3.10.33 UPnP/1.0 IQIYIDLNA/iqiyidlna/NewDLNA/1.0
SID: uuid:f392-a153-571c-e10b
Content-Type: text/html; charset="utf-8"
TIMEOUT: Second-3600
Date: Thu, 03 Mar 2016 19:01:42 GMT
订阅失败
HTTP/1.1 error code errordescrioption
Server: OS/Version UPnP/1.1 product/version
SID: uuid:subscibe-UUID
Content-Length: 0
Date: Thu, 03 Mar 2016 19:01:42 GMT
续订请求
SUBSCRIBE /dev/88024158-a0e8-2dd5-ffff-ffffc7831a22/svc/upnp-org/AVTransport/event HTTP/1.1
HOST: 192.168.1.243:46201
SID: uuid:subscibe-UUID
TIMEOUT: Second-3600 // 订阅期限
取消订阅请求
UNSUBSCRIBE /dev/88024158-a0e8-2dd5-ffff-ffffc7831a22/svc/upnp-org/AVTransport/event HTTP/1.1
HOST: 192.168.1.243:46201
SID: uuid:subscibe-UUID
单播事件消息
单播消息格式如下
NOTIFY /dlna/callback HTTP/1.0
Host: 192.168.1.100:5000
Content-Length: 325
Content-Type: text/xml; charset="utf-8"
User-Agent: Neptune/1.1.3, 6
SID: uuid:ac6dce5a-6047-7862-fd41-e5596960f57a // 订阅标识符
NTS: upnp:propchange // GENA规定,必须是 upnp:propchange
NT: upnp:event // GENA规定,必须是 upnp:event
SEQ: 4 // 事件编号,初始值为0。
<?xml version="1.0" encoding="UTF-8"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<!-- 消息内容 -->
<variableName>new values</variableName>
</e:property>
</e:propertyset>
播放消息
<?xml version="1.0" encoding="UTF-8"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<LastChange>
<Event xmlns="urn:schemas-upnp-org:metadata-1-0/AVT/">
<InstanceID val="0">
<TransportState val="PLAYING"/>
</InstanceID>
</Event>
</LastChange>
</e:property>
</e:propertyset>
停止播放消息
<?xml version="1.0" encoding="UTF-8"?>
<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
<e:property>
<LastChange>
<Event xmlns="urn:schemas-upnp-org:metadata-1-0/AVT/">
<InstanceID val="0">
<TransportState val="STOPPED"/>
</InstanceID>
</Event>
</LastChange>
</e:property>
</e:propertyset>
2.6显示
展示作为一个控制和事件的补充,实现upnp协议并不强制要求。其实就是一个网页,可以看到设备的信息和状态,做的好的还可以对设备进行控制,对我们的需求而言就是手机。