Binding for Apple-TV

Looks like I have it fixed. With some carefully selected help from ChatGPT, I reinstalled the custom patv and now the Apple TV thing is staying online.

Somewhere along the way I must have installed the wrong patv version.

Thanks for your help and pointers, and apologies for my randomization.

Hi-

Sorry for not getting back to this conversation sooner. I’m glad you were able to figure out what was going on. If you have specific points that were confusing, do let me know, as I’d like to be able to make the process as simple as possible (though having the binding do everything for you is the ultimate goal).

Hope it works well going forward, and feel free to get in touch if you run into problems or have any great ideas!

Bill

hi @hww3 i double check the settings, get rid off all automation and the problem is still there.

Problem: If the Power Status switch / channel is OFF, sending OFF again triggers the apple tv to ON.

Test#1

1/ Power status == OFF

2026-01-25 13:04:54.173 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on
2026-01-25 13:04:54.174 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

Test#2

2/ Power status == ON

2026-01-25 13:05:28.437 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

i just runn this test with simple js

i

tems.getItem(ā€œApple_TV_sypialnia_AppleTV_Gen4K_Power_Statusā€).sendCommand(ā€˜OFF’)

items.getItem(ā€œApple_TV_sypialnia_AppleTV_Gen4K_Power_Statusā€).sendCommand(ā€˜OFF’)


So confirmed problem is when you SENDCOMMAND OFF to an item which is already OFF you get

2026-01-25 13:08:19.317 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on
2026-01-25 13:08:19.318 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

Which turs te appletv ON for a few milis, the apple TV is turnning on the TV, but not turinig it off on the off command. TV stays on which is pain in the ass for me because there is a 5 minute delay to turn off when there is no hdmi signal.

Here are full responsoses of the pytv library - > every time frame IS one single OFF command send to the item which is OFF. Most of the times i still get ON command, rarly there is only OFF and this is ok.


2026-01-25 13:08:09.057 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off
2026-01-25 13:08:19.317 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on

2026-01-25 13:08:19.318 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:09:15.802 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:09:33.297 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on
2026-01-25 13:09:33.298 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:09:38.537 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on
2026-01-25 13:09:38.537 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:09:47.346 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on
2026-01-25 13:09:47.348 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:11:27.415 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:11:39.081 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on
2026-01-25 13:11:39.082 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:11:48.378 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off

2026-01-25 13:11:55.014 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_on
2026-01-25 13:11:55.015 [INFO ] [nding.appletv.internal.PyATV$Scanner] - queueing command: turn_off


Hi- Apologies for the delay in responding, I’ve been traveling for work and have just returned home. I’ll try to take some time to read through this more carefully, but a few quick comments on what you’re experiencing:

First, I don’t think there’s a way to control the behavior where an AppleTV will turn the device it’s connected to on but not back off. I personally rely on my TV turning itself off when it detects that there’s no signal.

Second, part of the problem is that when an AppleTV device has gone to sleep, it silently ignores any commands sent to it, with the exception of the power state. To get around that problem, the binding will send the power on command whenever a command is sent to a sleeping device that isn’t also ā€œpower onā€.

It’s not unreasonable to suggest that telling a sleeping device to power off is basically a command we should ignore. However, There is a potential problem in that the binding’s understanding of a device’s state can get out of sync with the device (particularly the power state), and I’m worried that might create more problems than it solves.

One suggestion might be to check that the device is off before telling it to turn off. That might avoid at least some of the problem.

I’m happy to hear comments and suggestions about this, one way or the other.

I’ve just upgraded to tvOS 26.5 and the AppleTV binding is now broke… OpenHAB reports a configuration error. Anyone with guidance on how to troubleshoot and fix? Thanks!

Have you updated openhab as well?

I’m on version 5.01, which I think is the latest version.

The log file shows the below. Any suggestions for what I should do next? All was fine until I updated the AppleTV to 26.5

