wakepy icon indicating copy to clipboard operation
wakepy copied to clipboard

Provide information about idle timer status after exiting the keep.running / keep.presenting modes

Open fohrloop opened this issue 6 months ago • 2 comments

Instead of just documenting the information that "what is the system sleep status" after existing a wakepy Mode, it would be nice to get the information programmatically.

Proposed interface

See this comment

status

Not sure yet if this is going to be implemented. I think that for wakepy 1.0.0 there are already enough other things to do that have higher priority.

fohrloop avatar Jul 16 '25 09:07 fohrloop

I'm a little concerned about the m.method.resets_idle_timer being True/False/None.

First, it cannot be just boolean (True/False), because for some methods the behavior is unknown. If it would also allow being None, people still could easily misuse it like this:

if m.method.resets_idle_timer:
    # do something (assuming idle_timer is reset)
else:
   # assume that the method did NOT reset the timer

but in reality the resets_idle_timer might be None, which would, being falsy, lead to accidentally assuming that the idle_timer was NOT reset.

alternative

The logical alternative would be to use some method where the value is not just truthy/falsy, but always truthy, and the user would have to compare the value to known values. Either:

if m.method.idle_timer_reset == 'resetting':
    ...
elif m.method.idle_timer_reset == 'non-resetting':
    ...
else: # 'unknown'
    ...

or against some enumerated values like:

from wakepy import IdleTimerResetType

if m.method.idle_timer_reset == IdleTimerResetType.RESETTING:
    ...
elif m.method.idle_timer_reset == IdleTimerResetType.NON_RESETTING:
    ...
else: # unknown
    ...

fohrloop avatar Jul 17 '25 15:07 fohrloop

I have given this a bit more thought.

What would a user want to know?

If a user is interested about the idle timer status after deactivating the inhibitor, the goal is probably to estimate when the automatic suspend might occur (does it occur right away or a few minutes later, if there's no user activity)

To accurately estimate time of next automatic suspend, one would need to know - When wakepy inhibitor flags were or will be cleared? (this is possible) - Did the last wakepy inhibitor reset the idle timer (this is possible) - What is the time of the last user activity (out of scope of wakepy) - What other inhibitors are active? (this is not possible or it's very difficult, out of scope of wakepy, or a borderline case. Not all of the inhibitor types have easy way to check if there's anything active. Sometimes it could be just a YouTube video playing which acts as an inhibitor) - What other inhibitors have been active, did they reset the idle timer and when they were exited (out of scope of wakepy) - What is the idle timer limit for display off and for suspend? (I would say this is also either out of scope of wakepy, or a borderline case)

What wakepy could offer?

For getting the latest idle timer reset

  • Mode.exited_at (dt.datetime)
  • MethodInfo.idle_timer_reset (RESETTING | NON_RESETTING | UNKNOWN)

Getting info when inhibit flags are cleared

Term: post exit inhibit: On Windows 10, after every inhibitor exit, there is 2 minutes of post exit inhibit (which seems to be stochastic, so sometimes it may be 1:30min, and sometimes 3:30min. See #450)

  • Mode.inhibit_flag_clear_time (dt.datetime). If there is no "post exit inhibit", this would equal to exited_at. If there is one, this would equal to exited_at + post_exit_inhibit
  • Mode.inhibit_flag_clear_time_earliest (dt.datetime): The post exit inhibit time seems to be sometimes stochastic. This would be the "good rule of thumb earliest possible time the inhibit flag will be cleared"
  • Mode.inhibit_flag_clear_time_lastest (dt.datetime): Similar to inhibit_clear_time_earliest, but the latest expected time.

Helper values

Related nice-to-know information which is easy to add

  • Mode.entered_at (dt.datetime)
  • Mode.duration (timedelta)

Required values

For the implementation, each method should have:

  • Method.idle_timer_reset (IdleTimerResetType): RESETTING | NON_RESETTING | UNKNOWN
  • Method.inhibits_after_exit (PostExitInhibitType): POST_INHIBIT | NO_POST_INHIBIT | UNKNOWN
  • Method.post_exit_inhibit (float) -- seconds typically inhibited after exiting the inhibitor
  • Method.post_exit_inhibit_range (tuple[float, float]) -- the range of values for post_exit_inhibit within it's assumed to be "almost always" (when the post-inhibit time is not deterministic)

How to get these values?

The required values are not easy to find for most of the systems. The easiest solution is to run a series of tests (like in #450) with scripts/example-test-with-wakepy.py and get the values from the data empirically.

fohrloop avatar Jul 18 '25 19:07 fohrloop