postlund / pyatv

A client library for Apple TV and AirPlay devices
https://pyatv.dev
MIT License
839 stars 91 forks source link

Power state not updated when device turned off with active airplay connections #2209

Open indiefan opened 9 months ago

indiefan commented 9 months ago

Describe the bug

I noticed with the new companion-based power state code, my apple tv would sometimes not trigger state-changed automations in home assistant.

It happens when I have the audio output set to multiple external airplay devices (if I disconnect first then power off the device, the automations do trigger).

Error log

<place log here>

How to reproduce the bug?

  1. Turn on Apple TV
  2. Connect apple tv to multiple output devices (I did this via the audio interface add_output_devices() method
  3. Turn off Apple TV
  4. Check the power state

What is expected behavior?

Expected power state of the Apple TV is PowerState.Off. Observed power state of the Apple TV is PowerState.On

Operating System

Linux

Python

3.8

pyatv

0.14.0

Device

Apple TV 4k tvOS 15

Additional context

After triggering the bug, I did some digging in a REPL. Not sure if this is expected or not, but I see the power state out of sync with the attention state (usually "On" maps to "Awake"):

>>> atv.power.power_state
<PowerState.On: 2>
>>> await atv.power._interfaces[Protocol.Companion].api.fetch_attention_state()
<SystemStatus.Asleep: 1>
postlund commented 9 months ago

This seems to still be the case, yep. Very unfortunate. Apparently it seems like Apple has decided that the Apple TV remains on (it does not go to sleep when you select "Turn off") if you have an additional AirPlay speaker grouped with it. I have verified the state with my HomePod grouped an turning the Apple TV on and off.

If you run commands from the REPL like that, you are interrupting the asyncio loop so if a system event gets triggered (i.e. system state changes), that will not be dispatched by the loop to the power manager in Companion, so state will end up out of sync.

indiefan commented 9 months ago

That's disappointing. You'd think there would be some state exposed that was usable here considering it handles all the hdmi cec stuff appropriately. Is that just a stateless protocol, or is the Apple TV retaining the relevant state opaquely?