2009年7月7日 星期二

UPnP Actoin Invoke

最近開始學習撰寫手機程式,這使我不得不思考過去一些使用 Library 能完成的事項要試著在沒有 Library 的情況下完成。以 UPnP Action 呼叫為例,在 Java 有 CyberLink for Java Library 能夠使用。

今天就在想,一個完整的 UPnP Library 包含 UPnP Device、Service 的組裝,並且在執行期負責做 Device、Service 的廣告。另外,它還需要提供 Control Point 與 UPnP Service 打交道。真的要使用 UPnP Service 您必需有 Control Point,UPnP 服務會以 Http Server 的方式,等待來自 Control Point Actoin Invoke。若僅是寫手持裝置上的 App 實在不需要整套 UPnP Library,頂多有 Control Point 就足夠。

不過,大家 Library 都相當完整不可分割。只好重新思考自己由底層的 protocol 下手。再次翻閱 UPnP 規格書,要對控制 UPnP Action 其實並不困難:


事實上,有了資料格式,整件事就簡化成了填空題。以操作 UPnP AV Media Server 內 Connection Manager 服務提供的 GetProtocolInfo Action 為例,下圖為 在 UPnP Spy 提供的視窗介面,您可以見到 GetProtocolInfo 有二個回傳變數 (無輸入變數),一個為 Source,另一個為 Sink,所以您應該要期待即使是使用 Socket 與 UPnP Service 溝通,也要有這項項回傳值:


而控制協定要求我們要填寫 POST Path,您可以在 Service Description Language 文件找到,透過 UPnP Spy 能知道此 Service 的控制 URL 為「_urn:schemas-upnp-org:service:ConnectionManager_control」。另外,您還需準備一個 SOAPACTION Header,規則是「serviceType + '#' + actionName」。最後 Http Body,依規格書的建議填上適當的 SOAP 標籤與 ActionName、ActionArgument,需傳送內容如下:

POST /_urn:schemas-upnp-org:service:ConnectionManager_control HTTP/1.1
HOST: 192.168.6.18
Content-Type: text/xml; charset="utf-8"
Content-Length: 313
SOAPACTION: "urn:schemas-upnp-org:service:ConnectionManager:1#GetProtocolInfo"
Connection: close

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:GetProtocolInfo xmlns:u="urn:schemas-upnp-org:service:ConnectionManager:1"></u:GetProtocolInfo>
</s:Body>
</s:Envelope>

如果,Action Invoke 成功,它就會回傳下列訊息:

HTTP/1.1 200 OK
EXT:
CONTENT-TYPE: text/xml ; charset="utf-8"
SERVER: Windows NT/5.0, UPnP/1.0, Intel CLR SDK/1.0
Content-Length: 521

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetProtocolInfoResponse xmlns:u="urn:schemas-upnp-org:service:ConnectionManager:1">
<Source>http-get:*:audio/mpeg:*,http-get:*:image/jpeg:*,http-get:*:text/plain:*,http-get:*:application/octet-stream:*,http-get:*:audio/x-mpegurl:*</Source>
<Sink />
</u:GetProtocolInfoResponse>
</s:Body>
</s:Envelope>

透過簡單的實驗知道,即使不依賴 Library 要實現簡單的 UPnP Control 是可行的。