Control a Hisense VIDAA TV or projector — such as the Hisense M2 laser projector — from your terminal or your keyboard.
VIDAA devices are not Android/Google TV, so adb does nothing. Instead they run a local MQTT broker (the one the RemoteNOW phone app talks to) over mutual TLS on port 36669. This is a small, dependency-light TypeScript/Bun implementation of that protocol, plus a ready-made Hammerspoon config so your MacBook keys drive the projector.
- Play/pause, next/prev, volume, and any raw VIDAA key
- Speaks the real protocol: mutual TLS + MAC-derived dynamic credentials
- Auto-discovers the device on your LAN and pairs with an on-screen PIN
- Hyper-key (
⌃⌥⌘) hotkeys via Hammerspoon — never clash with macOS media keys - One runtime dependency (
mqtt-packet)
git clone https://github.com/adamazad/vidaa-remote.git
cd vidaa-remote
bun installRequires Bun (uses Bun's node:tls). The client certificate needed for the TLS handshake ships in certs/ — no extra setup.
Make sure the device is on and on the same network, then:
bun src/cli.ts pairIt scans the LAN, finds the projector (excluding your Mac and the router), shows a 4-digit PIN on screen, and asks you to type it in. On success it writes ~/.config/vidaa-remote/config.json.
If auto-discovery is ambiguous, pass the IP (and optionally MAC):
bun src/cli.ts pair 192.168.1.164
bun src/cli.ts pair 192.168.1.164 7C:01:3E:5F:1D:9BTip: give the projector a static DHCP reservation on your router so its IP never changes.
bun src/cli.ts volup # volume up
bun src/cli.ts voldown # volume down
bun src/cli.ts playpause # toggle play/pause
bun src/cli.ts next # fast-forward
bun src/cli.ts prev # rewind
bun src/cli.ts key KEY_MUTE # any raw VIDAA key
bun src/cli.ts discover # list VIDAA devices on the LANNamed actions: playpause, next, prev, volup, voldown, mute, home, back, ok, up, down, left, right, power.
Config resolution order: CLI args → env (VIDAA_HOST / VIDAA_MAC) → ~/.config/vidaa-remote/config.json.
brew install --cask hammerspoon- Edit
hammerspoon/projector.lua— setREPOto your clone path. - Copy it into
~/.hammerspoon/init.lua(ordofile(".../projector.lua")). - Launch Hammerspoon, grant Accessibility, enable Launch at login, reload config.
| Shortcut | Action |
|---|---|
⌃⌥⌘ Space |
play/pause |
⌃⌥⌘ ← / → |
previous / next |
⌃⌥⌘ ↑ / ↓ |
volume up / down |
The Hyper chord (ctrl+alt+cmd) is unused by macOS, so your normal media keys keep controlling the Mac.
import { VidaaTV } from "vidaa-remote";
const tv = new VidaaTV("192.168.1.164", "7C:01:3E:5F:1D:9B");
await tv.connect();
await tv.action("volup");
await tv.sendKey("KEY_MUTE");
await tv.close();- Transport — MQTT over TLS on port
36669. The broker requires a client certificate (mutual TLS); without it the handshake fails withcertificate required. The standard VIDAA/RemoteNOW cert is incerts/. - Credentials — modern VIDAA firmware derives the MQTT
clientId/username/password from the device MAC and the current timestamp (seesrc/credentials.ts). No cloud, no account. - Pairing — publishing
vidaa_app_connectpops a PIN on screen; sending it back as{ "authNum": <int> }authorizes this MAC identity for good. - Keys — a key press is a raw string (e.g.
KEY_VOLUMEUP) published to/remoteapp/tv/remote_service/<clientId>/actions/sendkey.
- The send-key topic segment is the generated
clientId, not the literalHomeAssistantsome references show — publish to the wrong one and the device silently ignores you. - Bun's TLS always negotiates TLS 1.3 and does not surface the "certificate required" alert — it just drops the socket. If you fork this to Node you'll see the real alert.
- There's no dedicated track-skip key;
next/prevmap to fast-forward/rewind (KEY_FORWARDS/KEY_BACK).
Protocol knowledge, the credential algorithm, and the TLS client certificate are derived from vidaa-control by Tom Babolewski (MIT). See NOTICE.
Not affiliated with or endorsed by Hisense or VIDAA. "Hisense" and "VIDAA" are trademarks of their respective owners. Use at your own risk, on devices you own.