Apple TV
Apple TV and Apple TV 4K set-top boxes are controlled over the LAN using Apple's own Companion and MRP remote protocols — the same protocols the Apple TV Remote on an iPhone uses. One Apple TV on the network becomes one GEM device, and commands target the device directly (this driver creates no zones). Control requires a one-time on-screen pairing.
Two layers of control are available once paired:
- Remote control — the full on-screen-remote key set (D-pad, transport, on-screen text entry) plus launching installed apps by name.
- Now-playing feedback and an app lineup — the Apple TV pushes the current title, app, and playback state back to GEM live, and GEM turns the box's installed apps into a browsable channel lineup with fetched icons when the Apple TV is used as an AV source.
What's controlled
- Power — on / off (over the Companion protocol)
- Full D-pad and navigation: up / down / left / right / select, menu (back), home, top menu, and press-and-hold variants
- Media transport: play, pause, play/pause, stop, next, previous, skip forward / back, and a press-and-hold scrub (fast-forward / rewind)
- Volume: up / down / set level — rides the Apple TV's own volume control
- On-screen text entry: type, append, clear, and read the current on-screen text field
- App control: list installed apps and launch an app by its bundle id
- Live now-playing metadata: title, artist, album, position, current app, and play state
Prerequisites
- An Apple TV on the same LAN as GEM.
- The Apple TV powered on and awake the first time you pair, so it can display the pairing code.
- GEM's Python helper environment installed with
pyatv— this is the Python & Modules item on the Installation checklist, and it is what the Apple TV control rides on. Without it, scanning, pairing, and control all fail.
Give the Apple TV a static IP or a DHCP reservation so its address never moves. The driver finds the box by its identity on the LAN, but pinning the address keeps discovery fast and reliable.
Setup — discover and pair
- Open Devices, add a device, and choose the Apple TV driver. Give it a name, save, and enable it.
- Tell GEM which Apple TV this is. At least one of these identity fields must be set, or GEM
has nothing to connect to:
- pyatv Device ID (
apple_device_id) — the preferred binding. To get it, open the device's Commands tab and runscan_devices; GEM returns the Apple TVs it can see on the LAN, each with its identifier. Copy the identifier into this field. - Apple TV Name (
appletv_name) — the Bonjour name of the box (its device name from the Apple TV's Settings → General → About), used when no Device ID is set. - MAC Address (
mac_address) — used as the lookup identity when neither of the above is set.
- pyatv Device ID (
- With the Apple TV awake, run the
paircommand and choose protocolcompanion(the control protocol current Apple TVs use). The Apple TV displays a 4-digit code, and GEM pops up a prompt reading "Enter PIN displayed on screen." - Type the 4-digit code shown on the TV into the prompt and confirm. GEM completes the handshake, stores the pairing credentials, and reconnects automatically.
If you also want AirPlay credentials, run pair a second time with protocol airplay and enter
that code. Pairing usually takes a few seconds; once paired, GEM reconnects on its own and you only
pair again if a tvOS update invalidates the credentials (see Troubleshooting).
Pairing waits for the on-screen code for up to two minutes (set by Pairing Timeout (ms),
default 120000). If it times out, just run pair again — the Apple TV refreshes the code each
time.
Once one Apple TV is paired and connected, GEM scans the LAN and auto-creates a device entry for
every other Apple TV it finds (filling in the identifier, address, and model). Each new entry
still has to be paired individually with its own pair run before it will respond.
Using the Apple TV as an AV source
To put the Apple TV on a touchpanel as a selectable source, create an AV source for it:
- Open AV Sources and add a source whose Device is this Apple TV.
- Set the Component field to the on-screen panel you want:
appletv_ip— the full surface: a browsable app grid (tap an app to launch it), a favorites filter, an app-search field, an on-screen keyboard that types into the Apple TV, and a D-pad with play/pause and menu. This is the recommended panel.appletv— a simpler bare D-pad remote (menu, up/down/left/right, select) with no app grid.
- Save. When a user selects that source in a room, GEM draws the matching panel.
When the Apple TV is used as a source, GEM turns its installed apps into a channel lineup named
after the device — one channel per app, each with the app's icon fetched from Apple's app
catalog — and links that lineup to the AV source automatically, so you do not set the Channel
Provider field by hand. The appletv_ip panel's app grid is that lineup; press and hold an app to
mark it a favorite. See Channels for how channel lineups and the on-screen
browser work.
Attributes
Device — identity (set at least one)
| Attribute | Type | Description |
|---|---|---|
apple_device_id | string | The pyatv identifier from scan_devices (UUID / MAC / compact MAC). The preferred binding. |
appletv_name | string | The Apple TV's Bonjour / device name. Used when apple_device_id is blank. |
mac_address | string | The Apple TV's MAC address. Used as the lookup identity when the two above are blank. |
Device — optional
| Attribute | Type | Default | Description |
|---|---|---|---|
host | string | (discovered) | Pin control to a specific IP. Optional — discovery works without it. |
pairing_timeout | int | 120000 | How long (ms) to wait for the on-screen pairing code before giving up. |
GEM also manages two stored values you do not edit by hand:
companion_credentials/airplay_credentials— the pairing credentials, stored encrypted and read-only and written when you pair. They are managed for you; do not type into them.
The Apple TV reports its now-playing state back onto the device as it plays, and these values are read-only and useful as trigger conditions (for example, fire a macro when the current app becomes the one you care about):
| Attribute | Description |
|---|---|
device_state | Playback state — playing, paused, idle, etc. |
title / artist / album | Current media metadata. |
position / total_time | Elapsed and total time, in seconds. |
app_id / app_name | The app currently in the foreground (bundle id and friendly name). |
pin is a temporary attribute GEM fills from the on-screen-code prompt during pairing and clears
automatically afterward.
Commands
Driver-declared commands appear on the device's Commands tab and can be used in macros, triggers, and on UI buttons.
Power and navigation
| Command | Action |
|---|---|
power_on / power_off | Turn the Apple TV on / off (Companion protocol). |
up down left right select | D-pad navigation and select. |
menu (and back) | Menu / back. |
home | Go to the Home screen. |
top_menu | Jump to the top menu. |
hold_home hold_left hold_right | Press-and-hold the home / left / right keys (app switcher, scrub). |
Media transport
| Command | Action |
|---|---|
play pause play_pause stop | Transport controls. |
next previous | Next / previous track. |
skip_forward skip_backward (and skip_back) | Skip forward / back within the current item. |
fast_forward rewind (arg interval) | Engage scrub and seek; run the same command again to stop and resume playback. interval (seconds) sets the seek step. |
Volume
| Command | Action |
|---|---|
volume_up volume_down | Step volume on the Apple TV. |
set_volume (arg level) | Set volume to level (0–100). |
Volume rides the Apple TV's own volume control, so it only has an audible effect when the Apple TV is set up to control your TV or receiver volume (for example over HDMI-CEC). In a typical AV rack, control room volume on the receiver or amplifier instead.
On-screen text entry
| Command | Action |
|---|---|
text_set (arg text) — alias set_text | Replace the current on-screen text field with text. |
text_append (arg text) — alias append_text | Append text to the current field. |
text_clear — alias clear_text | Clear the current field. |
text_get — alias get_text | Read back the current field's contents. |
text_focus_state — alias get_text_focus | Report whether an on-screen text field has focus. |
Apps and state
| Command | Action |
|---|---|
launch_app (arg id) | Launch an installed app by its bundle id (the app_id / channel value). |
get_apps | List the Apple TV's installed apps (also rebuilds the app channel lineup). |
get_state | Refresh the now-playing metadata. |
Discovery and pairing
| Command | Action |
|---|---|
scan_devices | List the Apple TVs GEM can see on the LAN, with their identifiers. |
pair (arg protocol) | Start pairing; prompts for the on-screen 4-digit code. Choose companion (or airplay). |
Known limitations
- Position, repeat, and shuffle setting are not wired up.
set_position,set_repeat, andset_shuffle(and therepeat/shufflealiases) appear in the command list, but the chosen value is not forwarded to the Apple TV by the current integration, so they do not reliably change position, repeat, or shuffle. Treat them as placeholders. passthroughis not usable as a general escape hatch. It is intended to forward a raw remote verb, but the current integration does not substitute the verb into the request. Use the named commands above instead.- Volume needs the Apple TV in control of the display/receiver volume. See the Volume note above — otherwise control room volume on the AV gear.
- tvOS updates can invalidate pairing. A major tvOS update sometimes clears the stored
credentials; if commands silently stop working, run
pairagain.
Troubleshooting
| Symptom | Check |
|---|---|
scan_devices returns nothing | Confirm the Apple TV is powered on and on the same subnet as GEM, and that GEM's Python helper (pyatv) is installed — see Prerequisites. |
| Pairing never completes | The Apple TV must be awake to show the code, and you must enter the 4-digit code before the Pairing Timeout elapses. Run pair again to get a fresh code. |
| "apple tv pairing requires apple_device_id, mac_address, or appletv_name" | You ran pair before setting an identity field. Run scan_devices, set the pyatv Device ID (or the Apple TV Name), then pair. |
| Paired, but commands do nothing | Confirm the box's IP hasn't moved and the device is enabled. A tvOS update may have invalidated the pairing — run pair again. |
| Volume buttons have no effect | The Apple TV isn't controlling your TV/receiver volume. Configure that on the Apple TV, or drive volume on the AV gear instead. |
| App icons or names look wrong in the grid | Run get_apps to re-query the installed apps and refetch icons. |
See also
- AV Sources — add the Apple TV as a selectable source and pick the
appletv_iporappletvpanel. - Channels — how the app channel lineup and the on-screen browser work.
- Commands — running and scripting device commands.
- Devices — adding and configuring devices.
- Installation — installing the Python helper (
pyatv) Apple TV control depends on.