Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Erratic ValueError raised in get_power_mode() #289

Closed
gabortim opened this issue Oct 9, 2023 · 4 comments
Closed

Erratic ValueError raised in get_power_mode() #289

gabortim opened this issue Oct 9, 2023 · 4 comments

Comments

@gabortim
Copy link

gabortim commented Oct 9, 2023

  • Monitor manufacturer and model number: Dell U2415
  • Input source (HDMI, VGA, display port, ect.): via passive DVI-D -> HDMI cable
  • Output device (video card, discrete graphics, ect.): Nvidia GTX 1050 Ti
  • Operating system: Windows 10 (build 19045.3448)
  • Python version: 3.11.6
  • monitorcontrol version (monitorcontrol --version): 3.0.3

Steps to Reproduce

  1. Start this snippet:
      import time
      
      from monitorcontrol import get_monitors
      
      if __name__ == '__main__':
          while True:
              for i, monitor in enumerate(get_monitors()):
                  with monitor:
                      print(f"Monitor #{i}: {monitor.get_power_mode()}")
                      time.sleep(3)
  2. Wait until the display goes into standby, the issue should pop up after some time. It seems nondeterministic.
  3. Here the self._get_vcp_feature(code) returns zero, then PowerMode(value) called with this 0 which raises {ValueError}0 is not a valid PowerMode

def get_power_mode(self) -> PowerMode:
"""
Get the monitor power mode.
Returns:
Value from the :py:class:`PowerMode` enumeration.
Example:
Basic Usage::
from monitorcontrol import get_monitors
for monitor in get_monitors():
with monitor:
print(monitor.get_power_mode())
Raises:
VCPError: Failed to get the power mode.
ValueError: Set power state outside of valid range.
KeyError: Set power mode string is invalid.
"""
code = vcp.VCPCode("display_power_mode")
value = self._get_vcp_feature(code)
return PowerMode(value)

Traceback (most recent call last):
  File "C:\Users\Username\AppData\Roaming\JetBrains\PyCharm2023.2\scratches\scratch_1.py", line 9, in <module>
    print(f"Monitor #{i}: {monitor.get_power_mode()}")
                           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Projects\monitor\venv\Lib\site-packages\monitorcontrol\monitorcontrol.py", line 324, in get_power_mode
    return PowerMode(value)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\Username\AppData\Local\Programs\Python\Python311\Lib\enum.py", line 712, in __call__
    return cls.__new__(cls, value)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Username\AppData\Local\Programs\Python\Python311\Lib\enum.py", line 1135, in __new__
    raise ve_exc
ValueError: 0 is not a valid PowerMode

#288 Seems related.

@newAM
Copy link
Owner

newAM commented Oct 9, 2023

Could also be related to #117.

Does this only occur in standby mode? There are a number of monitors that simply don't respond to DDC-CI commands in standby. It is strange that this is erratic though. Perhaps check if there are some monitor power features you can tweak?

@gabortim
Copy link
Author

Yes, I've only seen it after the display entered standby. I'm going to profile it a bit more, maybe I'll find some patterns that help debug the case.

@gabortim
Copy link
Author

gabortim commented Oct 13, 2023

When I wait for Windows to put the display in sleep, it's erratic.
When I explicitly set monitor.set_power_mode(PowerMode.off_soft), it instantly reproduces edit: still erratic :( I gave up on this.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time

from monitorcontrol import get_monitors, VCPError, PowerMode
from winsound import Beep

if __name__ == '__main__':
    monitor = get_monitors()[0]
    with monitor:
        monitor.set_power_mode(PowerMode.off_soft)

    while True:
        for i, monitor in enumerate(get_monitors()):
            with monitor:
                try:
                    print(f"Monitor #{i}: {monitor.get_power_mode()}")
                    time.sleep(3)
                except (VCPError, ValueError) as e:
                    while True:
                        Beep(450, 400)
                        time.sleep(0.1)

Also, I updated to monitorcontrol 3.1.0 and the trace changed a bit:

Traceback (most recent call last):
  File "D:\Projects\monitor\test\test_offline.py", line 18, in <module>
    print(f"Monitor #{i}: {monitor.get_power_mode()}")
                           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Projects\monitor\venv\Lib\site-packages\monitorcontrol\monitorcontrol.py", line 390, in get_power_mode
    value = self._get_vcp_feature(code)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Projects\monitor\venv\Lib\site-packages\monitorcontrol\monitorcontrol.py", line 184, in _get_vcp_feature
    current, maximum = self.vcp.get_vcp_feature(code.value)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Projects\monitor\venv\Lib\site-packages\monitorcontrol\vcp\vcp_windows.py", line 135, in get_vcp_feature
    raise VCPError("failed to get VCP feature: " + ctypes.FormatError())
monitorcontrol.vcp.vcp_abc.VCPError: failed to get VCP feature: A művelet meghiúsult, mert a DDC/CI-üzenet parancsmezője érvénytelen értéket tartalmazott.

Which resembles #288 (comment). I think I'm out of luck, but at least I know the issue is in my hardware.

@gabortim
Copy link
Author

Changing closure state.

@gabortim gabortim closed this as not planned Won't fix, can't repro, duplicate, stale Oct 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants