2012-12-09 17 views
6

डिवाइस: मैं Windows से C++ का उपयोग कर एक UPnP डिवाइस की सेवाओं की गणना करने में कोशिश कर रहा हूँ Windows 7मैं यूपीएनपी डिवाइस की सेवाओं तक कैसे पहुंच सकता हूं?

पर एमएस कुलपति ++ 2010: Belkin WEMO
देव पर्यावरण स्विच।

मुझे IUPnPDevice पॉइंटर मिला है और कई गुणों तक पहुंच सकते हैं।
मुझे IUPnPServices पॉइंटर मिला है और सेवाओं की सही संख्या (7) की गणना कर सकते हैं।
पॉइंटर (जो सफल होने के लिए प्रतीत होता है) प्राप्त करने के लिए QueryInterface() का उपयोग करता हूं।
हालांकि, Next() विधि 0x80040500 के साथ हमेशा विफल रहता है - जो Windows error 1280 (0x500) - ERROR_ALREADY_FIBER के रूप में अनुवाद करता है।
यह त्रुटि मुझे कोई समझ नहीं देती है।

(मैं दोनों IEnumVARIANT और IEnumUnknown का उपयोग कर की कोशिश की है -। के रूप में किए गए दस्तावेज़ों से संकेत मिलता है यह या तो हो सकता है, लेकिन दोनों एक ही परिणाम का उत्पादन)

मैं पूरा स्रोत फ़ाइल नीचे दिये है, के साथ साथ उत्पादन यह पैदा करता है।
[नोट: यह मेरे अपने डिवाइस के udn का उपयोग करने के लिए हार्डकोड किया गया है]

यदि मैं वर्तमान में फंस गया हूं तो कोई भी मदद कर सकता है, तो मैं बहुत आभारी हूं।

सादर,
डेव

कोड:

// UpnpTest1.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 

#include <windows.h> 
#include <upnp.h> 

static void DumpComError(const TCHAR *api, HRESULT hr); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int retcode=-1; // assume failure 

    HRESULT hr = CoInitialize(0); 
    if (hr==S_OK) 
    { 
    IUPnPDeviceFinder *deviceFinder=0; 
    hr = CoCreateInstance(CLSID_UPnPDeviceFinder, 0, CLSCTX_INPROC_SERVER, IID_IUPnPDeviceFinder, (void**)&deviceFinder); 
    if (hr==S_OK) 
    { 
     IUPnPDevice *device=0; 
     hr = deviceFinder->FindByUDN(L"uuid:Socket-1_0-221239K11002F6", &device); 
     if (hr==S_OK) 
     { 
     if (device) 
     { 
      TCHAR *manufacturer=0, *manufacturerUrl=0; 
      TCHAR *description=0, *name=0, *modelUrl=0; 
      TCHAR *serialNumber=0, *udn=0, *upc=0, *deviceType=0; 
      TCHAR *presentationUrl=0; 

      device->get_ManufacturerName(&manufacturer); 
      device->get_ManufacturerURL(&manufacturerUrl); 
      device->get_Description(&description); 
      device->get_FriendlyName(&name); 
      device->get_ModelURL(&modelUrl); 
      device->get_SerialNumber(&serialNumber); 
      device->get_UniqueDeviceName(&udn); 
      device->get_UPC(&upc); 
      device->get_Type(&deviceType); 
      device->get_PresentationURL(&presentationUrl); 

      _tprintf(_T("MANUFACTURER: %s [%s]\n"), manufacturer, manufacturerUrl); 
      _tprintf(_T("MODEL:  %s [%s]\n    [%s]\n"), description, name, modelUrl); 
      _tprintf(_T("DEVICE:  serial=%s\n    udn=%s\n    upc=%s\n    type=%s\n"), serialNumber, udn, upc, deviceType); 
      _tprintf(_T("URL:   %s\n"), presentationUrl); 

      IUPnPServices *services=0; 
      hr = device->get_Services(&services); 
      if (hr==S_OK) 
      { 
      if (services) 
      { 
       long numberOfServices=0; 
       services->get_Count(&numberOfServices); 

       if (numberOfServices>0) 
       { 
       IUnknown *unknown=0; 
       hr = services->get__NewEnum(&unknown); 
       if (hr==S_OK) 
       { 
        if (unknown) 
        { 
        IEnumVARIANT *enumInterface=0; 
        hr = unknown->QueryInterface(IID_IEnumVARIANT,(void**)&enumInterface); 
        if (enumInterface) 
        { 
         VARIANT var; 
         unsigned long fetched=0; 
         hr = enumInterface->Next(1, &var, &fetched); 

         if (hr==S_OK) 
         { 

         } 
         else 
         DumpComError(_T("IEnumVARIANT::Next"), hr); 
        } 
        else 
         DumpComError(_T("IUnknown::QueryInterface"), hr); 
        } 
        else 
        fprintf(stderr, "Failed to get enumeration interface.\n"); 
       } 
       else 
        DumpComError(_T("IUPnPServices::get__NewEnum"), hr); 
       } 
       else 
       fprintf(stderr, "No services available.\n"); 
      } 
      else 
       fprintf(stderr, "Failed to get services collection.\n"); 
      } 
      else 
      DumpComError(_T("IUPnPDevice::get_Services"), hr); 
     } 
     else 
      fprintf(stderr, "Device not found.\n"); 
     } 
     else 
     DumpComError(_T("IUPnPDeviceFinder::FindByUDN"), hr); 
    } 
    else 
     DumpComError(_T("CoCreateIndex"), hr); 
    } 
    else 
    DumpComError(_T("CoInitialize"), hr); 

    return retcode; 
} 

