Apple TV

Using Apple TV with Home Assistant. Has notes on how Home Asssistant connects.


These are notes on on ongoing "project" that I sporadically work on, not actual documentation of how to achieve anything.


For a while my hass instance would loose track of the Apple TV if it went into a sleeping state. This was a bit of a problem for me, as I mainly relied on the state of my ATV to turn my (old and power hungry amp) on and off.

This was a known bug and had been fixed but the problems persisted for me, and it turned out that I had a config issue (probably as well as being affected by the bug). Saw the commit 33387bf and got clued in to what was going on: the hass integration is relying on the "Companion Protocol".

Reliable connection on local network

I had added it by hostname/ip, and it turns out that it relies heavily on the mdns advertisements from the ATV and its "identifiers" instead. Adding it as the "name" of the ATV (mine is creatively named "Apple TV") and now hass doesnt loose track of it when it goes to sleep and is immediately aware of the state of the ATV as soon as it wakes up.

This reliance on mdns and discovery requires you to run hass on the same network, which is an annoying constraint (though I do run it on the same network).

Can we use a proxy?

The hass integration uses pyatv, which comes with the (rather neat) atvproxy tool, which can proxy the companion protocol (and all the others too). Idea: can we use that as a bridge between home assistant and ATV?

First, we have to find the Apple TV and the identifiers:

$ atvremote scan
Scan Results

       Name: Apple TV
   Model/SW: Apple TV 4K, tvOS 16.6
        MAC: 8C:42:99:82:4C:CB
 Deep Sleep: False
 - 8B2E0556-6BFF-46AB-B977-3D8E678D38A4
 - 8C:42:99:82:4C:CB
 - 8C4299824CCB

Then we pair atvremote with the ATV for the companion protocol (note how we direct it to the ATV with the UUID, and not ip/hostname):

$ atvremote --id 8B2E0556-6BFF-46AB-B977-3D8E678D38A4 --protocol companion pair
Enter PIN on screen:

After that it spits out an authentiction token, which I saved as ~/.config/atv.credentials. Then we can start atvproxy for the companion protocol:

$ atvproxy companion `cat ~/.config/atv.credentials`
2023-08-18 00:50:30 DEBUG [pyatv.scripts]: Running with pyatv 0.13.4
2023-08-18 00:50:30 DEBUG [pyatv.scripts.atvproxy]: Binding to local address
2023-08-18 00:50:30 INFO [pyatv.scripts.atvproxy]: Started Companion server at port 46507
2023-08-18 00:50:30 DEBUG [pyatv.core.mdns]: Publishing zeroconf service: ServiceInfo(type='_companion-link._tcp.local.', name='Proxy._companion-link._tcp.local.', [....])

And now the proxy appears as an Apple TV named Proxy on the network, which the hass integration can connect to.


2023-08-18initial notes on pairing and starting atvproxy



Control your Apple TV using Perl: Wake up Apple TV over TCP on port 7000.