Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用UPnP.FindByType查找Belkin WeMo设备_C#_Upnp - Fatal编程技术网

C# 使用UPnP.FindByType查找Belkin WeMo设备

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

我正在尝试创建一个用于控制WeMo设备的C#应用程序。我遵循了Bernacules给出的代码示例和说明

代码的相关位粘贴在下面

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)
        {

        }
    }
}
用法相当简单。如果希望它以异步方式(在后台)运行,只需连接到event
OnWemoDeviceFound
并调用
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;
                }
            }
        }