A modern, intuitive Java library for controlling Philips Hue smart lighting systems. Built with dependency injection, clean architecture principles, and comprehensive error handling to provide a robust and maintainable solution.
Currently only supports basic features authentication and manipulating light state. Will add to this as requirements for downstream projects evolve, or people want something.
The library is available through GitHub Packages. You'll need to configure your build tool with GitHub authentication to access the package.
- Add the GitHub Packages repository to your
settings.xml
file (usually found in~/.m2/settings.xml
):
<settings>
<servers>
<server>
<id>github</id>
<username>${env.USERNAME}</username>
<password>${env.TOKEN}</password>
</server>
</servers>
</settings>
- Add the repository and dependency to your
pom.xml
:
<repositories>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/peavers/hue-java-wrapper</url>
</repository>
</repositories>
<dependency>
<groupId>space.forloop.hue</groupId>
<artifactId>hue-java-wrapper</artifactId>
<version>$latestVersion</version>
</dependency>
- Add the GitHub Packages repository and dependency to your
build.gradle
:
repositories {
mavenCentral()
mavenLocal()
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/peavers/hue-java-wrapper")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
}
}
}
dependencies {
implementation 'space.forloop.hue:hue-java-wrapper:$latestVersion'
}
- Set your GitHub credentials either through environment variables (
USERNAME
andTOKEN
) or in yourgradle.properties
file:
gpr.user=YOUR_GITHUB_USERNAME
gpr.key=YOUR_GITHUB_TOKEN
Note: Your GitHub token needs the read:packages
scope to download packages.
Here's a simple example to get you started:
class Example {
public static void main(String[] args) {
// Create a client
HueClient client = HueClient.builder().build();
// Discover bridges
List<HueBridge> bridges = client.discoverBridges();
HueBridge bridge = bridges.get(0);
// Authenticate (press the link button on the bridge first)
BridgeAuthentication auth = bridge.authenticate("MyApp");
// Get an authenticated bridge instance
AuthenticatedBridge authBridge = bridge.authenticate(auth);
// Control lights
Collection<Light> lights = authBridge.getLights();
for (Light light : lights) {
LightState state = LightState.builder()
.on(true)
.brightness(254)
.colorTemperature(300)
.build();
light.setState(state);
}
}
}
- HueClient: The main entry point for the library. Handles bridge discovery and connection.
- HueBridge: Represents a physical Hue bridge, providing authentication and configuration.
- AuthenticatedBridge: Provides access to lights and other bridge features after authentication.
- Light: Represents individual light bulbs, allowing state control and capability querying.
Google Guice for dependency injection to:
- Promote loose coupling between components
- Facilitate easier testing through dependency substitution
- Provide a clean, modular architecture
Retrofit was selected for HTTP communication because it:
- Provides a type-safe HTTP client
- Offers excellent async support
- Has built-in JSON serialization
- Is widely used and well-maintained
The builder pattern is used for client configuration to:
- Allow optional customization of HTTP client and object mapper
- Maintain immutability
- Provide a fluent, readable API
We implemented a hierarchy of custom exceptions to:
- Provide clear error handling paths
- Enable specific error handling for different failure modes
- Maintain type safety in error handling
class Example {
public static void main(String[] args) {
// Use your own object mapper
ObjectMapper customMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
// Own version of OkHttpClient
OkHttpClient customClient = new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(10))
.build();
// Use the builder to wire them in
HueClient client = HueClient.builder()
.withObjectMapper(customMapper)
.withOkHttpClient(customClient)
.build();
}
}
class Example {
public static void main(String[] args) {
try {
List<HueBridge> bridges = client.discoverBridges();
} catch (
HueDiscoveryException e) {
// Handle discovery failure
} catch (
HueConnectionException e) {
// Handle connection failure
}
try {
BridgeAuthentication auth = bridge.authenticate("MyApp");
} catch (
HueAuthenticationException e) {
// Handle authentication failure
System.err.println("Please press the link button on the bridge and try again");
}
}
}
-
Store Authentication: Save the
BridgeAuthentication
after initial setup to avoid requiring link button presses on subsequent connections. -
Error Handling: Always handle specific exceptions (
HueDiscoveryException
,HueConnectionException
,HueAuthenticationException
) to provide appropriate user feedback.
3Resource Management: The client uses OkHttp which manages its own resources. However, consider implementing a shutdown method if needed in your application.
The library is designed to be thread-safe. All mutable state is properly encapsulated, and the underlying HTTP client ( OkHttp) is thread-safe by design.
The library is designed with testing in mind:
- Interfaces are used throughout to allow mocking
- Dependency injection makes it easy to substitute test implementations
- Factory patterns enable easy creation of test objects
- Java 17 or higher
- Philips Hue Bridge (v2 or later)