homebridge-philips-hue-sync-box
Version:
Homebridge plugin for the Philips Hue Sync Box.
377 lines (314 loc) • 24.3 kB
Markdown
<p align="center">
<img src="https://github.com/homebridge/branding/raw/latest/logos/homebridge-wordmark-logo-vertical.png" width="150">
</p>
<h1 align="center">Homebridge Philips Hue Sync Box</h1>
<p align="center">Bring your Philips Hue Sync Box into Apple HomeKit.</p>
<p align="center">
[](https://www.npmjs.com/package/homebridge-philips-hue-sync-box)
[](https://www.npmjs.com/package/homebridge-philips-hue-sync-box)
[](https://www.npmjs.com/package/homebridge-philips-hue-sync-box)
[](https://github.com/jabrown93/homebridge-philips-hue-sync-box)
[](https://github.com/jabrown93/homebridge-philips-hue-sync-box/actions/workflows/build.yaml)
[](https://github.com/jabrown93/homebridge-philips-hue-sync-box/actions/workflows/codeql.yaml)
[](https://github.com/jabrown93/homebridge-philips-hue-sync-box/releases)
[](./LICENSE)
</p>
A [Homebridge](https://homebridge.io) plugin that exposes the [Philips Hue Sync Box](https://www.philips-hue.com/en-us/p/hue-play-hdmi-sync-box/8719514440996) to Apple HomeKit, so you can turn syncing on/off, switch inputs, change modes, and automate it alongside the rest of your smart home.
## Features
- **Base accessory** — expose the Sync Box as a lightbulb (on/off + brightness) or a plain switch (on/off).
- **Power switch** — an optional, separate switch that toggles the box between passthrough and powersave.
- **TV accessories** (opt-in, one per behavior) — each appears in the Apple TV remote widget and iOS Control Center:
- **HDMI TV** — switch inputs.
- **Mode TV** — switch between `video`, `music`, and `game`.
- **Intensity TV** — switch between `subtle`, `moderate`, `high`, and `intense`.
- **Entertainment TV** — switch the active Hue entertainment area.
- Each TV accessory optionally exposes its own integrated lightbulb for brightness control.
- **HTTP API** — an optional local API for scripting and HomeKit Shortcuts automations.
- **Multiple Sync Boxes** — run one plugin instance per box, each with its own accessories.
> [!IMPORTANT]
> TV accessories are published as _external_ accessories and must be added to HomeKit manually — Homebridge logs the pairing PIN (the same one used for the main bridge).
## Table of Contents
- [Installation](#installation)
- [Requirements](#requirements)
- [Install the Plugin](#install-the-plugin)
- [Get a Sync Box Access Token](#get-a-sync-box-access-token)
- [Running Multiple Sync Boxes](#running-multiple-sync-boxes)
- [Configuration](#configuration)
- [HTTP API](#http-api)
- [GET /state](#get-state)
- [POST /state](#post-state)
- [Development](#development)
- [Getting Help](#getting-help)
- [Acknowledgments](#acknowledgments)
## Installation
### Requirements
- Homebridge `^1.8.0` or `^2.0.0-beta.0`
- Node.js `^22.12.0` or `^24.11.0`
- A Philips Hue Sync Box on the same network as Homebridge
### Install the Plugin
**Using Homebridge UI (recommended)**
1. Open the [Homebridge UI](https://github.com/homebridge/homebridge/wiki/Install-Homebridge-on-macOS#complete-login-to-the-homebridge-ui).
2. Go to the **Plugins** tab, search for `homebridge-philips-hue-sync-box`, and install it.
3. Get a Sync Box access token as described [below](#get-a-sync-box-access-token).
4. Configure the plugin from the Homebridge Config UI.
**Manual**
1. Install with `hb-service add homebridge-philips-hue-sync-box`, or `npm i -g homebridge-philips-hue-sync-box` if you're not using `hb-service`.
2. Get a Sync Box access token as described [below](#get-a-sync-box-access-token).
3. Add the platform to Homebridge's `config.json`, see [Configuration](#configuration).
### Get a Sync Box Access Token
The plugin authenticates with the Sync Box using a token you generate once via its local API:
1. Make sure the Sync Box is powered on and synchronization is stopped.
2. Send an HTTP `POST` to `https://<SYNC-BOX-IP>/api/v1/registrations` with a JSON body of `{ "appName": "homebridge", "instanceName": "homebridge" }`.
3. The first response will be `{ "code": 16, "message": "Invalid State" }` — this is expected.
4. Within 5 seconds, press and hold the button on the Sync Box until the LED turns green, then release it immediately. It will switch back to white.
5. Within 5 seconds of the LED turning green, send the exact same `POST` request again.
6. The response now contains an `accessToken` string — save it for your plugin configuration.
One way to do this from a terminal:
```shell
curl -k -H "Content-Type: application/json" \
-X POST -d '{"appName": "homebridge", "instanceName": "homebridge"}' \
https://<SYNC-BOX-IP>/api/v1/registrations
```
You can also use a tool like [Postman](https://www.postman.com/): set the method to `POST`, the URL to `https://<SYNC-BOX-IP>/api/v1/registrations`, and the body to raw JSON containing `{ "appName": "homebridge", "instanceName": "homebridge" }`. If you hit a certificate error, disable SSL certificate verification in Postman's settings.
Once you have a token, you can validate it with:
```shell
curl -k -H "Authorization: Bearer <ACCESS-TOKEN>" https://<SYNC-BOX-IP>/api/v1/
```
See the [official Hue Sync Box API documentation](https://developers.meethue.com/develop/hue-entertainment/hue-hdmi-sync-box-api/#Getting%20Started) for more detail (a free developer account is required).
> [!NOTE]
> This plugin has no control over how the Sync Box issues or validates tokens. Please don't open issues about "Invalid Token" errors — they will be closed without action.
### Running Multiple Sync Boxes
Each Sync Box needs its own plugin instance, added as a separate entry under `platforms` in `config.json`, each with a unique `uuidSeed`:
```json5
{
// rest of config
platforms: [
{
platform: 'PhilipsHueSyncBoxPlatform',
name: 'LivingRoomPhilipsHueSyncBoxPlatform',
syncBoxIpAddress: '<SYNC-BOX-1-IP-ADDRESS>',
syncBoxApiAccessToken: '<SYNC-BOX-1-ACCESS-TOKEN>',
uuidSeed: 'LivingRoom',
// rest of config
},
{
platform: 'PhilipsHueSyncBoxPlatform',
name: 'BedroomPhilipsHueSyncBoxPlatform',
syncBoxIpAddress: '<SYNC-BOX-2-IP-ADDRESS>',
syncBoxApiAccessToken: '<SYNC-BOX-2-ACCESS-TOKEN>',
uuidSeed: 'Bedroom',
// rest of config
},
],
}
```
- `uuidSeed` must be unique per Sync Box; it may be left empty (`""`) for at most one instance.
- `name` should also be unique per instance — it makes the logs easier to follow.
> [!WARNING]
> Changing `uuidSeed` on an existing setup removes and recreates every accessory for that instance. HomeKit treats them as brand new, so you'll need to re-add them (including any automations or room assignments). Only set it if you're running more than one Sync Box.
## Configuration
| Name | Description | Type | Default | Required | Allowed Values |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------- | -------- | --------------------------------------------- |
| `syncBoxIpAddress` | IP address of your Philips Hue Sync Box. | string | | Yes | |
| `syncBoxApiAccessToken` | Access token obtained during [registration](#get-a-sync-box-access-token). | string | | Yes | |
| `defaultOnMode` | Mode used when switching the Sync Box on via HomeKit. | string | `video` | No | `video`, `music`, `game`, `lastSyncMode` |
| `defaultOffMode` | Mode used when switching the Sync Box off via HomeKit. | string | `passthrough` | No | `powersave`, `passthrough` |
| `baseAccessory` | Type of the primary Sync Box accessory. `none` exposes no base accessory. | string | `lightbulb` | No | `lightbulb`, `switch`, `none` |
| `powerSwitchAccessory` | Adds a separate switch that toggles passthrough (on) vs. powersave (off), independent of `baseAccessory`. | boolean | `false` | No | |
| `tvAccessory` | Enables a TV accessory for switching HDMI inputs. | boolean | `false` | No | |
| `tvAccessoryConfiguredName` | Custom name for the HDMI TV accessory. | string | | No | |
| `tvAccessoryType` | Icon shown for the HDMI TV accessory in the Home app. | string | `tv` | No | `tv`, `settopbox`, `tvstick`, `audioreceiver` |
| `tvAccessoryLightbulb` | Adds an integrated lightbulb to the HDMI TV accessory. | boolean | `false` | No | |
| `modeTvAccessory` | Enables a TV accessory for switching modes (`video`, `music`, `game`). | boolean | `false` | No | |
| `modeTvAccessoryConfiguredName` | Custom name for the Mode TV accessory. | string | | No | |
| `modeTvAccessoryType` | Icon shown for the Mode TV accessory in the Home app. | string | `tv` | No | `tv`, `settopbox`, `tvstick`, `audioreceiver` |
| `modeTvAccessoryLightbulb` | Adds an integrated lightbulb to the Mode TV accessory. | boolean | `false` | No | |
| `intensityTvAccessory` | Enables a TV accessory for switching intensity (`subtle`, `moderate`, `high`, `intense`). | boolean | `false` | No | |
| `intensityTvAccessoryConfiguredName` | Custom name for the Intensity TV accessory. | string | | No | |
| `intensityTvAccessoryType` | Icon shown for the Intensity TV accessory in the Home app. | string | `tv` | No | `tv`, `settopbox`, `tvstick`, `audioreceiver` |
| `intensityTvAccessoryLightbulb` | Adds an integrated lightbulb to the Intensity TV accessory. | boolean | `false` | No | |
| `entertainmentTvAccessory` | Enables a TV accessory for switching the active Hue entertainment area. | boolean | `false` | No | |
| `entertainmentTvAccessoryConfiguredName` | Custom name for the Entertainment TV accessory. | string | | No | |
| `entertainmentTvAccessoryType` | Icon shown for the Entertainment TV accessory in the Home app. | string | `tv` | No | `tv`, `settopbox`, `tvstick`, `audioreceiver` |
| `entertainmentTvAccessoryLightbulb` | Adds an integrated lightbulb to the Entertainment TV accessory. | boolean | `false` | No | |
| `treatPassthroughAsOffForTv` | When enabled, TV accessories show as off in passthrough mode instead of on. | boolean | `false` | No | |
| `updateIntervalInSeconds` | Polling interval, in seconds, for reading Sync Box state. | integer | `5` | No | |
| `uuidSeed` | Unique identifier for this instance when running [multiple Sync Boxes](#running-multiple-sync-boxes). Leave empty for a single Sync Box. | string | | No | |
| `apiServerEnabled` | Enables the [HTTP API](#http-api). | boolean | `false` | No | |
| `apiServerPort` | Port the HTTP API listens on. Change this if the port is already in use. | integer | `40220` | No | |
| `apiServerToken` | Token required in the `Authorization` header of every API request. Must be at least 32 characters long. Generate one with e.g. `openssl rand -hex 32` — do not reuse the example value below. Required if the API is enabled. | string | | No | |
<details>
<summary>Full example config.json</summary>
```json
{
"platforms": [
{
"platform": "PhilipsHueSyncBoxPlatform",
"syncBoxIpAddress": "<SYNC-BOX-IP-ADDRESS>",
"syncBoxApiAccessToken": "<ACCESS-TOKEN>",
"defaultOnMode": "video",
"defaultOffMode": "passthrough",
"baseAccessory": "lightbulb",
"powerSwitchAccessory": false,
"tvAccessory": false,
"tvAccessoryConfiguredName": "Sync Box Input",
"tvAccessoryType": "tv",
"tvAccessoryLightbulb": false,
"modeTvAccessory": false,
"modeTvAccessoryConfiguredName": "Sync Box Mode",
"modeTvAccessoryType": "tv",
"modeTvAccessoryLightbulb": false,
"intensityTvAccessory": false,
"intensityTvAccessoryConfiguredName": "Sync Box Intensity",
"intensityTvAccessoryType": "tv",
"intensityTvAccessoryLightbulb": false,
"entertainmentTvAccessory": false,
"entertainmentTvAccessoryConfiguredName": "Sync Box Area",
"entertainmentTvAccessoryType": "tv",
"entertainmentTvAccessoryLightbulb": false,
"treatPassthroughAsOffForTv": false,
"updateIntervalInSeconds": 5,
"uuidSeed": "livingroom",
"apiServerEnabled": false,
"apiServerPort": 40220,
"apiServerToken": "<A-LONG-RANDOM-SECRET-AT-LEAST-32-CHARS>"
}
]
}
```
</details>
Each TV accessory also supports the iOS remote widget:
| Remote control | Action |
| --------------- | ----------------- |
| Up / Down | Change brightness |
| Left / Right | Change intensity |
| Select (center) | Toggle mode |
| Info button | Toggle HDMI input |
| Play / Pause | Toggle on/off |
## HTTP API
When `apiServerEnabled` is `true`, the plugin exposes a small local HTTP API for automating the Sync Box outside of HomeKit — handy for HomeKit Shortcuts, which can call arbitrary HTTP endpoints from an automation.
```
http://<YOUR-HOST-IP-ADDRESS>:<apiServerPort>
```
Every request must include the configured token in the `Authorization` header:
```
Authorization: <YOUR-TOKEN>
```
### GET /state
Returns the current state of the Sync Box as JSON:
```json
{
"hue": {
"bridgeUniqueId": "ID1",
"bridgeIpAddress": "192.168.1.2",
"groupId": "1",
"groups": {
"1": {
"name": "Living Room TV area",
"numLights": 1,
"active": true,
"owner": "HueSyncBox (ID2)"
},
"2": {
"name": "Bedroom TV area",
"numLights": 2,
"active": false
}
},
"connectionState": "streaming"
},
"execution": {
"mode": "video",
"syncActive": true,
"hdmiActive": true,
"hdmiSource": "input4",
"hueTarget": "1",
"brightness": 200,
"lastSyncMode": "video",
"video": {
"intensity": "moderate",
"backgroundLighting": true
},
"game": {
"intensity": "intense",
"backgroundLighting": false
},
"music": {
"intensity": "high",
"palette": "melancholicEnergetic"
},
"preset": null
}
}
```
### POST /state
Sets Sync Box state. The body accepts any subset of the following:
```json5
{
hue: {
bridgeUniqueId: 'ID1',
bridgeIpAddress: '192.168.1.2',
groupId: '1',
groups: {
'12345678-be8e-4866-adce-ff3800aca123': {
name: 'Living Room TV area',
numLights: 1,
active: true,
owner: 'HueSyncBox (ID2)',
},
'56169ef5-be8e-4866-adce-ff3800aca35e': {
name: 'Bedroom TV area',
numLights: 2,
active: false,
},
},
connectionState: 'streaming',
},
execution: {
mode: 'video',
syncActive: true,
hdmiActive: true,
hdmiSource: 'input4',
// hueTarget must be a valid ID from hue.groups. Any other value causes an error.
hueTarget: '12345678-be8e-4866-adce-ff3800aca123',
brightness: 200,
lastSyncMode: 'video',
video: {
intensity: 'moderate',
backgroundLighting: true,
},
game: {
intensity: 'intense',
backgroundLighting: false,
},
music: {
intensity: 'high',
palette: 'melancholicEnergetic',
},
preset: null,
},
}
```
## Development
This plugin is written in TypeScript and targets ES2022 modules. See [`CLAUDE.md`](./CLAUDE.md) for a deeper architecture overview.
```shell
npm install # install dependencies
npm run build # compile src/ -> dist/
npm link # link the plugin to your global Homebridge install
npm run watch # rebuild and restart Homebridge on changes
npm test # run the unit test suite
```
`npm run watch` runs `homebridge -U ./test/hbConfig -I -D` against the sample config in [`test/hbConfig`](./test/hbConfig). Before running it for the first time, copy `test/hbConfig/config-template.json` to `test/hbConfig/config.json` and fill in your Sync Box details (the `setup-config` script does this automatically if the file doesn't exist yet).
Other useful checks:
```shell
npm run typecheck # type-check without emitting files
npm run lint # lint TypeScript sources
npm run format # format with Prettier
```
## Getting Help
- Check the [Homebridge basic troubleshooting guide](https://github.com/homebridge/homebridge/wiki/Basic-Troubleshooting).
- Still stuck? Open an [issue](https://github.com/jabrown93/homebridge-philips-hue-sync-box/issues/new/choose) with as much detail as the template asks for.
- Have a feature idea? Open a [feature request](https://github.com/jabrown93/homebridge-philips-hue-sync-box/issues/new?template=feature-request.md).
- Want to contribute code or docs? See [CONTRIBUTING.md](./CONTRIBUTING.md).
## Acknowledgments
This plugin was originally developed by [Lukas Rögner](https://github.com/lukasroegner).