[#1] How to connect to Hue Bridge | Philips Hue - C# Programming

in #programming7 years ago

How to connect to Hue Bridge

I'm currently working on a small App for the lightning system from Philips. They are doing a great job with the API but I didn't find much information for C#. So I decided to share my experience here on steemit. I'm by far not the best programmer - if you find something you would do different/better please give me feedback ;-)


In this first part of the Hue Tutorial Series we will focus on the Bridge. The Bridge is the brain of the System, so at first we need a connection to it! You can test it first with the built in debug tool from Hue in your web browser.

Just search for the IP Address from your Bridge.
Add
/debug/clip.html
at the end and go!
[Example: http://192.168.1.2/debug/clip.html]

You should now see the CLIP API Debugger Interface:

This site is just for testing but you can already create an user!
URL: /api
Message Body: {"devicetype":"testHueApp#YourName"}

Click on Post

You will get an error because you didn't press the button on the Bridge. So press it and click on Post again

Tadaaa - User created! ;-)

You can do a lot more with the CLIP API!
For more information Sign Up on MeetHue
and go to the Docs at Step 3: Docs

Nice - but we want our own program!?

Right - lets go :-)

Open Visual Studio and create a new Project. I'm using a WinForms Project for this :-)
My GUI


First of all we need the IP Address from the Bridge. For this task I'm using a NuGet Package called "Rssdp" NuGet. Install it for you Project and add a Class - i called it HueLogic.cs.
First of all add all the usings we will need:

using Rssdp;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

Add the following Method:

public void FindBridgeIP()
{
    SsdpDeviceLocator deviceLocator = new SsdpDeviceLocator(GetLocalIPAddress().ToString());
    var foundDevices = deviceLocator.SearchAsync().Result.ToList();
}

SsdpDeviceLocator from Rssdp needs your IP in the local network as parameter - add:

private IPAddress GetLocalIPAddress()
{
    if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
        return null;

    return Dns.GetHostEntry(Dns.GetHostName())
        .AddressList
        .FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
}

deviceLocator.SearchAsync().Result gives back all Devices it found at the local network.
Now we just have to search for the word "IpBridge" in the ResponseHeader of a device.
Add the following to the FindBridgeIP Method: (just working for one Bridge)

foreach (var device in foundDevices)
{
    if (device.ResponseHeaders.ToString().Contains("IpBridge"))
    {
        BridgeIP = device.DescriptionLocation.Host;
                return;
    }
        BridgeIP = "not Found";
}

Add the public Property:

public static string BridgeIP;

Just call FindBridgeIP in your GUI and you will receive the IP.

private void btnFindIp_Click(object sender, EventArgs e)
{
    HueLogic.FindBridgeIP();
    txtIp.Text = HueLogic.BridgeIP;
}

Now we are able to create an user!
Back to our HueLogic class add the following:

public static string Usercode;

private const string APIAddressTemplate = "http://{0}/api";
private const string BodyTemplate = "{{\"devicetype\":\"{0}\"}}";

public static string ConnectBridge(string username)
{
      return PostRequestToBridge(
           string.Format(APIAddressTemplate, BridgeIP),
           string.Format(BodyTemplate, username));
}

private static string PostRequestToBridge(string uri, string data, string contentType = "application/json", string method = "POST")
{
    byte[] dataBytes = Encoding.UTF8.GetBytes(data);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
    request.ContentLength = dataBytes.Length;
    request.ContentType = contentType;
    request.Method = method;

    using (Stream requestBody = request.GetRequestStream())
    {
        requestBody.Write(dataBytes, 0, dataBytes.Length);
    }

    //search for easier way
    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using (Stream stream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(stream))
    {
        string json = reader.ReadToEnd();

        var result = ResultHelper.FromJson(json);
        Usercode = result.First().Success.Username;

        return json;
    }          
}

We are doing nothing different as in the web tool I mentioned at the beginning => Post Request containing the username.

I'm using Newtonsoft.Json for parsing and reading the JSON strings.

Here is the ResultHelper.cs Class: (generated with http://json2csharp.com/)

public partial class ResultHelper
    {
        [JsonProperty("success")]
        public Success Success { get; set; }
    }

    public partial class Success
    {
        [JsonProperty("username")]
        public string Username { get; set; }
    }

    public partial class ResultHelper
    {
        public static ResultHelper[] FromJson(string json) => JsonConvert.DeserializeObject<ResultHelper[]>(json, Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this ResultHelper[] self) => JsonConvert.SerializeObject(self, Converter.Settings);
    }

    public class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
        };
    }

Now just call it from your GUI and show the result:

private void btnConnect_Click(object sender, EventArgs e)
{
    if (string.IsNullOrEmpty(txtUsername.Text))
        txtUsername.Text = "test";

    txtResult.Text = HueLogic.ConnectBridge(txtUsername.Text);
    txtUsername.Text = HueLogic.Usercode;
}

With the username we can now control the light! More in the next Post :-)