postlund / pyatv

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

Confused about Power State #2368

Closed stevemac00 closed 2 months ago

stevemac00 commented 2 months ago

What do you need help with?

I'm sending deeplinks from my python code to atv. This works as I expect although apps.launch_app fails if atv.power.power_state == pyatv.const.PowerState.Off

So, I need to be able to atv.power.turn_on() and attempt launch_app again. Since I already was using twisted, my first thought was to add a deferred to a PowerListener but I can never receive a powerstate_update even though state changed. (Do I also have to implement push_updater.listener and push_updater.start?)

Next, I tried polling every 10ms in a non-blocking loop but logger.debug(f"atv.power.power_state={atv.power.power_state}") state never changes.

In the loop, I noticed every time I call atv = await pyatv.connect(atvconf, asyncio.get_event_loop()) I get a new atv object and a new atv.power object so this explains why my atv and atv.power objects are stale and after a few ms the latest object has the correct atv.power.power_state.

I didn't find much help with the atvremote code because the PowerListener is implemented but not called. Also, if I call as: atvremote -s 10.0.1.29 power_state turn_on delay=1000 power_state turn_off delay=1000 power_state the result is: PowerState.On PowerState.On PowerState.On

Summary: How can I implement a PowerListener to know when atv has power turned on?

stevemac00 commented 2 months ago

It's my experience PowerState cannot be relied upon. I now assume "power" is off and do this:

        for attempt in range(20):
            try:
                atv = await pyatv.connect(conf, loop)
                await atv.power.turn_on()
                await atv.apps.launch_app((url))
                logger.info(f"successful launch url={url}")
                break
            except Exception as e:
                logger.error(f"{attempt+1}: {host} err={e}")
                await sleepms(500)