Controlling my Philips Hue Lights using C++Builder for iOS

Posted by on in Blogs
Last Friday (January 31, 2014) in my blog post, "Managing my Philips Hue Lights from a C++Builder FireMonkey Desktop", I showed you how to use C++Builder XE5 to build a Windows (32 and 64 bit) and Mac OS X application to control my Philips Hue wireless LED lights. In this blog post, I will show you the screens and code for the C++Builder for iOS version of the project. I reused the code and the data module and built a mobile UI on the main form. I tested the application on my iPhone 4s and set the Target Platform to Win32 to also test it using Windows.



The C++ mobile app's UI

The main form starts with a TToolBar and a TabControl with 3 TabItems for the lights controller (using TColorPanel and 3 SpinBox and 2 TComboBox components), JSON messages tab (saved in a TMemo), and settings tab (with a TEdit to input the Developer ID, a TComboBox to contain a list of the Hue Bridge boxes found on the network, and a TButton to populate the TCombobox with the Bridge boxes found). All three of the TComboBox components will use the native CustomPicker on iOS and the Windows ComboBox on Windows. Here are the screens for the application's mobile UI. The ToolBar has a TLabel for the caption and a TSpeedButton used to turn on/off all the lights for the selected Bridge box.



Here is the Project Manager window showing two Target Platforms (Win32 and iOS Device).



The C++ mobile project also includes a DataModule to contain the REST Client Library components that leverage the Philips Hue REST/JSON API to get information about the Bridge boxes found on my network.



Here is the form's class declaration managed in part by the IDE as you drop components on the form.



The Code

Like the desktop version of the C++Builder project, the C++ iOS version has four sections of code: the form's OnCreate event handler, the GetHueIPAddresses for all of the Bridge boxes, the AllLightsButtonClick used to turn all of the lights on and off, and the SetLightButtonClick to control the on/off and color of each light independently.

Here's the code for the form's OnCreate event handler:
void __fastcall THueAppForm::FormCreate(TObject *Sender)
{
HueLightsOnOff = false;
Memo1->Lines->Clear();
TabControl1->ActiveTab = LightsTabItem;
}

Here's the code for the GetHueIPAddress button OnClick event handler:
void __fastcall THueAppForm::GetHueIPAddressButtonClick(TObject *Sender)
{
// find HUE Bridge - if there is one and there may be more
HueBridgeComboBox->Clear();
// Execute the REST Get to receive all Hue Bridge boxes
// the RESTRequest uses the Hue broker server
// discover process at www.meethue.com/api/nupnp
DM->FindHueRESTRequest->Execute();
// display the JSON result
Memo1->Lines->Add(DM->FindHueRESTResponse->Content);

// populate combobox with all Hue Bridge Boxes found using the CDS
if (DM->FindHueClientDataSet->RecordCount > 0) {
for (int HueBridgeIndex = 0; HueBridgeIndex < DM->FindHueClientDataSet->RecordCount; HueBridgeIndex++) {
HueBridgeComboBox->Items->Add(
DM->FindHueClientDataSet->FieldByName("internalipaddress")->AsString
);
Memo1->Lines->Add("Hue Bridge Found: "+HueBridgeComboBox->Items[HueBridgeIndex].Text);
}
HueBridgeComboBox->ItemIndex = 0;
// Bridge found - enable the other buttons
AllLightsButton->Enabled = true;
SetLightButton->Enabled = true;

//TODO: Populate Lights ComboBox using JSON return from lights get
// for now I will assume that I have the 3 starter kit lights

}
else {
Memo1->Lines->Add("Hue Bridge not Found!");
}
}

Here's the code for the AllLightsButtonClick SpeedButton OnClick event handler:
void __fastcall THueAppForm::AllLightsButtonClick(TObject *Sender)
{
// http://<bridge ip address>/api/newdeveloper/groups/0/action
// Body {"on":false}
// Method PUT
TStringStream *jsonToSend = new TStringStream;
String jsonBodyString;

// build the json body string - toggling the button
// if button text is off - turn lights off and set button to on
// if button text is on - turn lights on and set button to off
if (AllLightsButton->Text == "ON") {
AllLightsButton->Text = "OFF";
jsonBodyString = "{\"on\":true}";
}
else {
AllLightsButton->Text = "ON";
jsonBodyString = "{\"on\":false}";
}
jsonToSend->WriteString(jsonBodyString);

// build the http put string
String putString =
"http://"
+ HueBridgeComboBox->ListItems[HueBridgeComboBox->ItemIndex]->Text
+ "/api/"
+ DeveloperIDEdit->Text
+ "/groups/0/action"; // assume that for now I only have one group

// HTTP Put to turn on/off all lights and put return result in the Memo
Memo1->Lines->Add(
HueSetLightsIdHttp->Put(
putString,
jsonToSend)
);
delete jsonToSend;
}

