Linux下UPnP sample分析

 

  1、UPnP簡介  html

       UPnP(Universal Plug and Play)技術是一種屏蔽各類數字設備的硬件和操做系統的通訊協議。它是一種數字網絡中間件技術,創建在TCP/IP、HTTP協議之上,採用XML來描述設備和控制信息。這種技術最開始是被微軟,因特爾等公司使用在數字家庭中的,用來在家庭網絡中完成多媒體資源共享,家電一體化等功能,例如在各類家電上實現IP數字化,加入網絡傳輸和控制部分,從而讓家電能組建UPnP網絡,這種技術能讓人們在上班或者外地出差時能查看家庭狀況,如:是否有家電忘記關閉;監控家庭狀況;或者在回家以前打開家裏的熱水器並設置水溫;在天熱時提早打開空調;打開電飯煲開始蒸飯……linux

    這些應用因爲家電廠商的不積極(目前能鏈接到網絡的家電可能只有電視吧),或許是成本問題等,UPnP設計之初想要達到的數字家庭並未獲得普及和普遍應用。可是UPnP的特有特性仍是很吸引人的,它最大的特性是它的消息發送是經過HTTP協議發送,全部的消息內容都是經過XML包裝的,這種消息傳輸模式使得咱們能經過瀏覽器訪問和控制支持UPnP協議的設備,再來讓咱們看看傳統的嵌入式網絡的通訊吧,大多數設備之間網絡通訊直接使用TCP/IP上的socket編程,這種通訊模式須要通訊的雙方制定好通訊數據的格式包,在客戶端和服務器端都須要進行編程,並且一旦項目需求發生變化,通訊格式發生變化時,這時通訊兩端的程序都須要修改,若是客戶還提出跨平臺的問題,那須要修改的就更多了。UPnP協議自己是利用的現有的通用協議而來的,它佔用資源少,特別適用於嵌入式網絡領域,能經過瀏覽器訪問和控制設備的特性使得UPnP的編程一般只涉及一方,即設備端。通訊數據格式的修改和客戶需求的變化也只涉及到設備端的修改,它便於設備的升級,UPnP設備在添加到網絡中時,就能夠當即被網絡中擁有瀏覽器的客戶端訪問和控制。web

2、UPnP的組成編程

UPnP網絡是指經過採用UPnP協議的設備所組成的網絡,它的基本組件是服務、設備和控制點:瀏覽器

服務是UPnP網絡中最小邏輯功能單元,由狀態表、事件和控制服務器組成。狀態表描述服務的當前狀態;事件服務器用來管理來自控制點的事件訂閱請求,並在服務的狀態改變時向訂閱者發送狀態更新事件;而控制服務器則負責處理來自控制點的動做請求。服務器

      UPnP設備由一組子設備或服務構成,同時多個設備下的子設備也經過邏輯組合構成新的設備。設備中的每一個功能也能夠當作一個邏輯子設備向外發佈。網絡

   控制點的功能是發現和控制其它設備,在控制點發現一個網絡設備後,它會發出請求先獲取設備描述和服務列表,再獲取感興趣的服務描述,而後經過動做請求來控制服務。控制點訂閱設備的服務事件時,服務會在狀態變化時向控制點發送的狀態更新事件。一個控制點能夠控制多個UPnP設備,也能夠做爲一個設備被其它控制點控制。架構

3、UPnP的工做過程app

 

UPnP的工做過程socket

 

UPnP協議棧

4、UPnP的描述文檔

     在UPnP的工做是基於UPnP描述文件的。UPnP描述文件分爲設備描述文件和服務描述文件。

設備描述文件包括設備屬性和它所提供的服務,一個標準設備描述文檔以下所示:

 

[plain]  view plain copy
  1. <span style="font-size:16px;"><?xml version="1.0"?>  
  2. <root xmlns="urn:schemas-upnp-org:XXXXXX">  
  3.  ......  
  4.   <device>  
  5.     <deviceType>urn:schemas-upnp-org:device: XXXXXX: X </deviceType>  
  6.  ……  
  7.     <UDN>uuid:XXXXXX</UDN>  
  8.     <UPC>……</UPC>  
  9.     <serviceList>  
  10.       <service>…… </service>  
  11.     </serviceList>  
  12.    <presentationURL>/設備展現URL地址</presentationURL>  
  13. </device>  
  14. </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服務描述文件的基本格式以下:

