Thiết bị này: Belkin Wemo Chuyển
Dev môi trường: MS VC++ 2010 trên Windows7Tôi làm cách nào để truy cập các dịch vụ của thiết bị UPnP?
Tôi đang cố gắng để liệt kê các dịch vụ của một thiết bị UPnP sử dụng C++ từ Windows.
Tôi có con trỏ IUPnPDevice
và có thể truy cập một số thuộc tính.
Tôi có con trỏ IUPnPServices
và có thể đếm số lượng dịch vụ chính xác (7).
Tôi sử dụng QueryInterface()
để có được con trỏ IEnumVARIANT
(dường như thành công).
Tuy nhiên, phương pháp Next()
luôn không thành công với HRESULT
của 0x80040500
- được dịch là Windows error 1280 (0x500) - ERROR_ALREADY_FIBER
.
Lỗi này không có ý nghĩa gì đối với tôi.
(Tôi đã thử sử dụng cả hai IEnumVARIANT
và IEnumUnknown
-. Như các tài liệu cho thấy nó có thể là một trong hai, nhưng cả hai đều tạo ra kết quả tương tự)
Tôi đã bao gồm bên dưới file nguồn đầy đủ, cộng với đầu ra nó sản xuất.
[Lưu ý: Mã này được mã hóa cứng để sử dụng udn của thiết bị của riêng tôi]
Tôi rất biết ơn nếu có ai có thể trợ giúp như tôi hiện đang bị kẹt.
Trân trọng,
Dave
Code:
// 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);
}
Output: nó tạo ra sau đầu ra:
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]
EDIT:
Sau rất nhiều kết thúc chết, tôi đã quản lý để làm việc này bằng cách thủ công xây dựng các yêu cầu SOAP và gửi các yêu cầu qua TCP bằng cách sử dụng các ổ cắm Windows. Bit khó hiểu đã nhận được cú pháp vừa phải như tôi đã không có kinh nghiệm của SOAP trước đây. [UPnP hữu ích khi xác định địa chỉ IP & số cổng - vì chúng có thể thay đổi]. Khi lên và chạy - nó thực sự đơn giản hơn rất nhiều so với giao diện UPnP. Hãy cho tôi biết nếu bạn quan tâm và tôi có thể đăng mã ... Nó không trực tiếp trả lời câu hỏi tôi đặt ra ở đây, vì vậy sẽ không có ý nghĩa gì khi trả lời câu hỏi của tôi với chi tiết này.
Tuy nhiên, nếu bạn quan tâm, hãy cho tôi biết và tôi có thể đăng mã.
Chúc mừng,
Dave
Lưu ý: Từ trang này [http://www.issackelly.com/blog/2012/07/30/wemo-hacking/] bạn có thể xem danh sách dịch vụ, vì vậy về lý thuyết tôi có thể truy cập dịch vụ trực tiếp sử dụng IUPnPServices :: get_Item() tuy nhiên, tôi không thể tìm ra định dạng đúng cho serviceId (tham số đầu tiên) ... – user390935
Note2: Tôi đã thử sử dụng IUPnPService :: get_Item (L "urn: Belkin: serviceId: basicevent1 ", & serviceId); tuy nhiên HRESULT được trả lại giống như trước (0x80040500) – user390935
Có @ user390935, đăng mã của bạn. Tôi đang tìm kiếm nền tảng máy khách SSDP trung lập. – Vink