Linux下UPnP sample分析
一、UPnP简介
UPnP(Universal Plug and Play)技术是一种屏蔽各种数字设备的硬件和操作系统的通信协议。它是一种数字网络中间件技术,建立在TCP/IP、HTTP协议之上,采用XML来描述设备和控制信息。这种技术最开始是被微软,因特尔等公司使用在数字家庭中的,用来在家庭网络中完成多媒体资源共享,家电一体化等功能,例如在各种家电上实现IP数字化,加入网络传输和控制部分,从而让家电能组建UPnP网络,这种技术能让人们在上班或者外地出差时能查看家庭情况,如:是否有家电忘记关闭;监控家庭情况;或者在回家之前打开家里的热水器并设置水温;在天热时提前打开空调;打开电饭煲开始蒸饭……
这些应用由于家电厂商的不积极(目前能连接到网络的家电可能只有电视吧),或许是成本问题等,UPnP设计之初想要达到的数字家庭并未得到普及和广泛应用。但是UPnP的特有特性还是很吸引人的,它最大的特性是它的消息发送是通过HTTP协议发送,所有的消息内容都是通过XML包装的,这种消息传输模式使得我们能通过浏览器访问和控制支持UPnP协议的设备,再来让我们看看传统的嵌入式网络的通信吧,大多数设备之间网络通信直接使用TCP/IP上的socket编程,这种通信模式需要通信的双方制定好通信数据的格式包,在客户端和服务器端都需要进行编程,而且一旦项目需求发生变化,通信格式发生变化时,这时通信两端的程序都需要修改,如果客户还提出跨平台的问题,那需要修改的就更多了。UPnP协议本身是利用的现有的通用协议而来的,它占用资源少,特别适用于嵌入式网络领域,能通过浏览器访问和控制设备的特性使得UPnP的编程通常只涉及一方,即设备端。通信数据格式的修改和客户需求的变化也只涉及到设备端的修改,它便于设备的升级,UPnP设备在添加到网络中时,就可以立即被网络中拥有浏览器的客户端访问和控制。
二、UPnP的组成
UPnP网络是指通过采用UPnP协议的设备所组成的网络,它的基本组件是服务、设备和控制点:
服务是UPnP网络中最小逻辑功能单元,由状态表、事件和控制服务器组成。状态表描述服务的当前状态;事件服务器用来管理来自控制点的事件订阅请求,并在服务的状态改变时向订阅者发送状态更新事件;而控制服务器则负责处理来自控制点的动作请求。
UPnP设备由一组子设备或服务构成,同时多个设备下的子设备也通过逻辑组合构成新的设备。设备中的每个功能也可以当做一个逻辑子设备向外发布。
控制点的功能是发现和控制其它设备,在控制点发现一个网络设备后,它会发出请求先获取设备描述和服务列表,再获取感兴趣的服务描述,然后通过动作请求来控制服务。控制点订阅设备的服务事件时,服务会在状态变化时向控制点发送的状态更新事件。一个控制点可以控制多个UPnP设备,也可以作为一个设备被其它控制点控制。
三、UPnP的工作过程
UPnP的工作过程
UPnP协议栈
四、UPnP的描述文档
在UPnP的工作是基于UPnP描述文件的。UPnP描述文件分为设备描述文件和服务描述文件。
设备描述文件包括设备属性和它所提供的服务,一个标准设备描述文档如下所示:
- <span style="font-size:16px;"><?xml version="1.0"?>
- <root xmlns="urn:schemas-upnp-org:XXXXXX">
- ......
- <device>
- <deviceType>urn:schemas-upnp-org:device: XXXXXX: X </deviceType>
- ……
- <UDN>uuid:XXXXXX</UDN>
- <UPC>……</UPC>
- <serviceList>
- <service>…… </service>
- </serviceList>
- <presentationURL>/设备展示URL地址</presentationURL>
- </device>
- </root></span>
在设备描述文档中,<root>到</root>即描述的一个根设备,specVersion配置的是UPnP协议版本编号,<device>到</device>之间描述的是一个完整的UPnP设备,deviceType表示设备的类型,它的标准命名方式是urn:schemas-upnp-org:device:deviceType:ver,其中deviceType:ver是由用户来设定的。presentationURL参数表示设备展示所对应的请求页面地址。
设备描述中UDN(Unique Device Name)是必须设定的,这个参数用来在UPnP组建的网络中用来唯一标识一个设备,产品编号UPC(Universal Product Code)是可选的,然后<serviceList>到</serviceList>之间是来描述设备提供的服务,每个服务的参数说明在<service>到</service>之间,服务的主要参数如表1所示:
表1设备服务XML描述字段
参数 |
说明 |
<serviceType> |
服务类型,UPnP论坛规定为urn:schemas-upnp-org:service:serviceType: ver,serviceType:ver由用户自己设定 |
<serviceId> |
服务ID,它在一个设备描述里命名需要唯一 |
<SCPDURL> |
服务描述的URL |
<controlURL> |
服务控制的URL |
<eventSubURL> |
服务事件的URL |
它们描述了设备支持的服务类型和数量,以及所有服务支持的动作和变量。
UPnP服务描述文件定义了动作、动作参数、变量、变量类型和及其范围、事件特性,每个服务提供的动作有参数选择(分为输入参数和输出参数),每个参数必须对应服务描述文件中的服务状态变量表(serviceStateTable)中的一个状态变量(stateVariable),UPnP服务描述文件的基本格式如下:
- <span style="font-size:16px;"><?xml version="1.0"?>
- <scpd xmlns="urn:schemas-upnp-org:service-1-0">
- <actionList>
- <action>
- <name>XXX<name>
- <argumentList>
- <argument>……</argument>
- ……
- </argumentList>
- </action>
- ……
- </actionList>
- <serviceStateTable>
- <stateVariable>…… </stateVariable>
- </serviceStateTable>
- </scpd>
- </span>
每个动作在一个设备服务中由动作名称name唯一标识,动作的参数是在<argumentList>中由<argument>描述的,argument的参数如表2:
表2 设备服务XML描述文档中动作字段
参数 |
说明 |
<name> |
参数名,以字母开头,可以以数字、字母和下划线组成 |
<direction> |
“in”或“out”,表示输入和输出参数 |
<retval> |
可选,最多指定一个参数为动作返回值 |
<relatedStateVariable> |
必须为一个状态变量名 |
再来看状态变量< stateVariable >的参数,如表3:
表3设备服务XML描述文档中状态变量字段
参数 |
说明 |
<name> |
状态变量名,以字母开头,可以以数字、字母和下划线组成 |
<dataType> |
数据类型,详细见注 |
<defaultValue> |
默认值 |
<allowedValueList> |
有效的字符值列表,每个有效字符值在<allowedValue>中定义 |
<allowedValueRange> |
包括最小值在<minimum>中定义,最大值在<maximum>中定义,<step>步进值 |
上面叙述的设备描述和服务描述是通过XML文件完成的,在程序中就是对应不同的XML文件,首先设备在XML文档中描述设备名称和它所包含的服务信息(服务信息中包括服务名称和ID,最重要的是指定服务描述对应XML文件地址)。这样程序才能在解析设备文档后能根据它提供的信息去解析对应的服务XML文档。服务XML文档指定了服务的状态表和动作。状态表可以理解为服务的测量数据,动作则可理解为服务向用户提供的控制点。
五、UPnP在ARM Linux上的使用
UPnP应用在arm平台有它的特点和优势,这些我都在前文简单介绍了,但实际开发时可以现在PC机上测试,测试成功后再通过交叉编译工具编译放在ARM平台运行即可,开发UPnP应用程序先要下载UPnP开发套件,下载后在Linux虚拟机中解压执行./configure;然后make 即可测试SDK中提供的sample程序了(目录为:libupnp-1.6.14/upnp/sample),下面有三个测试程序tv_ctrlpt ,tv_combo, tv_device。这三个程序只是程序的启动脚本,本文只分析tv_device程序,这个脚本文件最终实际上执行了libupnp-1.6.14/upnp/sample/.libs/tv_device 程序,程序代码在sample目录下的common和linux中,它所使用的XML描述文件在web目录下。
执行tv_device脚本:./tv_device,效果如下:
将图中的网址http://192.168.128.128:49152/tvdevicedesc.xml输入到另一台计算机的浏览器上,最后的关键部分显示如下:
tvdevicedesc.xml是一个设备描述文档,我们可以清楚的看到,它的设备描述文档中指明了设备拥有两个服务和服务的描述文档地址(tvcontrolSCPD.xml和tvpictureSCPD.xml),设备文档中还指定了设备展示文档的地址<presentationURL>/tvdevicepres.html</presentationURL> ,这个地址是提供给用户在浏览器中访问和操作设备,将之前的网址改为http://192.168.128.128:49152/tvdevicepres.html ,(注意:这里由于例子中的设备展示文档中使用了VBscript脚本,故暂时只能通过IE内核的浏览器正常访问):
当你操作这些按钮时,虚拟机中的Linux程序中会输入对应的操作信息,在局域网中的任何用户都能通过浏览器访问和控制设备。如果你想要在arm平台中测试这些,首先需要在程序配置时执行: ./configure --host=arm-linux
--prefix=/home/yanghao/Desktop/libupnp --enable-shared 然后执行make,make install,先把程序运行所需要的lib库编译生成出来,然后将sample下的编译好的程序复制到开发板,将/home/yanghao/Desktop/libupnp中的lib库复制到开发板的lib目录下,或者是在其中脚本中设置LD_LIBRARY_PATH变量也行,这样程序就可以在arm开发板中执行了。
通过之前的演示,我们可以看到UPnP的模式有些像一个网页服务器,的确如此,UPnP协议通过网页来完成用户数据的操作和访问,但它又和网页服务器有着重大的区别,网页的操作模式只是它众多特性中的一种,UPnP架构中消息的发布和传输是基于HTTP和XML,UPnP占用资源小,协议架构简单,我们可以看到它编译出的支持库大小1.5M,这还是动态链接库和静态链接库的总大小,网页是它数据显示的一种方式,它的数据更多的是应用程序间的交互。控制点可以通过订阅一个UPnP设备服务,当UPnP设备服务中的状态变量发生变化时会主动向订阅该服务的控制点发送状态变化信息,同时控制点可以在程序中利用远程调用完成对设备的控制。这种简单灵活的方式非常适合于嵌入式领域,通常嵌入式领域中网络通信无非就是传感器测量数据的传输和远程用户对设备的控制,UPnP的状态变量和动作刚好可以完成这两方面的功能,状态变量可以等同于测量数据的实时显示,动作等同于控制,动作提供远程接口供用户调用。
六、UPnP程序的编写
UPnP开发包中使用很简单,可以参考sample例子中的源代码,大部分API函数的调用是固定的,需要我们做的工作主要集中在XML文档的编写上,我这里以一例子中的TvDevice Control State Table中的Power选项为例。首先查看它的定义,在sample下的web目录下的tvdevicepres.html中:
- <TR>
- <TD BGCOLOR="#FFFFFF" VALIGN=center ALIGN=center><span style="color:#000000;">Power</span></TD>
- <TD BGCOLOR="#FFFFFF" valign="top"><P ID=Power></P></TD>
- <TD BGCOLOR="#FFFFFF" valign="top">
- <INPUT type="button" onclick="SetPowerOn()" value=" On ">
- <INPUT type="button" onclick="SetPowerOff()" value=" Off ">
- </TD>
- </TR>
- ……
- If (callbackType = "VARIABLE_UPDATE") Then
- select case svcObj.Id case "urn:upnp-org:serviceId:tvcontrol1"
- select case varName Case "Power" Power.innerText = value
- ……
- function SetPowerOn()
- Dim inArgs(0)
- Dim outArgs(0)
- TvControlService.InvokeAction "PowerOn", inArgs, outArgs
- end function
- function SetPowerOff()
- Dim inArgs(0)
- Dim outArgs(0)
- TvControlService.InvokeAction "PowerOff", inArgs, outArgs
- end function
Power旁边的编辑框ID为Power,后面紧跟的两个按钮On和Off触发的函数依次为SetPowerOn()和SetPowerOff()。由VBscript中的判断语句中可以看到当服务ID为"urn:upnp-org:serviceId:tvcontrol1"的变量"Power"值发生变化时,编辑框ID为Power的内容为服务的"Power"变量值。这里将网页中的编辑框内容与服务中的变量值绑定起来了。再来看按钮On的触发函数SetPowerOn(),函数定义中说明函数最终执行TvControlService中的PowerOn动作。再来看tvcontrol服务的描述文件对状态变量和动作的说明(在web目录下tvcontrolSCPD.xml文件中):
- <actionList>
- <action>
- <name>PowerOn</name>
- <argumentList>
- <argument>
- <retval />
- <name>Power</name>
- <relatedStateVariable>Power</relatedStateVariable>
- <direction>out</direction>
- </argument>
- </argumentList>
- </action>
- ……
- </actionList>
- <serviceStateTable>
- <stateVariable sendEvents="yes">
- <name>Power</name>
- <dataType>Boolean</dataType>
- <defaultValue>0</defaultValue>
- </stateVariable>
- ……
tvcontrol服务的状态变量Power是一个bool类型的变量,PowerOn动作与状态变量Power绑定,这样我们在执行PowerOn时会影响状态变量Power,而这个具体的影响是在程序代码中完成的,这里只是完成一个关系建立的工作。在UPnP代码中也是根据这里设定好的动作名称和状态变量名称去执行不同动作所对应的函数和改变对应变量的值。
Linux下UPnP sample分析的更多相关文章
- 在Linux下,如何分析一个程序达到性能瓶颈的原因
0.在Linux下,如何分析一个程序达到性能瓶颈的原因,请分别从CPU.内存.IO.网络的角度判断是谁导致的瓶颈?注意现在的机器CPU是多核 1.用sar -n DEV 1 10 2.用iotop命令 ...
- 几款抓包工具在windows,mac,linux下的支持分析
抓包工具的使用 几款抓包工具在windows,mac,linux下的支持分析 抓包工具简介 Chrome/Firefox 开发者工具: 浏览器内置,方便易用 Fiddler/Charles: 基于代理 ...
- 以C语言为例完成简单的网络聊天程序以及关于socket在Linux下系统调用的分析
套接字是网络编程中的一种通信机制,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程. 端 ...
- (转)Linux 下栈溢出问题分析解决 *** stack smashing detected *** XXXX terminated
Linux 下栈溢出问题分析解决 *** stack smashing detected *** XXXX terminated 1.利用gdb 或者valgrind 定位到具体的代码 最近在Linu ...
- Android/Linux下CGroup框架分析及其使用
1 cgroup介绍 CGroup是control group的简称,它为Linux kernel提供一种任务聚集和划分的机制,可以限制.记录.隔离进程组(process groups)所使用的资源( ...
- linux下进程权限分析
转自http://blog.chinaunix.net/uid-27105712-id-3349522.html 在linux下,关于文件权限,大部分人接触比较多,也比较熟悉了解.但是对进程权限一般知 ...
- Linux下触摸屏驱动程序分析
[摘要: 本文以linux3.5--Exynos4412仄台,剖析触摸屏驱动焦点内容.Linux下触摸屏驱动(以ft5x06_ts为例)须要懂得以下学问: 1. I2C协定 2. Exynos4412 ...
- linux下编译原理分析
linux下编译hello.c 程序,使用gcc hello.c,然后./a.out就能够执行:在这个简单的命令后面隐藏了很多复杂的过程,这个过程包含了以下的步骤: ================= ...
- Linux 下蓝牙bluez分析及使用 (1)
蓝牙耳机的使用 由于Linux下蓝牙使用不及Windows下直观,致使使用时会出现一些小问题.虽然是小问题,但是由于普通的操作都具有顺序性,前面的中断了,后面的哪怕再简单,也无法继续了.正好近期工作与 ...
随机推荐
- Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数
上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...
- 10个最好用的HTML/CSS 工具、插件和资料库
大家在使用HTML/CSS开发项目的过程中,有使用过哪些工具,插件和库?下面介绍的10种HTML/CSS工具,插件和资料库,是国外程序员经常用到的. Firebug Lite FirebugLite ...
- PayPal高级工程总监:读完这100篇论文 就能成大数据高手(附论文下载)
100 open source Big Data architecture papers for data professionals. 读完这100篇论文 就能成大数据高手 作者 白宁超 2016年 ...
- JDK安装与配置
JDK安装与配置 一.下载 JDK是ORACLE提供免费下载使用的,官网地址:https://www.oracle.com/index.html 一般选择Java SE版本即可,企业版的选择Java ...
- RunLoop 总结:RunLoop的应用场景(一)
参考资料 好的书籍都是值得反复看的,那好的文章,好的资料也值得我们反复看.我们在不同的阶段来相同的文章或资料或书籍都能有不同的收获,那它就是好文章,好书籍,好资料.关于iOS 中的RunLoop资料非 ...
- 用Taurus.MVC 做个企业站(下)
前言: 上一篇完成了首页,这一篇就把剩下的几个功能给作了吧. 包括文章列表.文章详情和产品展示. 1:文章列表: 原来的ArticleList.aspx 1:现在的articlelist.html 除 ...
- Vue.js——基于$.ajax实现数据的跨域增删查改
概述 之前我们学习了Vue.js的一些基础知识,以及如何开发一个组件,然而那些示例的数据都是local的.在实际的应用中,几乎90%的数据是来源于服务端的,前端和服务端之间的数据交互一般是通过ajax ...
- 《深入理解Java虚拟机》内存分配策略
上节学习回顾 1.判断对象存活算法:引用计数法和可行性分析算法 2.垃圾收集算法:标记-清除算法.复制算法.标记-整理算法 3.垃圾收集器: Serial:新生代收集器,采用复制算法,单线程. Par ...
- ucos实时操作系统学习笔记——任务间通信(信号量)
ucos实时操作系统的任务间通信有好多种,本人主要学习了sem, mutex, queue, messagebox这四种.系统内核代码中,这几种任务间通信机制的实现机制相似,接下来记录一下本人对核心代 ...
- ReactNative&weex&DeviceOne对比
React Native出来有一段时间了,国内的weex和deviceone是近期发布的,我可以说从2011年就开始关注快速开发的跨平台平台技术了,接触过phoneGap.数字天堂.appcan等早期 ...