static void AddBoolToString(const TCHAR *name, bool value, TCHAR *buf, int &i, int max) 
{ 
    if (name && *name && value && buf && i>=0) 
    i += _snwprintf_s(&buf[i], max-i, (max-i-1)*sizeof(TCHAR), _T("%s%s=YES"), (i>0? _T("; "): _T("")), name); 
} 

static void AddIntToString(const TCHAR *name, int value, TCHAR *buf, int &i, int max) 
{ 
    if (name && *name && value && buf && i>=0) 
    i += _snwprintf_s(&buf[i], max-i, (max-i-1)*sizeof(TCHAR), _T("%s%s=%d"), (i>0? _T("; "): _T("")), name, value); 
} 

static void DumpComError(const TCHAR *api, HRESULT hr) 
{ 
    bool failure = (hr&0x80000000? true: false); 
    bool severe = (hr&0x40000000? true: false); 
    bool microsoft = (hr&0x20000000? false: true); 
    bool ntStatus = (hr&0x10000000? true: false); 
    bool xBit  = (hr&0x08000000? true: false); 
    int facility = (hr&0x07FF0000)>>16; 
    int code  = (hr&0x0000FFFF); 

    TCHAR buf[1024]={0}; 
    int bufsize = sizeof(buf)/sizeof(TCHAR); 
    int i=0; 

    AddBoolToString(_T("failure"), failure, buf, i, bufsize); 
    AddBoolToString(_T("severe"), severe, buf, i, bufsize); 
    AddBoolToString(_T("microsoft"), microsoft, buf, i, bufsize); 
    AddBoolToString(_T("ntStatus"), ntStatus, buf, i, bufsize); 
    AddBoolToString(_T("xBit"), xBit, buf, i, bufsize); 
    AddIntToString(_T("facility"), facility, buf, i, bufsize); 
    AddIntToString(_T("code"), code, buf, i, bufsize); 

    _ftprintf(stderr, _T("\n%s() failed, hr=0x%08x\n[%s]\n"), api, hr, buf); 
} 

आउटपुट: यह निम्न उत्पादन उत्पादन:

