Developing the Internet of Things: Philips Hue Lux Starter Kit

Posted by on in Tutorial

Header-Hue-Lux-Multi-Device

There was a time when commanding light by flicking a mechanical switch was a revolutionary act. Today, our desire to control light has reached a new technological pinnacle. Growing tired of the physically arduous task of flicking a switch? Thanks to the Internet of Things, you are in luck! So sit back, relax, and read on to find out how to control light by making RESTful API calls!

In this blog post, discover how Appmethod and the REST Debugger enables developers to create native multi-device applications that interface with the Philips Hue Lux Starter Kit over REST.

 

 

Light and the Internet of Things 

The Internet of Things brings hyper-connectivity to the ordinary objects found within our homes. Connecting these everyday objects to the internet will enable them to know us; to know what we need and when we need it. Wearables track our sleeping patterns and know when we wake up, beacons keep track of when and where we are in the house, even our mood is tracked by the sentiment of tweets we send out or the kind of music being listened too.

Light, therefore, will come to know us. It will automatically turn on before you enter a dark room and turn off after you leave it. Light becomes a novel source of information, flashing when an important event occurs, like when your favorite sports team scores a goal. Thanks to the Internet of Things, control over light itself has new kind of relevance and application to our day to day life.

Philips Hue Lux Starter Kit

Philips has entered the smart home automation consumer space of Internet of Things applications with its Hue Lux Starter Kit. The starter kit ships with two Hue Lux bulbs and one bridge. The bridge is a controller that connects over the wire to a local network and supports up to 50 Hue lights. The Hue Lux is an A19 bulb capable of producing dimmable white light. Philips has opened an informative micro-site called meethue.com which showcases 3rd party apps that add connected functionality to how we experience light.


Appmethod Philips Hue Lux Control App Project Files

Download a free copy of Appmethod and explore this multi-device application as you follow along this blog post.

Download the project files!

 

Controlling Philips Hue Lux with Appmethod REST Debugger

The REST Debugger is built on top of the Embarcadero REST Library, which is a framework for accessing REST-based web services (REST stands for Representational State Transfer). The REST Debugger allows developers to make ad hoc RESTful API calls and easily spelunk through any returned JSON blobs. The REST Debugger is capable of generating REST components which can be directly copy and pasted into the Appmethod IDE. This is a very convenient, fast, and powerful approach to prototype and build REST integration and tie in functionality with your application.

Step One: Discover the Bridge

The first step to controlling the Hue Lux bulb over the Philips REST API is to discover available bridges.

The Hue Bridge Discovery Guide offers advice on how to use a N-UPnP web service to obtain the local network IP address of the Bridge. This web service is addressable at https://www.meethue.com/api/nupnp and will return a JSON blog with the device info.

Open the REST Debugger by clicking Tools -> REST Debugger

Ensure the Method is set to GET and enter https://www.meethue.com/api/nupnp in the URL field.

Press Send Request.

The returned JSON blob is viewable In the lower half of the REST Debugger window the Body tab.
Set the JSON Root Element to [0].internalipaddress to narrow the selection of the JSON content to the internal ip address.

REST-Debugger-nupnp

Step Two: Authenticate With the Bridge

Before any API calls can be made, an authenticated user must be added to the Bridge. The link button on the bridge must be pressed before this API is called. To register a new user using the REST Debugger follow these steps:

On the Request tab, set Method to POST, URL to the obtained internal IP address of the bridge, and Content-Type to application/json.

The Custom body will contain the json blog with the username information we wish to register to the Bridge.

{"devicetype": "ApplicationName#DeviceName ", "username": "AppmethodTestUser"}

On the Parameters tab, enter /api in the Resource field.

REST-Debugger-Auth

Step Three: Discover and Query Lights State

From the Request tab set the Method to GET, the URL to the internal IP address of the Bridge, and from the Parameters tab set the Resource to /api/<username>/lights

Press Send Request.

The Body tab should display the JSON blob that represents all known lights and their current state.

Notice the property reachable. If this is set to false it means the Bridge knows about this light but it is not addressable likely because it does not have power.

Step Four:  Control Hue Lux Lights State

Now that both the Bridge IP is known and the username has been added to the Bridge white list, its time to control light.

From the REST Debugger Request tab set the Method to PUT and enter the Bridge internal IP address into the URL field, and the Content-Type to application/json.

The Custom body will contain the JSON blob contains directives for setting the state of the Hue Lux bulb. To tell the light to turn on enter:

{ "on": true }

On the Parameters tab set the Resource field to /api/<username>/lights/<light id>/state

