一、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代碼中也是根據這里設定好的動作名稱和狀態變量名稱去執行不同動作所對應的函數和改變對應變量的值。
sourceurl:http://blog.csdn.net/yanghao23/article/details/7684860