MANUFACTURER: Belkin International Inc. [http://www.belkin.com/] 
MODEL:  Belkin Plugin Socket 1.0 [WeMo Switch] 
       [http://www.belkin.com/plugin/] 
DEVICE:  serial=221239K11002F6 
       udn=uuid:Socket-1_0-221239K11002F6 
       upc=123456789 
       type=urn:Belkin:device:controllee:1 
URL:   http://192.168.1.16:49153/pluginpres.html 

IEnumVARIANT::Next() failed, hr=0x80040500 
[failure=YES; microsoft=YES; facility=4; code=1280] 

संपादित करें:

बहुत सारे मृत-सिरों के बाद, मैंने मैन्युअल रूप से एसओएपी अनुरोधों का निर्माण करके और विंडोज सॉकेट का उपयोग कर टीसीपी के माध्यम से अनुरोध भेजकर काम किया है। ट्रिकी बिट सिंटैक्स को ठीक से प्राप्त कर रहा था क्योंकि मुझे पहले एसओएपी का कोई अनुभव नहीं था। [यूपीएनपी आईपी एड्रेस & पोर्ट नंबर की पहचान करने के लिए उपयोगी था - क्योंकि ये बदल सकते हैं]। एक बार ऊपर और चलना - यह वास्तव में यूपीएनपी इंटरफेस से बहुत आसान है। यदि आप रुचि रखते हैं तो मुझे बताएं और मैं कोड पोस्ट कर सकता हूं ... यह मेरे द्वारा यहां दिए गए प्रश्न का सीधे उत्तर नहीं देता है, इसलिए इस विवरण के साथ मेरे प्रश्न का उत्तर देना समझ में नहीं आता है।

हालांकि, यदि आप रुचि रखते हैं, तो मुझे बताएं और मैं कोड पोस्ट कर सकता हूं।

चीयर्स,
डेव

+0

नोट: इस पृष्ठ से [http://www.issackelly.com/blog/2012/07/30/wemo-hacking/] आप सेवाओं की सूची देख सकते हैं, इसलिए सिद्धांत में मुझे पहुंचने में सक्षम होना चाहिए IUPnPServices :: get_Item() का उपयोग कर सीधे सेवा, मैं यह नहीं समझ सकता कि serviceId (पहला पैरामीटर) के लिए सही प्रारूप क्या है ... – user390935

+0

नोट 2: मैंने IUPnPService :: get_Item (L "urn: Belkin: serviceId: basicevent1 का उपयोग करने का प्रयास किया ", और सेवा आईडी); हालांकि HRESULT वापस लौटा है (0x80040500) – user390935

+0

हां @ user390935, अपना कोड पोस्ट करें। मैं मंच तटस्थ एसएसडीपी ग्राहक की तलाश में था। – Vink

उत्तर

2

0x80040500 की HRESULT आप क्या सोचते नहीं है, लेकिन UPNP_E_INVALID_DOCUMENT। इस तरह की अस्पष्टता के बारे में स्पष्टीकरण के लिए, my answer in another SO question देखें।

मेरा अनुमान है कि आपका बेल्किन डिवाइस गैर-अनुरूप डिवाइस विवरण या सेवा विवरण XML दे रहा है। गैर-अनुरूपता का मतलब टूटा प्रारूप नहीं है, यूपीएनपी विनिर्देश में कई माध्यमिक आवश्यकताएं हैं। यदि डिवाइस पॉप अप हो जाता है, तो डिवाइस डेवलपर टूल्स (अन्य उत्तर के नीचे लिंक) से डिवाइस जासूस आज़माएं, फिर डिवाइस वैलिडेटर को उसी सूट से चलाएं।

+0

इसके लिए धन्यवाद ... मुझे सुविधा 4 के रूप में जाना जाना चाहिए था। मुझे लगता है कि इसका मतलब है कि विंडोज डिवाइस से प्रतिक्रिया वापस पसंद नहीं करता है। – user390935

+0

हां, यह मेरा अनुमान है। HRESULT ओएस/2 के साथ 20 साल की संगतता की एक भयानक विरासत है। सभी "उपयोगकर्ता परिभाषित कोड" के लिए केवल एक FACILITY_ITF है जो स्वयं में काफी खराब है, लेकिन माइक्रोसॉफ्ट अपने स्वयं के नए एपीआई के लिए एक ही सुविधा का उपयोग कर रहा है, जहां यह एक और अप्रयुक्त कोड का उपयोग कर सकता था। –

0

मेरा अनुभव समान है, उस UPnPDeviceFinder में बस काम नहीं करता है। यह यूपीएनपी खोज पैकेट को कभी नहीं भेजता है, इसलिए डिवाइस प्रतिक्रिया नहीं देते हैं। इसे काम करने का एकमात्र तरीका यह है कि यदि आप खोज शुरू करने के लिए विंडोज मीडिया प्लेयर या "कास्ट टू डिवाइस" मेनू (जो डब्लूएमपी है) का उपयोग करते हैं। चूंकि यह UPnPDeviceFinder कुछ डिवाइस लौटाएगा, केवल तभी जब वे उस पल में प्रसारण कर रहे हों, लेकिन एक्सबॉक्स (एक और माइक्रोसॉफ्ट उत्पाद) भी ढूंढना अन्य गतिविधियों के बिना उदाहरणों में काम नहीं करता है।

संबंधित मुद्दे