Every device in my home theater shows up in the Home app — the lights, the Apple TV, the PS5, except the one screen everything actually plays on: the projector. A Sony VPL‑XW5100 sits at the heart of the setup, and there was no way to turn it on, switch its input, or change its picture mode from HomeKit. I’d reach for the Home app to dim the lights, then reach for a separate remote for the projector.
I run a self-hosted Homebridge install to bridge the odd devices Apple’s ecosystem doesn’t speak to. But a projector is a particular kind of awkward: in HomeKit it really wants to be a Television — power plus an input picker — and the generic HTTP-webhook bridge I use for simpler devices can’t expose a Television service at all. So I wrote a proper plugin: homebridge-sony-adcp.
What It Is
homebridge-sony-adcp exposes a Sony projector (the VPL‑XW and VW series) to Apple HomeKit as a native Television accessory. You get a real TV tile in the Home app: a power button and an input picker. Pick a source and the projector switches; turn it off and it goes to standby. It also reports the projector’s model, serial number, and firmware version back to HomeKit.
Control is over Sony’s ADCP — the Advanced Display Control Protocol, a plain-text command protocol over TCP (default port 53595). The plugin talks straight to the projector on your LAN.
Inputs
Here’s the design decision at the center of the plugin. A projector has two things you’d plausibly want behind the Home app’s input picker:
- HDMI sources — HDMI 1, HDMI 2, and so on. The literal physical inputs.
- Picture modes — Cinema Film 1, Reference, Game, IMAX Enhanced, and the rest. The projector’s calibrated presets.
Different setups want different things. If everything routes through an AV receiver into a single HDMI port, the physical inputs are useless and what you really switch between are picture modes. If you plug devices straight into the projector, you want HDMI sources. So the plugin lets you choose which group is the Television’s input list — and the other group can show up as a set of switches on a companion tile.
The companion switches are a radio group: mutually exclusive, and they reflect the projector’s actual state. Change the picture mode from the projector’s own remote and the matching switch lights up in the Home app. My own setup is HDMI sources as the TV inputs, picture modes as companion switches — but a single-tile setup with picture modes as the inputs works just as well.
Configuration
The minimal config is just the projector’s IP — that gives you a standard TV tile with HDMI inputs:
{
"platform": "SonyADCPProjector",
"name": "Projector",
"host": "192.168.1.50"
}
A fuller example — named HDMI inputs plus an opt-in companion tile of picture-mode switches:
{
"platform": "SonyADCPProjector",
"name": "Projector",
"host": "192.168.1.50",
"hdmiInputs": [
{ "input": "hdmi1", "name": "Apple TV" },
{ "input": "hdmi2", "name": "PS5" }
],
"companionSwitches": "pictureModes",
"pictureModes": [
{ "mode": "cinema_film1", "name": "Cinema Film 1" },
{ "mode": "game", "name": "Game" },
{ "mode": "user3", "name": "IMAX Enhanced" }
]
}
There’s a full config UI for the Homebridge web interface too, so you don’t have to touch JSON if you don’t want to. Everything is a dropdown, including a “Custom…” picture-mode option with a free-text field — so even if your model has a mode I didn’t hard-code, you can still add it.
The Tricky Parts
A few things about HomeKit and ADCP made this more interesting than “send a command, flip a bit.”
A Television can’t be a normal bridged accessory. HomeKit requires TV accessories to be published externally — they pair through Homebridge but appear as their own tile rather than inside the bridge. The companion switches, by contrast, are an ordinary bridged accessory, so they appear and disappear cleanly when you change the configuration, with no leftover “No Response” tiles.
HomeKit’s input picker has no “none.” Its ActiveIdentifier can’t represent an off-list value — so if you switch the projector (with its physical remote) to an input or mode you didn’t expose, the tile just reads “On.” It’s a HomeKit limitation, not a bug, and it’s exactly why companion switches are nicer for the secondary group: a switch with no match simply goes dark, no ambiguity. The fix on the input side is just to expose every value you’d actually switch to.
Picture modes need a live signal; HDMI switching doesn’t. The projector will switch HDMI inputs in standby, but it rejects a picture-mode change unless it’s powered on with a source feeding it. So selecting a mode while the projector is off logs the reason and reverts the switch to its previous state rather than lying about success. Power, deliberately, is only ever changed by the TV’s own power button — selecting an input never silently powers the projector on.
Warm-up and cool-down flicker. A projector takes ten-plus seconds to actually come on, and ADCP reports several transitional states along the way. Polling naively makes the tile flash on→off→on during warm-up. The plugin shows the target state during transitions and adds a short command-latency grace window, so the tile settles instead of strobing.
Why TypeScript, Zero Dependencies
The plugin is written in TypeScript under strict settings and ships compiled JavaScript. It has no runtime dependencies — ADCP is simple enough that everything it needs comes from Node’s built-in net, crypto, and fs. Nothing to audit for vulnerabilities, nothing to bloat the install. The handshake (including the optional SHA-256 authentication, for projectors with ADCP auth enabled) is a few dozen lines against a raw TCP socket.
It’s model-agnostic by design. The picture-mode dropdown lists the common VPL‑XW values, but the projector itself is the validator — send a value it doesn’t support and it’s logged and reverted at runtime, never silently wrong. ADCP has no “list your capabilities” query, so this is the honest way to stay compatible across the whole VPL line.
Built with Claude Code
I built this with Claude Code, Anthropic’s CLI coding agent — same as ascelerate. A lot of the work here was the unglamorous middle layer: probing a sparsely documented protocol against a real device, mapping its quirks (the User 1 slot that reports as bare user, IMAX Enhanced hiding under user3, the transitional power states) onto HomeKit’s equally quirky accessory model, and chasing down the edge cases that only show up when you actually point it at hardware. That iterative loop — try a command, read the projector’s reply, adjust — is exactly where having an agent in the terminal pays off, while I focused on how the thing should behave in the Home app.
Get Started
homebridge-sony-adcp is open source under the MIT license and published to npm.
Install from the Homebridge UI — search for Sony ADCP on the Plugins tab and click Install. Or from the command line:
npm install -g homebridge-sony-adcp
On the projector, enable the ADCP service under [Advanced Settings] → [ADCP] → [Start ADCP Service], and make sure network control stays alive in standby if you want to power it on from HomeKit. Then point the plugin at the projector’s IP and you’re set.
Source and full documentation are on GitHub.
Leave a Reply