Pairing failed: 2026-05-13 21:50:18 ERROR \[pyatv.protocols.companion\]: Could not fetch SystemStatus, power_state will not work (Command FetchAttentionState failed) Traceback (most recent call last): File "/usr/lib/python3.11/asyncio/tasks.py", line 490, in wait_for return fut.result() ^^^^^^^^^^^^ File "/usr/lib/python3.11/asyncio/locks.py", line 213, in wait await fut asyncio.exceptions.CancelledError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/protocols/companion/api.py", line 172, in \_send_command resp = await self.\_protocol.exchange_opack( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/protocols/companion/protocol.py", line 153, in exchange_opack return await self.\_exchange_generic_opack(frame_type, data, identifier, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/protocols/companion/protocol.py", line 166, in \_exchange_generic_opack unpacked_object = await self.\_queues\[identifier\].wait(timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/support/collections.py", line 161, in wait await asyncio.wait_for(self.\_event.wait(), timeout) File "/usr/lib/python3.11/asyncio/tasks.py", line 492, in wait_for raise exceptions.TimeoutError() from exc TimeoutError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/protocols/companion/\__init_\_.py", line 219, in initialize system_status = await self.api.fetch_attention_state() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/protocols/companion/api.py", line 439, in fetch_attention_state resp = await self.\_send_command("FetchAttentionState", {}) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/protocols/companion/api.py", line 183, in \_send_command raise exceptions.ProtocolError(f"Command {identifier} failed") from ex pyatv.exceptions.ProtocolError: Command FetchAttentionState failed

I asked because every time you upgrade OH you have to reinstall the python part. See my previous posting about it.

Got it, makes sense. I’ve not knowingly updated OpenHAB. I’m still on OpenHAB 5.0.1 Release Build.

Ok. I will check my 2 sites later tonight.
Just made the appletv upgrade myself.

You are right. I get the exact same error on 26.5.
@hww3 any ideas?

Edit: a fix has already been made over at: FetchAttentionState silently dropped on Apple TV 4K gen 3(AppleTV14,1) with tvOS 26.5 -- pyatv 0.17.0 does not fix Ā· Issue #2845 Ā· postlund/pyatv Ā· GitHub

I assume we can’t just apply this fix and we need to wait for the OpenHAB ready version?

We kan wait for @hww3 or patch manually like: FetchAttentionState silently dropped on Apple TV 4K gen 3(AppleTV14,1) with tvOS 26.5 -- pyatv 0.17.0 does not fix Ā· Issue #2845 Ā· postlund/pyatv Ā· GitHub

Ok thanks. My preference is to wait for Bill’s update.

Hi All-

My devices are still at 26.4, and still seem to be working. There was a pyatv since the last binding update, it may be more than just patching the file described (though it’s possible that’s all that is needed).

I’ve got some high priority tasks going on here, so it’s probably going to be a week before I have time to really dig into this problem in depth.

If someone wants to try the patch, I’d recommend first taking a backup of the tmp/appletv directory in case things go sideways.

I think I’ve mentioned this before, but we’re entirely at Apple’s mercy when it comes to keeping this integration working. Any update could cause things to break temporarily (or even permanently), so I highly recommend disabling auto-update on your devices if it’s important that things work.

I wish there were a way to know if any given tvos update was ā€œsafeā€, but I don’t think anyone has built such a thing. Then we could at least know that basic functionality still worked, rather than many people discovering that independently. Maybe some adventurous soul with a spare AppleTV wants to be a hero to the rest of the world?

Thanks for the update Bill, totally get the priorities. I’m not certain I’m sufficiently skilled to experiment further but maybe I can try (I might learn something new along the way!).

I set out trying to patch, but got lost on these two directions:

Simply insert this code in your app/library :

# Then in your main program when it starts :

Don’t know what files applies in our case …

Well if you are having difficulty this is well beyond my level. I’ll await the easier option!

With help from Claude, I think I was able to insert the necessary code and it appears to be working. It seems to have been fairly straightforward. Before starting, I made a backup copy of the /tmp/appletv-binding folder as suggested by Bill.

Below are the instructions as provided by Claude

Firstly, the code needs to be inserted into the _init_.py file…

sudo nano /var/lib/openhab/tmp/appletv-binding/lib/python3.11/site-packages/pyatv/protocols/companion/__init__.py

At the end of this file, the following code was added, which is a slightly modified version of what on GitHub.

async def patched_pyatv_companion_connect(self):
    """Patch connect method for pyatv Companion protocol."""
    if self._protocol:
        return
    from pyatv.protocols.companion import connection as _conn_mod
    from pyatv.protocols.companion import protocol as _proto_mod
    from pyatv.auth import hap_srp as _hap_srp
    self._connection = _conn_mod.CompanionConnection(
        self.core.loop,
        str(self.core.config.address),
        self.core.service.port,
        self.core.device_listener,
    )
    self._protocol = _proto_mod.CompanionProtocol(
        self._connection, _hap_srp.SRPAuthHandler(), self.core.service
    )
    self._protocol.listener = self
    await self._protocol.start()
    await self.system_info()
    await self._touch_start()
    await self._session_start()
    await self._send_command("TVRCSessionStart", {"ProtocolVersionKey": "1.2"})
    await self._text_input_start()
    await self.subscribe_event("_iMC")

# TODO patch for tvOS 26.5 : to be removed when fixed
from pyatv.protocols.companion import api as _companion_api
_companion_api.CompanionAPI.connect = patched_pyatv_companion_connect

The changes from the GitHub version is the use of relative imports… per Claude…

The patch code looks correct. The issue is that lines 698-699 still reference pyatv.protocols.companion.protocol and pyatv.auth.hap_srp using the full pyatv. prefix, which aren’t available that way inside the package itself.

Let’s fix the function to use relative imports instead.

Once OpenHAB was restarted, the Apple TV Thing started to appear online and the existing automation I had created working correctly.

Claude did also mention the below so clearly a more robust fix is needed.

:warning: Important caveat: This edit will be wiped every time OpenHAB restarts because that folder gets re-extracted from the binding JAR. If it works, we’ll need to figure out a way to make it persistent — but let’s confirm it fixes the issue first.

Hope this helps!