Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Philips Hue Laravel Package

cannonb4ll/laravel-philips-hue

Laravel wrapper for the Philips Hue API that lets you discover bridges, control lights, groups and scenes, and manage colors, brightness and schedules directly from your Laravel app. Simple configuration and an expressive interface make smart-home automation easy to add.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require cannonb4ll/laravel-philips-hue

The package was last released in November 2020, so treat the version constraint in its composer.json as a starting point, not a guarantee. On Laravel 9+ you may need --with-all-dependencies and, if resolution fails, a fork with widened illuminate/* constraints. Package discovery registers the service provider and PhilipsHue facade automatically on supported versions; on older skeletons add them manually.

Publish config first

php artisan vendor:publish --provider="Cannonb4ll\PhilipsHue\PhilipsHueServiceProvider"

That drops config/philips-hue.php — this is the file to read before anything else. It is where the two operating modes are configured:

  • Local bridge: bridge IP + a bridge username ("app key") generated by pressing the physical link button.
  • Remote (Hue Remote API): client_id, client_secret, app_id, and the remote username/token obtained through the Hue developer OAuth flow.

Read the published config top to bottom, then the README's remote section. Those two files explain 90% of the behaviour; everything else is a thin client over the Hue REST API.

Create a local app key

Press the link button on the bridge, then run the setup command the package ships (list them with php artisan list | grep -i hue) within the 30-second window. If you don't have a command available, POST https://<bridge>/api with {"devicetype":"laravel#dev"} against the same window works identically and is worth knowing — the bridge is the source of truth, the package is just a wrapper.

Put the result in .env:

HUE_BRIDGE_IP=192.168.1.42
HUE_BRIDGE_USERNAME=abc123...

First use case

The natural first task is "list lights, toggle one":

use Cannonb4ll\PhilipsHue\Facades\PhilipsHue;

$lights = PhilipsHue::lights();          // collection of light resources

PhilipsHue::light(1)->turnOn();
PhilipsHue::light(1)->setBrightness(180);
PhilipsHue::light(1)->setColor('#ff8800');

Exact method names should be checked against the facade/README — the package's API surface is a direct mapping of Hue's /lights/{id}/state fields, so the mental model transfers even if a method differs.

Implementation Patterns

Put a seam between your app and the package

The package is archived. Do not let PhilipsHue:: calls sprawl across controllers. Define a small contract and one adapter:

interface HomeLighting
{
    public function signal(string $color, int $brightness = 200): void;
    public function allOff(): void;
}

class HueLighting implements HomeLighting
{
    public function signal(string $color, int $brightness = 200): void
    {
        PhilipsHue::light(1)->turnOn();
        PhilipsHue::light(1)->setColor($color);
        PhilipsHue::light(1)->setBrightness($brightness);
    }
}

Bind it in a service provider. Swapping to a fork, another package, or raw Guzzle later becomes a one-line change, and tests get a trivial fake.

Local vs remote is an environment decision

  • Local mode for anything running on the LAN: home servers, Raspberry Pi, a homelab box. Lowest latency, no OAuth, no internet dependency. Fails the moment the app leaves the network.
  • Remote mode for cloud-hosted apps, CI runners, or anything with a queue worker in a datacenter. It needs a public-facing OAuth redirect URI, token storage, and refresh handling.

A common production shape: remote mode in staging/CI, local mode in dev, and a config switch so the same code path runs in both. Keep the mode selection in .env, never hardcoded.

Queue every command

The Hue bridge is a slow, rate-limited Zigbee gateway. Never issue light commands inline in a web request that a user is waiting on. Use jobs:

dispatch(new FlashLightJob('red', times: 3))->onQueue('hue');

Consider a dedicated queue with a low concurrency (1–2 workers). The bridge tolerates roughly ~10 commands/second per light and far less in aggregate; parallel workers will produce 429-style errors or silent drops. If you need bursts, batch with Bus::batch() and stagger with delay().

Good day-to-day use cases

  • Deploy/build status lights: green on success, red on failure, triggered from a Deployed event listener.
  • Team notification: a light flashes amber when a high-priority ticket lands.
  • Presence simulation: a scheduled command that varies lights in the evening — this is where remote mode earns its keep.
  • Ambient dashboards: poll a metric and map it to hue via a scheduler task.
// app/Console/Kernel.php
$schedule->job(new SyncPresenceLightsJob)->everyFifteenMinutes()->between('19:00', '23:00');

Wrap polling, don't stream

There is no event stream from the bridge. If you need state, poll on a schedule and cache the result briefly; do not poll inside request handlers.

Testing

Fake the facade — this is why the seam above matters:

PhilipsHue::shouldReceive('light->turnOn')->once();

If you bind HomeLighting to a fake instead, most tests never touch the package at all, which is the right outcome for an unmaintained dependency.

Gotchas and Tips

Archived status is the real gotcha. Last release 2020, no security or compatibility patches. Pin the version, audit it, and plan a fork. The Hue REST API is stable and simple enough that a hand-rolled Guzzle client is a realistic exit strategy — often under 200 lines for light control.

Config caching freezes bridge IP and credentials. php artisan config:cache in deploy pipelines will bake in whatever .env was present at build time. Ensure the cache is built on the target environment, or read runtime values outside the config file.

The link button window is genuinely 30 seconds. Most "cannot authenticate" reports are just a missed window. Retry rather than debugging code.

Remote mode token lifecycle. Hue Remote API access tokens expire (~15 minutes in practice, depending on your app's grant). You need refresh logic and persistent token storage; the package's helpers are from 2020 and may not handle every refresh path. Log the token exchange, and test refresh explicitly — expiry bugs surface hours later in production, not in dev.

OAuth redirect URI must match exactly. Scheme, host, trailing slash, port — the Hue developer portal does a strict string comparison. http vs https mismatch is the classic failure.

Brightness is 1–254, not 0–100. Values below 1 error out or are rejected. Clamp in your adapter.

Color gamut differs per bulb. RGB → HSB/XY conversion is lossy and gamut A/B/C bulbs render the same hex differently. If color fidelity matters (status indicators), pick from a fixed palette calibrated per physical bulb rather than sending arbitrary hex.

Group vs light commands. Acting on a group is one bridge command and usually what you want for "all lights red"; looping over lights multiplies rate-limit exposure for identical visual effect.

Timeouts should be short. Set a 2–5 second connect timeout. A powered-off bridge will otherwise hang a worker for the default HTTP timeout. Never retry aggressively — you'll amplify a bridge problem into a queue backlog.

Debugging workflow: tail -f storage/logs/laravel.log while running a single command in php artisan tinker. The Hue bridge returns a JSON array of per-command {"error": {...}} objects with HTTP 200 — a "successful" request can still contain errors. Always inspect the body, not just the status code.

Extension points: the service provider and facade root are the places to bind your own decorated client. If a method is missing, the underlying Bridge/transport class is thin enough to extend — but do it in your app, not by editing vendor files.

Don't put it on a critical path. Lights are a nice-to-have signal. Wrap all calls in try/catch, fail open, and let the application continue if the bridge is unreachable.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ipregistry/ipregistry-php
quellabs/canvas-smarty
quellabs/signal-hub
goodport/laravel-js-error-logger
szabrob/laravel-billingo
devkussema/acapapay-laravel
apartejs/laravel
smronju/nativephp-geolocation
luppakorva/laravel-nist-password-rules
owenmelbz/sashimi
gui1535/sql-to-eloquent
hashtap/laravel-responsecache
pnscripts/laravel-proverka-lite
bhawdeadlydan/laravel-accountkit
jlawrence/eos
wireblob/wire
leafs/csrf
leafs/vite
leafs/db
leafs/auth