C# 使用UPnP.FindByType查找Belkin WeMo设备
我正在尝试创建一个用于控制WeMo设备的C#应用程序。我遵循了Bernacules给出的代码示例和说明 代码的相关位粘贴在下面C# 使用UPnP.FindByType查找Belkin WeMo设备,c#,upnp,C#,Upnp,我正在尝试创建一个用于控制WeMo设备的C#应用程序。我遵循了Bernacules给出的代码示例和说明 代码的相关位粘贴在下面 private void GetAllDevices() { var finder = new UPnPDeviceFinder(); var foundDevices = new List<UPnPDevice>(); var deviceType = "upnp:rootdevice"; var devices = fi
private void GetAllDevices()
{
var finder = new UPnPDeviceFinder();
var foundDevices = new List<UPnPDevice>();
var deviceType = "upnp:rootdevice";
var devices = finder.FindByType(deviceType, 1);
foreach (UPnPDevice upnpDevice in devices)
{
if (upnpDevice.Type.StartsWith("urn:Belkin:"))
{
....
}
}
}
private void GetAllDevices()
{
var finder=new UPnPDeviceFinder();
var foundDevices=新列表();
var deviceType=“upnp:rootdevice”;
var devices=finder.FindByType(deviceType,1);
foreach(UPnPDevice UPnPDevice-in-devices)
{
if(upnpDevice.Type.StartsWith(“urn:Belkin:”))
{
....
}
}
}
当我迭代UPnPDeviceFinder找到的设备时,我想到了各种各样的东西,我的媒体服务器,在我的Android手机上运行的一些应用程序,我的Chromecast,但没有WeMos,甚至没有任何东西能远程将Belkin放在骨灰盒中
在谷歌搜索了一段时间后,我找到了一个可以让我找出如何查询每个设备的“setup.xml”的方法。通过将上面代码中的“upnp:rootdevice”替换为xml中的值(我相信它是“urn:Belkin:device:controllee:1”),我从UPnPDeviceFinder得到了0个结果。我猜Belkin最近改变了他们的配置,但是有没有一个更具网络Saaveness的人能告诉我,我可以使用什么值来查找我的WeMos?你使用的是什么版本的windows 我的UPnP扫描仪在Windows7上可以找到Wemo,但在Windows8.1上不起作用
在Windows 8.1上,所有其他UPnP设备都会显示,但Wemo根本不会显示。具有
UPnP:rootdevice
属性的Wemo在Windows 10上也找不到。你有没有把你的“另一种方式”贴出来。另一方面,我正在考虑记录MAC,然后每次做一次ARP,看看IP地址是否改变,检查端口49152、49153、49154(据我所知,它们可能会改变)我设法找到了解决办法。这是一个有点黑客,并没有真正使用upnp协议(因为我无法让它在Windows10上工作)
基本上,我们所做的是使用netsh命令来获取设备列表及其地址。然后,我们尝试在我们知道wemo设备可以运行的不同端口上访问setup.xml。当我们得到正确的响应时,它包含所有upnp设备信息,然后我们可以解析这些信息,以了解有关该设备的任何信息。在这个示例中,我只是做了一个简化的解析,只是检查它是否包含单词“Belkin”。它确实做了一些工作,但我们应该解析UDN以确定模型,并向最终用户显示friendlyName。否则,贝尔金制造的其他设备可能会出现
这种方法在Windows 10 pc上确实适用。我还没有尝试过其他平台。这是一种蛮力方法,但所有请求都是异步并行的,所以我们很快就能得到响应。不管怎么说,这门课发挥了所有的魔力:
public class WemoScanner
{
public delegate void WemoDeviceFound(WemoDevice device);
public event WemoDeviceFound OnWemoDeviceFound;
public void StartScanning()
{
var addresses = GetAddresses().Where(a => a.Type == "Dynamic");
var tasks = addresses.SelectMany(CheckWemoDevice);
Task.Run(async () => { await Task.WhenAll(tasks).ConfigureAwait(false); });
}
public List<WemoDevice> GetWemoDevices()
{
var devices = new List<WemoDevice>();
OnWemoDeviceFound += device => devices.Add(device);
var addresses = GetAddresses().Where(a => a.Type == "Dynamic");
var tasks = addresses.SelectMany(CheckWemoDevice);
Task.WhenAll(tasks).GetAwaiter().GetResult();
return devices;
}
private NetshResult[] GetAddresses()
{
Process p = new Process();
p.StartInfo.FileName = "netsh.exe";
p.StartInfo.Arguments = "interface ip show ipnet";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
var lines =
output.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
.SkipWhile(l => !l.StartsWith("--------"))
.Skip(1);
var results =
lines.Select(l => new NetshResult(l.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)))
.ToArray();
return results;
}
private IEnumerable<Task> CheckWemoDevice(NetshResult netshResult)
{
var tasks = new List<Task>();
for (uint i = 49150; i <= 49156; i++)
{
tasks.Add(CheckWemoDevice(netshResult.IpAddress, i));
}
return tasks;
}
private async Task CheckWemoDevice(string ip, uint port)
{
var url = $"http://{ip}:{port}/setup.xml";
try
{
using (var wc = new WebClient())
{
var resp = await wc.DownloadStringTaskAsync(url);
if (resp.Contains("Belkin")) // TODO: Parse upnp device data and determine device
OnWemoDeviceFound?.Invoke(new WemoDevice {Address = ip, Port = port});
}
}
catch (Exception)
{
}
}
}
用法相当简单。如果希望它以异步方式(在后台)运行,只需连接到eventOnWemoDeviceFound
并调用StartScanning()
,如下所示:
var scanner = new WemoScanner();
scanner.OnWemoDeviceFound += device => Console.WriteLine($"{device.Address}:{device.Port}");
scanner.StartScanning();
否则,如果您想要一个同步运行并返回设备列表的方法,只需调用
GetWemoDevices()
。请注意,这并不是真正的建议,因为在所有“无效”请求发生超时之前,它不会返回。如果您想缩短web请求的超时时间,可以修改该超时时间。我知道这是一个非常古老的线程,但我在2018年无法在Windows 10上使用上述任何解决方案。我能够在Windows10上使用@Inrego和类的代码组合,检查开放端口49153
public IList<WemoDevice> GetWemoIPs()
{
var wemos = new List<WemoDevice>();
Parallel.For(1, 255, (i) =>
{
var ip = string.Format(this.IpFormat, i);
var device = new WemoDevice(ip);
if (IsWemo(ip))
wemos.Add(device);
});
return wemos;
}
public bool IsWemo(string ipAddress)
{
using (TcpClient tcpClient = new TcpClient())
{
try
{
tcpClient.Connect(ipAddress, 49153);
return true;
}
catch
{
return false;
}
}
}
public IList GetWemoIPs()
{
var wemos=新列表();
对于(1255,(i)=>
{
var ip=string.Format(this.IpFormat,i);
var设备=新的WemoDevice(ip);
if(IsWemo(ip))
添加(设备);
});
返回wemos;
}
公共bool IsWemo(字符串ipAddress)
{
使用(TcpClient TcpClient=new TcpClient())
{
尝试
{
tcpClient.Connect(ipAddress,49153);
返回true;
}
抓住
{
返回false;
}
}
}
天哪,你成功了。我一直在使用Windows8.1。我在Windows7机器上运行了代码,它检测到了WeMos。至少现在我知道它与UPNPLib.dll有关,而不是WeMo固件的更改。这就引出了一个问题。。。有什么解决办法吗?很抱歉撞到这么旧的帖子。但是有人把它用在8.1上了吗?我找到了另一种方法!我将写一个小的库来发布在GitHub上,然后带着一个链接回到这里。@Inrego你已经将它发布在GitHub上了吗?我感觉到了冲动!你发布了吗?不幸的是,我发现的“另一种方式”在Windows 10中停止工作(它在8.1中工作)。相反,我找到了一种黑客/野蛮的方式来发现Wemo设备。请看我今天提交的答案。好的,我花了一些时间来尝试这个。我同意这有点粗俗。但是嘿。。。你成功了,其他人都没有。干得好,很有效。很抱歉出现了两篇帖子,现在编辑上一篇已经太晚了。这里有两件事可以帮助下一个人。1) 您可以添加p.StartInfo.CreateNoWindow=true;使netsh.exe窗口不闪烁。2) netsh.exe的结果将转换为操作系统语言,您可能还需要检查您的语言。例如,我所做的是:var addresses=GetAddresses(),其中(a=>a.Type==“Dynamic”| | a.Type==“Dynamique”);支持法语和英语(我的操作系统是法语)
public IList<WemoDevice> GetWemoIPs()
{
var wemos = new List<WemoDevice>();
Parallel.For(1, 255, (i) =>
{
var ip = string.Format(this.IpFormat, i);
var device = new WemoDevice(ip);
if (IsWemo(ip))
wemos.Add(device);
});
return wemos;
}
public bool IsWemo(string ipAddress)
{
using (TcpClient tcpClient = new TcpClient())
{
try
{
tcpClient.Connect(ipAddress, 49153);
return true;
}
catch
{
return false;
}
}
}