Skip to content
Alexander Overvoorde edited this page Aug 16, 2013 · 20 revisions

Jue is designed to be a lightweight wrapper over the actual API. It provides some convenience functions and constructs, but in general it just wraps the API calls and responses into nice classes and exceptions, so you don't have to worry about all the gory network and JSON details.

Organization

The two most important classes are HueBridge and BridgeDiscovery. The HueBridge class represents a physical Hue bridge and has methods closely resembling API calls, such as getLights() and createGroup(). The BridgeDiscovery class gives you two methods of actually finding bridges on the local network. These are useful for developing apps that automatically discover bridges.

Then there're classes representing each entity:

All of these objects contain data, like the current state (on/off, color, ...) or configuration. All these types of data have their own classes as well.

Interaction with the bridge

All operations that require interaction with the bridge go through the HueBridge class. For example, you may find code like this:

bridge.setLightName(kitchenLight, "Kitchen");

rather than:

kitchenLight.setName("Kitchen");

This is done to make it more obvious to you as developer what methods will result in requests to the bridge, and which methods are free of side-effects.

Exceptions

All functions that interact with the bridge have the checked exceptions IOException and ApiException. The former is thrown if something goes wrong on the connection/HTTP protocol level and the latter if the bridge responds with an error through the API. There is a subclass for every type of API exception that can occur. The documentation for each function tells you exactly which exceptions you can expect.

Additionally, an IllegalArgumentException may be thrown if you don't meet API restrictions when passing certain parameters. For example, name and description parameters are often limited in length. The documentation specifies the exact byte length boundaries for each function parameter. Note that with UTF-8 encoding, a single character does not always correspondent to a single byte!

Getting started

Clone the repository and add the project to your Eclipse workspace. Add it to your project's Java buildpath using the project properties.

It all begins with connecting to your bridge. Construct a new HueBridge object with the IP address of your bridge.

HueBridge myBridge = new HueBridge("192.168.1.101");

Notice that we haven't specified a username yet, so we haven't actually authenticated with the bridge. The only action available to unauthorized users is retrieving the basic configuration with only the bridge name and software version.

Config config = myBridge.getConfig();

This code doesn't work yet, because the checked exceptions IOException and ApiException need to be handled. Add a try...catch statement and try printing the name of your bridge.

try {
    HueBridge myBridge = new HueBridge("192.168.1.101");
    Config config = myBridge.getConfig();
    System.out.println(config.getName());
} catch (IOException e) {
    e.printStackTrace();
} catch (ApiException e) {
    e.printStackTrace();
}

If you're connected to the same network as your bridge and you've specified the right IP address, you should now be staring at the name of your bridge in excitement.

Authenticating

To do anything more than this, you need to authenticate with a whitelisted username on the bridge. You can do this by constructing a new bridge with the username parameter or by calling authenticate on our existing bridge object.

HueBridge myBridge = new HueBridge("192.168.1.101");
myBridge.authenticate("aValidUser");

// or

HueBridge myBridge = new HueBridge("192.168.1.101", "aValidUser");

Alternatively, you can register a new user on the bridge after pressing the link button by calling link.

If the username you specified is indeed whitelisted, the program should exit successfully, otherwise an UnauthorizedException will be thrown. Now that we've got whitelisted access to the bridge, we can get to the good stuff.

Object and FullObject

Let's start by seeing what lights are connected to the bridge by calling getLights.

for (Light light : myBridge.getLights()) {
    System.out.println(light.getName());
}

You should see something like this printed to the console:

HueLamp 1
HueLamp 2
HueLamp 3

By inspecting the Light, you will notice that it only has the two methods getId and getName. That's because the API request behind the lights retrieval only returns this much information for each light. If you want to know more about a specific light, you will have to retrieve a FullLight object.

for (Light light : myBridge.getLights()) {
    FullLight fullLight = myBridge.getLight(light);
    System.out.println(fullLight.getName() + " (" + fullLight.getState().getBrightness() + ")");
}

This class has much more information, like the model ID, software version and the current state of the light. You will see this pattern with other types of objects as well.

Light -> FullLight
Group -> FullGroup
Config -> FullConfig
Schedule -> FullSchedule

This is an advantage, because it allows you to save bandwidth when you just need to list the names of the lights or groups that you have in your app. In general, try to design your app so that it only retrieves the data it needs.

If you need to synchronise state with the bridge, it is desirable to retrieve all information in one simple request, however. This can be accomplished by retrieving a FullConfig by calling getFullConfig on the bridge. This will return all data the bridge has to offer, but it's a fairly resource intensive operation and shouldn't be used too often.

Changing state

Now that we've seen how to retrieve state, let's try to change it. Most objects have many different kinds of properties that can be changed, like brightness, hue, effects, on/off, etc. The Hue API allows you to bundle these updates in single requests. It would be a bit of a waste if we were to throw this ability away by exposing functions like setLightBrightness, setLightHue and setLightEffect that each send a separate request.

Instead, there's a mechanism that allows you to set a few properties and then send it off as a single request. Let's see what that looks like by turning all lights on and setting their colour to red.

Group all = myBridge.getAllGroup();
StateUpdate update = new StateUpdate().turnOn().setHue(0);
myBridge.setGroupState(all, update);

It's fairly simple to understand what's going on here. A StateUpdate object allows you to build a list of things you want to change. In this case, we first want to turn lights on and then set their hue to 0 (red). To actually apply these changes, you pass this object to setGroupState and it will turn the collection of changes into a single request.

You can combine these in a single line to reduce verbosity:

bridge.setGroupState(bridge.getAllGroup(), new StateUpdate().turnOn().setHue(0));

This StateUpdate object can be used both groups and individual lights. For other types of objects, there are other types of state objects with different setters.

Light/Group -> StateUpdate
Schedule -> ScheduleUpdate
Config -> ConfigUpdate

Some objects have so few different properties that they don't really need this system. They have separate functions that work just as you expect them to:

bridge.setLightName(light, "Awesome New Name");

You may be a bit confused here, because lights do actually have many types of state, but properties like name are usually not counted as state and can unfortunately not be updated together with things like colour in a single request.

Clone this wiki locally