Pressing Send Request should turn the targeted Hue Lux bulb on or off depending upon the boolean set in the JSON body.

Building Appmethod Hue Lux Control App - UI


Video not found or Youtube service not available
 

Building Appmethod Hue Lux Control App - Logic

The following code will discover available bridges, discover available lights and their state, and handle basic application UI state.

Finding Bridges

void __fastcall TForm1::HandleFindBridges() {
 
    Memo1->Lines->Add( "Finding Bridges via https://www.meethue.com/api/nupnp" );
 
 
 
    FindHueBridgeRESTRequest->Execute();
 
    TJSONObject * json      = static_cast<TJSONObject *> ( FindHueBridgeRESTResponse->JSONValue );
    NumBridgesFound         = json->Count;
 
    if ( json == NULL ) {
        Memo1->Lines->Add( "Error connecting to bridge discover service." );
    }
    else if ( json->Count > 0 ) {
        for ( int i = 0; i < NumBridgesFound; i++ ) {
            FindHueBridgeRESTResponse->RootElement   = String("[") + i + String("].internalipaddress");
            json = static_cast<TJSONObject *> ( FindHueBridgeRESTResponse->JSONValue );
            HueBridgeIPsComboBox->Items->Add( json->Value() );
 
            Memo1->Lines->Add( "Bridge found, IP:" + json->Value() );
        }
 
        //- set active index to first bridge added
        HueBridgeIPsComboBox->Enabled    = true;
        HueBridgeIPsComboBox->ItemIndex = 0;
 
        //- update base url
        UpdateBaseURL();
 
 
        //- enable app authorization button
        //      authorization only needs to occur once
        //      to authenticate, the link button on the bridge must first be
        //      pushed.
        AuthenticateAppButton->Enabled   = true;
 
        //- we found one or more bridges, so now discover lights
        HandleFindLights();
    }
    else{
        Memo1->Lines->Add( "No bridges found." );
    }
}

A set of REST Components were pasted in from the REST Debugger to handle authentication API calls. Calling the Execute method of the Request Component will perform the API call.

Then the returned Bridges are iterated over and added to the application.

void __fastcall TForm1::UpdateBaseURL(){
    BaseURL = String("http://") + HueBridgeIPsComboBox->Selected->Text + String("/api/");
}

Authenticating User

void __fastcall TForm1::HandleAuthentication() {
    TJSONObject * json;
    AddUserRESTClient->BaseURL = BaseURL;
    AddUserRESTRequest->Params->Items[0]->Value = "{\"devicetype\":\"test user\",\"username\":\"" + String(UserName) + "\"}";
    AddUserRESTRequest->Execute();
 
    Memo1->Lines->Add( "Authentication request sent." );
 
    //- test for error, here we assume just one bridge is found.
    AddUserRESTResponse->RootElement = "[0].error.description";
    json = static_cast<TJSONObject *> ( AddUserRESTResponse->JSONValue );
 
    if ( json != NULL) {
        Memo1->Lines->Add( "Authentication error: " + json->Value() );
    }
    else {
        //- display succesfull pairing info
        AddUserRESTResponse->RootElement = "[0].success.username";
        json = static_cast<TJSONObject *> ( AddUserRESTResponse->JSONValue );
 
        if ( json != NULL) {
            Memo1->Lines->Add( "Username " + json->Value() + " validaded. Application authorized." );
 
            //- now that the app is authorized, discover lights
            HandleFindLights();
        }
    }
}

A set of REST Components were setup and copied form the REST Debugger to handle authentication.

The base url is updated to the selected bridge. The JSON body is updated to include the application username. If the returned JSON data is successful then the username is verified as authenticated and the process of finding the available lights begins.

Finding Lights