[plain]  view plain copy
  1. <span style="font-size:16px;"><?xml version="1.0"?>  
  2. <scpd xmlns="urn:schemas-upnp-org:service-1-0">  
  3. <actionList>         
  4.        <action>  
  5.        <name>XXX<name>  
  6.                <argumentList>  
  7.               <argument>……</argument>  
  8.                ……  
  9.              </argumentList>  
  10.       </action>  
  11. ……  
  12. </actionList>  
  13.   
  14. <serviceStateTable>  
  15. <stateVariable>…… </stateVariable>  
  16. </serviceStateTable>  
  17. </scpd>  
  18. </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文檔指定了服務的狀態表和動做。狀態表能夠理解爲服務的測量數據,動做則可理解爲服務向用戶提供的控制點。

 

5、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.xmltvpictureSCPD.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的狀態變量和動做恰好能夠完成這兩方面的功能,狀態變量能夠等同於測量數據的實時顯示,動做等同於控制,動做提供遠程接口供用戶調用。

6、UPnP程序的編寫

         UPnP開發包中使用很簡單,能夠參考sample例子中的源代碼,大部分API函數的調用是固定的,須要咱們作的工做主要集中在XML文檔的編寫上,我這裏以一例子中的TvDevice Control State Table中的Power選項爲例。首先查看它的定義,在sample下的web目錄下的tvdevicepres.html中:

[html]  view plain copy
  1.        <TR>  
  2.           <TD  BGCOLOR="#FFFFFF" VALIGN=center ALIGN=center><span style="color:#000000;">Power</span></TD>  
  3.           <TD  BGCOLOR="#FFFFFF" valign="top"><P ID=Power></P></TD>  
  4.           <TD  BGCOLOR="#FFFFFF" valign="top">    
  5.         <INPUT type="button" onclick="SetPowerOn()"      value=" On   ">     
  6.         <INPUT type="button" onclick="SetPowerOff()"     value=" Off  ">          
  7.           </TD>  
  8.         </TR>  
  9. ……  
  10.   
  11.   
  12.   
  13.   
  14.   
  15. If (callbackType = "VARIABLE_UPDATE") Then      
  16.      select case svcObj.Id      case "urn:upnp-org:serviceId:tvcontrol1"   
  17.             select case varName          Case "Power"      Power.innerText = value  
  18. ……  
  19.   
  20.   
  21. function SetPowerOn()  
  22.     Dim inArgs(0)  
  23.     Dim outArgs(0)  
  24.     TvControlService.InvokeAction "PowerOn", inArgs, outArgs  
  25. end function  
  26.   
  27. function SetPowerOff()  
  28.     Dim inArgs(0)  
  29.     Dim outArgs(0)  
  30.     TvControlService.InvokeAction "PowerOff", inArgs, outArgs  
  31. 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文件中):

[html]  view plain copy
  1.  <actionList>  
  2.     <action>  
  3.       <name>PowerOn</name>  
  4.       <argumentList>  
  5.          <argument>  
  6.            <retval />  
  7.            <name>Power</name>  
  8.            <relatedStateVariable>Power</relatedStateVariable>  
  9.            <direction>out</direction>  
  10.           </argument>  
  11.       </argumentList>  
  12.     </action>  
  13. ……  
  14. </actionList>  
  15.   
  16.   <serviceStateTable>  
  17.   
  18.     <stateVariable sendEvents="yes">  
  19.       <name>Power</name>  
  20.       <dataType>Boolean</dataType>  
  21.       <defaultValue>0</defaultValue>  
  22.     </stateVariable>  
  23. ……  

tvcontrol服務的狀態變量Power是一個bool類型的變量,PowerOn動做與狀態變量Power綁定,這樣咱們在執行PowerOn時會影響狀態變量Power,而這個具體的影響是在程序代碼中完成的,這裏只是完成一個關係創建的工做。在UPnP代碼中也是根據這裏設定好的動做名稱和狀態變量名稱去執行不一樣動做所對應的函數和改變對應變量的值。

轉自 http://blog.csdn.net/yanghao23/article/details/7684860

相關文章
相關標籤/搜索