And finally, here's the code for the SetLightButtonClick OnClick event handler which uses a helper function to allow C++ to work with the TAlphaColorRec using a "reinterpret_cast" typecast (Note about the difference in the mobile version code - this is because Delphi's mobile TAlphaColor is a strong alias while on teh desktop implementation it's not).
// helper to make working with TAlphaColorRec easy for C++
const TAlphaColorRec& AsAlphaColorRec(const TAlphaColor& c) {
return reinterpret_cast<TAlphaColorRec&>(const_cast<TAlphaColor&>(c));
}
//---------------------------------------------------------------------------
void __fastcall THueAppForm::SetLightButtonClick(TObject *Sender)
{
String lightStateString;
TStringStream *jsonToSend = new TStringStream;

if (OnOffComboBox->Items[OnOffComboBox->ItemIndex].Text == "Off")
lightStateString = "false";
else
lightStateString = "true";

// Convert ColorPicker/ColorQuad RGB to CIE x,y
int R, G, B;
R = AsAlphaColorRec(ColorPanel1->Color).R;
G = AsAlphaColorRec(ColorPanel1->Color).G;
B = AsAlphaColorRec(ColorPanel1->Color).B;
// calculate X,Y,Z using the RGB values
double X1 = 0.4124*R + 0.3576*G + 0.1805*B;
double Y1 = 0.2126*R + 0.7152*G + 0.0722*B;
double Z1 = 0.0193*R + 0.1192*G + 0.9505*B;
// normalize the CIE x,y values using X,Y,Z
double x = X1 / (X1 + Y1 + Z1);
double y = Y1 / (X1 + Y1 + Z1);

// the following lines from the desktop version
// are commented out for the mobile app to leave
// more space for the TColorPanel component display
// display the CIE x,y values
// XLabel->Text = FloatToStrF(x,ffFixed,4,3);
// YLabel->Text = FloatToStrF(y,ffFixed,4,3);

// build the json body string
String jsonBodyString =
"{\"on\":" + lightStateString
+ ",\"bri\":" + FloatToStr(BrightnessSpinBox->Value)
+ ",\"hue\":" + FloatToStr(HueSpinBox->Value)
+ ",\"sat\":" + FloatToStr(SaturationSpinBox->Value)
+ ",\"xy\":" + "["+FloatToStrF(x,ffFixed,4,3)+","+FloatToStrF(y,ffFixed,4,3)+"]"
+ "}";
jsonToSend->WriteString(jsonBodyString);

// build the http put string
String putString =
"http://"
+ HueBridgeComboBox->ListItems[HueBridgeComboBox->ItemIndex]->Text
+ "/api/"
+ DeveloperIDEdit->Text
+ "/lights/"
+ LightsComboBox->ListItems[LightsComboBox->ItemIndex]->Text
+ "/state";

// HTTP Put to set a light's color and put return result in the Memo
Memo1->Lines->Add(
HueSetLightsIdHttp->Put(
putString,
jsonToSend)
);
delete jsonToSend;
}

C++ iOS and Win32 running apps

The following are screen grabs for the iOS and Win32 versions of the mobile application running and controlling my lights. For the two Lights tab ComboBoxes you also see the iOS native custom picker in action.

iOS:







Win32:



That's it. In the two blog posts you've seen the C++Builder XE5 update 2 desktop and mobile versions of my Philips Hue applications. You'll find the source code to this C++Builder for iOS project on Code Central at http://cc.embarcadero.com/item/29714.
About
Gold User, Rank: 1, Points: 2466
David Intersimone (known to many as David I.) is a passionate and innovative software industry veteran-often referred to as a developer icon-who extols and educates the world on Embarcadero developer tools. He shares his visions as an active member of the industry speaking circuit and is tapped as an expert source by the media. He is a long-standing champion of architects, developers and database professionals and works to ensure that their needs are folded into Embarcadero's strategic product plans. David holds a bachelor's degree in computer science from California Polytechnic State University at San Luis Obispo, California.

Comments

  • Guest
    Aurelio Monday, 03 February 2014

    Very good!
    I would like to see an example like this in Delphi, is it possible?
    Thanks!!

  • Guest
    Lena Monday, 03 February 2014

    Thank you very much!

  • Please login first in order for you to submit comments
  • Page :
  • 1