void __fastcall TForm1::HandleFindLights() {
    HueRESTRequest->Method   = Rest::Types::rmGET;
    HueRESTClient->BaseURL   = BaseURL;
    HueRESTRequest->Resource = UserName + String("/lights");
    HueRESTRequest->Execute();
 
    Memo1->Lines->Add( "Finding Lights." );
 
 
    TJSONObject * json  = static_cast< TJSONObject * > (HueRESTResponse->JSONValue);
 
    //- test for error, here we assume just one bridge is found.
    HueRESTResponse->RootElement = "[0].error.description";
    json = static_cast<TJSONObject *> ( HueRESTResponse->JSONValue );
 
    if ( json != NULL) {
        Memo1->Lines->Add( "Error finding lights: " + json->Value() );
    }
    else {
 
        HueRESTResponse->RootElement = "";
        json = static_cast<TJSONObject *> ( HueRESTResponse->JSONValue );
        NumLightsFound      = json->Count;
 
        //- Hue Bridge returns light count starting from 1
        for ( int i=1; i <= NumLightsFound; i++ ) {
 
            //- test if light is reachable
            HueRESTResponse->RootElement = String(i) + ".state.reachable";
            json = static_cast< TJSONObject * > (HueRESTResponse->JSONValue);
            if ( json->Value() == "false" ) {
                HueRESTResponse->RootElement = String(i) + ".name";
                json = static_cast< TJSONObject * > (HueRESTResponse->JSONValue);
                Memo1->Lines->Add(    "Found light: " +
                                    json->Value() +
                                    " at index: " +
                                    String(i) +
                                    " but it is unreachable" );
 
                LightsAvailable.push_back( false );
            }
            else {
                HueRESTResponse->RootElement = String(i) + ".name";
                json = static_cast<TJSONObject *> ( HueRESTResponse->JSONValue );
                Memo1->Lines->Add( "Found light: " +
                                    json->Value() +
                                    " at index: " +
                                    String(i) );
 
                LightsAvailable.push_back( true );
            }
 
            LightsComboBox->Items->Add( json->Value() );
        }
 
        //- set combo box to first active item added
        for ( int i=0; i<LightsAvailable.size(); i++ ) {
            if ( LightsAvailable[i] ) {
                LightsComboBox->ItemIndex = i;
                break;
            }
        }
 
 
 
        //- remove inital overlay
        RemoveSplashScreen();
    }
}

A generic set of REST Components is used for all GET/PUT API calls.

Since this function is sued to query the lights, the Request Component is set to GET.

The code then iterates over all returned lights and adds them to the application.

Turning a Light On/Off

void __fastcall TForm1::HandleLightsOnOff() {
    //- turn the selected light on or off
    HueRESTRequest->Method   = Rest::Types::rmPUT;
    HueRESTClient->BaseURL   = BaseURL;
 
    //- use currently selected light
    //  hue light index starts at 1
    HueRESTRequest->Resource = UserName +
                                String("/lights/") +
                                String(LightsComboBox->ItemIndex+1) +
                                String("/state");
 
    HueRESTRequest->Params->Items[0]->Value = "{\"on\":" +
                                                String( (LightStateSwitch->IsChecked)?"true":"false" ) +
                                                "}";
 
    HueRESTRequest->Execute();
    Memo1->Lines->Add( "PUT " +
                        BaseURL +
                        HueRESTRequest->Resource +
                        " json: " +
                        HueRESTRequest->Params->Items[0]->Value );
}

 

 

In this case, the generic set of REST Components are telling the lights to change so the Request Component Method is set to PUT.

The Resource is updated per the /state API  call pointing to the currently selected light.

The On/Off state is set by the JSON body which is set to the Request Paramaters list according to the switch on the application UI.

Lastly the REST Request is executed.

 

A Note On Deploying to iOS Devices

iOS devices do not include the SSL libraries needed to make an HTTPS rest API call. For more information on this, please refrence Open SSL and HTTPS Support for iOS Devices blog post.

This is required for the application to make the Find Bridges web service call to https://www.meethue.com/api/nupnp.

The following code needs to be added to the top of Unit1.cpp

 

#if defined(TARGET_OS_IPHONE)
    // needed for iOS deployment, libcrypto.a libssl.a for https calls
    //  place libcrypto.a and libssl.a in the iOSDevice/debug folder
    //  see https://github.com/st3fan/ios-openssl for more info
    #include <IdSSLOpenSSLHeaders_Static.hpp>
#endif

 

Download the files from https://github.com/st3fan/ios-openssl

Look for libcrypto.a and libssl.a and place them in the project directory (they are included in the project download files at the end of this blog post)

Next open Project -> Options and select C++ Linker.

 

From the Target drop down menu at the top of the window, select  All Configurations - iOS Device Platform.

Cpp-Linker-iOS

 

Summary

The Appmethod Hue Lux Control App took 10 minutes of UI building and a bit of simple application logic. This application will run on OSX, Windows, iOS, and Android smart phones and tablets.

The project files are available to download so you can try it out yourself!


Download the project files!

 

Windows-Hue

 

 OSX-Hue

 

 

 

 

 

Tags: Appmethod


About
Gold User, Rank: 8, Points: 399
Brian Alexakis is a Product Marketing Manager at Embarcadero Technologies. He is focused on leveraging the connected world of technology to build new experiences for the Internet of Things.

Comments

Check out more tips and tricks in this development video: