Search code examples
c#monoxamarinxamarin.androidupnp

Discover devices mono.upnp


I'm trying to communicate with my new wemo switch over upnp. On windows this works just fine. Now I'm trying to do the same on android using the mono.upnp lib. Everything looks the same but I cant figuer out how to discover devices on mono.upnp.

Here is the code on windows:

    public static List<WeMoDevice> GetDevices ()
    {
        UPnPDeviceFinder finder = new UPnPDeviceFinder ();
        List<WeMoDevice> foundDevices = new List<WeMoDevice> ();


        string deviceType = "upnp:rootdevice";
        Device devices = finder.FindByType (deviceType, 1);


        foreach (Device device in devices) {
            if (device.Type.StartsWith ("urn:Belkin:")) {
                switch (GetDeviceType (device)) {
                case WeMoDeviceType.Switch:
                    WeMoSwitch wemoSwitch = new WeMoSwitch (device);
                    foundDevices.Add (wemoSwitch);
                    break;

                case WeMoDeviceType.Sensor:
                    WeMoSensor wemoSensor = new WeMoSensor (device);
                    foundDevices.Add (wemoSensor);
                    break;
                default:

                    break;

                }
            }
        }

        return foundDevices;
    }

I already changed the device class to the mono.upnp one but I cant seem to find the equivalent for UPnPDeviceFinder in mono.upnp.


Solution

  • Alright finally got it working. Here is the code I used to switch my wemo on and off:

        const string COMMAND_OFF = @"<?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:SetBinaryState xmlns:u=""urn:Belkin:service:basicevent:1""><BinaryState>0</BinaryState></u:SetBinaryState></s:Body></s:Envelope>";
        const string COMMAND_ON = @"<?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:SetBinaryState xmlns:u=""urn:Belkin:service:basicevent:1""><BinaryState>1</BinaryState></u:SetBinaryState></s:Body></s:Envelope>";
    
        public void On (string iP, string port)
        {
            SendCommand (COMMAND_ON, iP, port); 
        }
    
    
        public void Off (string iP, string port)
        {
            SendCommand (COMMAND_OFF, iP, port);
        }
    
        private void SendCommand (string command, string iP, string port)
        {
    
            string targetUrl = "http://" + iP + ":" + port + "/upnp/control/basicevent1";
    
    
            //  Create the packet and payload to send to the endpoint to get the switch to process the command
    
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create (targetUrl);
            request.Method = "POST";
            request.Headers.Add ("SOAPAction", "\"urn:Belkin:service:basicevent:1#SetBinaryState\"");
            request.ContentType = @"text/xml; charset=""utf-8""";
            request.KeepAlive = false;
            Byte[] bytes = UTF8Encoding.ASCII.GetBytes (command);
            request.ContentLength = bytes.Length;
            using (Stream stream = request.GetRequestStream ()) {
                stream.Write (bytes, 0, bytes.Length);
                stream.Close ();
                request.GetResponse ();
            }
    
    
            //  HACK: If we don't abort the result the device holds on to the connection sometimes and prevents other commands from being received
    
            request.Abort ();
        }
    
        public void GetDevice (string Name, wemoAction action)
        {
    
            try {
    
                Client client = new Client ();
    
                client.BrowseAll (); //Browse all available upnp devices
    
                client.DeviceAdded += (sender, e) => { //do something when a device is found
                    System.Console.WriteLine ("got one!");
                    if (e.Device.ToString ().Contains ("urn:Belkin")) {
    
                        if (e.Device.GetDevice ().FriendlyName.Equals (Name)) {
                            var url = e.Device.GetDevice ().Services.First ().EventUrl;
                            switch (action) {
                            case wemoAction.on:
                                On (url.DnsSafeHost, url.Port.ToString ());
                                break;
                            case wemoAction.off:
                                Off (url.DnsSafeHost, url.Port.ToString ());
                                break;
                            }
                        }
    
                    }
    
                };
    
    
            } catch (Exception ex) {
                System.Console.WriteLine (ex.Message);
            }
    
        }
    

    The code for sending the on and off packet are from this video: http://www.youtube.com/watch?v=ifzmJFdvNEE