본문 바로가기
Review/일상

모니터 진짜 전원 끄는 파이썬 코드

by 조이써니 2025. 6. 5.
반응형

Python으로 모니터 전원 제어하기 (monitorcontrol 사용)

이 블로그 글에서는 Python의 monitorcontrol 라이브러리를 사용하여 모니터의 전원을 완전히 껐다 켜는 방법을 단계별로 살펴봅니다. DDC/CI(Display Data Channel/Command Interface) 프로토콜을 활용해 VCP(Virtual Control Panel) 코드를 송신함으로써 물리 모니터의 전원 모드를 제어할 수 있으며, Windows와 Linux 환경 모두에서 동작합니다:contentReference[oaicite:0]{index=0}. 예시로 제공된 코드를 블로그 독자가 그대로 복붙해 쓸 수 있도록, 설치부터 기본 코드 설명, Troubleshooting, 그리고 확장 사용 사례까지 HTML 형식으로 정리했습니다.

목차

  1. 개요 및 DDC/CI란?
  2. monitorcontrol 설치
  3. 기본 코드 설명
  4. 어떻게 동작하는가
  5. Troubleshooting & 주의사항
  6. 고급 사용 예시
  7. 참고 문헌

1. 개요 및 DDC/CI란?

DDC/CI(Display Data Channel/Command Interface)는 모니터와 그래픽 카드 간에 표준화된 커뮤니케이션을 제공하는 프로토콜입니다. 이를 통해 호스트(PC)는 모니터의 EDID(Extended Display Identification Data)를 읽을 뿐만 아니라, 밝기(brightness), 대비(contrast), 전원 모드(power mode) 등 다양한 설정을 직접 제어할 수 있습니다:contentReference[oaicite:1]{index=1}.

DDC/CI를 사용한 제어 명령은 VESA MCCS(Monitor Control Command Set)라는 규격에 정의되어 있으며, 0xD6라는 VCP 코드(Power Mode)를 통해 모니터를 완전히 “Off” 상태로 전환하거나 “On” 상태로 복귀시킬 수 있습니다:contentReference[oaicite:2]{index=2}. … 즉, 단순히 화면만 끄는 것이 아니라 전력이 실제로 끊긴 상태로 만들어 줍니다.

Python에서는 monitorcontrol 라이브러리를 통해 이런 DDC/CI 명령을 간단한 API 호출 형태로 사용할 수 있습니다:contentReference[oaicite:3]{index=3}. Windows, Linux 모두 지원되며, 별도의 C 언어 바인딩 없이 순수 Python 코드로 모니터 전원 제어가 가능합니다.

2. monitorcontrol 설치

2.1 Windows 환경

Windows 환경에서는 Python 3.x를 설치한 뒤, 아래 명령으로 monitorcontrol를 설치합니다:

py -3 -m pip install monitorcontrol

:contentReference[oaicite:4]{index=4}

2.2 Linux 환경

Ubuntu, Debian 등 대부분의 배포판에서 Python 3 환경이 활성화된 상태라면, 아래 명령으로 설치할 수 있습니다:

python3 -m pip install monitorcontrol

:contentReference[oaicite:5]{index=5}

설치 완료 후, Python REPL에서 import monitorcontrol 구문이 에러 없이 동작하면 설치가 정상적으로 완료된 것입니다.

3. 기본 코드 설명

아래 코드는 블로그 머릿글 앞부분에서 소개한 예시 그대로이며, monitorcontrol.get_monitors()로 시스템에 연결된 모든 모니터 객체를 순회하면서 VCP 코드 0xD6를 통해 전원 모드를 제어하는 함수들입니다:contentReference[oaicite:6]{index=6}.

from monitorcontrol import get_monitors

# 연결된 모든 모니터를 순회하며 전원 Off/On 제어
def turn_off_all_monitors():
    for monitor in get_monitors():
        with monitor:
            # VCP 코드 0xD6에 0x02 전송 -> 전원 Off
            monitor.set_power_mode(0x02)

def turn_on_all_monitors():
    for monitor in get_monitors():
        with monitor:
            # VCP 코드 0xD6에 0x01 전송 -> 전원 On
            monitor.set_power_mode(0x01)

if __name__ == "__main__":
    turn_off_all_monitors()  # 모니터 전원 끄기
    # 필요시 import time; time.sleep(숫자) 후 turn_on_all_monitors() 호출

코드 동작 순서:

  1. get_monitors() 호출: 시스템에 연결된 DDC/CI 지원 모니터들의 리스트를 반환합니다:contentReference[oaicite:7]{index=7}.
  2. with monitor: 블록 내부에서 해당 모니터와의 DDC/CI 통신이 활성화됩니다.
  3. monitor.set_power_mode(0x02): VCP 코드 0xD6에 값 0x02를 보내 물리 모니터 전원을 완전히 Off로 전환합니다:contentReference[oaicite:8]{index=8}.
  4. monitor.set_power_mode(0x01): VCP 코드 0xD6에 값 0x01를 보내 전원을 다시 On 상태로 변경합니다:contentReference[oaicite:9]{index=9}.

4. 어떻게 동작하는가

4.1 VCP 코드 0xD6(Power Mode)

VESA MCCS 명세에서 0xD6는 Power Mode를 의미하며, 이 값에 따라 모니터 전원을 제어할 수 있습니다:contentReference[oaicite:10]{index=10}. 주요 값은 다음과 같습니다:

  • 0x01: 전원 On
  • 0x04: 절전(Standby/Low Power)
  • 0x02: 전원 Off
  • 0x03: 스탠바이(Standby)

monitorcontrol 라이브러리의 set_power_mode 메서드는 내부적으로 I²C 채널을 통해 이 VCP 코드를 모니터로 전달하며, 모니터 펌웨어에서 해당 값에 맞춰 전원 모드를 전환합니다:contentReference[oaicite:11]{index=11}.

4.2 DDC/CI 통신 과정

일반적으로 모니터와 그래픽 카드는 케이블(HDMI, DVI, DisplayPort) 상에서 DDC 라인을 통해 통신하며, OS 측 드라이버를 통해 I²C 명령이 모니터로 전송됩니다:contentReference[oaicite:12]{index=12}. monitorcontrol는 이 과정을 추상화하여 Python 호출만으로도 필요한 바이트 스트림을 자동 생성해 전송합니다.

다만, 일부 구형 또는 저가형 모니터에서는 DDC/CI 기능을 완전히 지원하지 않거나, DisplayPort 연결 시 DDC/CI 채널이 비활성화되는 경우가 있어 동작하지 않을 수 있습니다. 이럴 때는 HDMI/DVI로 케이블을 교체하거나, 모니터 OSD 설정에서 DDC/CI를 활성화해야 합니다:contentReference[oaicite:13]{index=13}.

5. Troubleshooting & 주의사항

5.1 DDC/CI 미지원 모니터

모든 모니터가 DDC/CI를 지원하는 것은 아닙니다. 특히 일부 TV나 저가형 모니터는 VCP 코드 0xD6를 지원하지 않을 수 있습니다. 이 경우 monitor.get_capabilities() 메서드를 통해 해당 모니터가 지원하는 VCP 코드를 확인할 수 있으므로, 0xD6가 없으면 “Off” 대신 “Low Power(0x04)”만 사용하거나, 전혀 제어가 불가능할 수 있습니다:contentReference[oaicite:14]{index=14}.

5.2 권한 문제 (Windows)

Windows 환경에서 DDC/CI 명령을 보내려면, 일반적으로 관리자 권한이 필요하지 않지만, 일부 드라이버와 보안 설정에 따라 “관리자 권한으로 실행”이 필요한 경우가 있습니다. Python 스크립트를 우클릭 → “관리자 권한으로 실행”으로 실행하거나, 작업 스케줄러(Task Scheduler)에 등록할 때 “가장 높은 권한으로 실행” 옵션을 체크하면 권한 오류를 피할 수 있습니다:contentReference[oaicite:15]{index=15}.

5.3 원격 데스크톱(RDP) 환경

RDP 세션(RDP(Remote Desktop Protocol))으로 원격 접속한 상태에서 turn_off_all_monitors()를 호출하면, “원격 데스크톱 세션 창”이 꺼지지만 실제 물리 모니터 전원까지 차단되지는 않습니다. 이런 경우 물리적 모니터 전원까지 완전히 끄려면 Smart Plug나 원격 전원 스위치를 사용하거나, 원격지에서 직접 실행 가능한 DDC/CI 유틸리티(CLI 기반)로 제어해야 합니다:contentReference[oaicite:16]{index=16}.

5.4 Linux의 Wayland 환경

Ubuntu 등 일부 최신 리눅스 배포판에서 Wayland 세션을 사용하면, DDC/CI 제어가 제한될 수 있습니다. Wayland는 X11을 대체하는 디스플레이 서버 프로토콜인데, 이때는 monitorcontrol가 내부적으로 I²C 장치를 직접 열어 통신해야 하므로 권한 또는 드라이버 호환성 문제가 발생할 수 있습니다. 이럴 경우 X11(Xorg) 세션으로 로그인한 뒤 테스트하거나, ddcutil 명령을 별도 호출하는 방식을 고려해야 합니다:contentReference[oaicite:17]{index=17}.

6. 고급 사용 예시

6.1 특정 모니터만 제어하기

멀티 모니터 환경에서 특정 모니터만 전원을 끄고 싶다면, get_monitors() 대신 for monitor in get_monitors(): print(monitor) 등으로 디스플레이 ID를 확인한 뒤, 선택적으로 제어할 수 있습니다:contentReference[oaicite:18]{index=18}.

def turn_off_monitor_by_index(index: int):
    """
    index: get_monitors() 순서(0부터 시작)
    """
    monitors = list(get_monitors())
    if index < 0 or index >= len(monitors):
        raise IndexError("유효하지 않은 모니터 인덱스입니다.")
    with monitors[index]:
        monitors[index].set_power_mode(0x02)  # 해당 모니터만 Off

# 예시: 세 번째 모니터만 끄기 (인덱스 2)
if __name__ == "__main__":
    turn_off_monitor_by_index(2)

6.2 밝기 제어 및 입력 전환

monitorcontrol는 전원 모드 외에도 밝기(brightness), 대비(contrast), 입력 소스(input source) 등 다양한 VCP 코드 제어를 지원합니다:contentReference[oaicite:19]{index=19}. 예를 들어, 밝기를 50%로 설정하려면 VCP 코드 0x10을 사용합니다:

def set_brightness_to(monitor, level: int):
    """
    level: 0 ~ 100 사이 밝기 값
    """
    with monitor:
        # VCP 코드 0x10 = brightness, 값(level: 0~100)
        monitor.set_luminance(level)

# 모든 모니터 밝기를 50%로 설정
if __name__ == "__main__":
    for m in get_monitors():
        set_brightness_to(m, 50)

:contentReference[oaicite:20]{index=20}

6.3 스케줄러를 통한 자동화

Windows 환경에서는 작업 스케줄러(Task Scheduler)에 Python 스크립트를 등록하여 특정 시간에 자동으로 모니터를 끌 수 있습니다. 예를 들어, 매일 밤 11시 정각에 스크립트를 실행하려면:

  • 작업 스케줄러 열기 → 작업 만들기(Create Task) → 일반(General) 탭 → “가장 높은 권한으로 실행” 체크
  • 트리거(Triggers) 탭 → 새로운 트리거(New) 설정 → 매일 23:00
  • 동작(Actions) 탭 → 새로운 동작(New) → 프로그램/스크립트: python, 인수: “C:\경로\monitor_off.py”
  • 조건(Conditions) → “절전 모드에서 깨우기” 등 필요시 설정

:contentReference[oaicite:21]{index=21}

Linux 환경에서는 cron 탭(예: crontab -e)에 아래와 같이 추가할 수 있습니다:

# 매일 밤 23시 정각에 turn_off.py 실행
0 23 * * * /usr/bin/python3 /home/username/turn_off.py

:contentReference[oaicite:22]{index=22}

7. 참고 문헌

  • newAM/monitorcontrol: Python monitor control using DDC-CI (GitHub). :contentReference[oaicite:23]{index=23}
  • monitorcontrol — PyPI (monitorcontrol 프로젝트 설명). :contentReference[oaicite:24]{index=24}
  • python StackOverflow: “Sending DDC/CI commands to monitor on Windows using Python?” :contentReference[oaicite:25]{index=25}
  • MonitorControl/MonitorControl (GitHub 리포지토리, macOS용). :contentReference[oaicite:26]{index=26}
  • monitorcontrol 문서 — Read the Docs. :contentReference[oaicite:27]{index=27}
  • monitorcontrol 최신 문서 — newAM GitHub Pages. :contentReference[oaicite:28]{index=28}
  • monitorcontrol 공식 문서 (버전 1.6). :contentReference[oaicite:29]{index=29}
  • StackOverflow: “Turn screen on and off on Windows - Python”. :contentReference[oaicite:30]{index=30}
  • Display Data Channel 위키백과 문서. :contentReference[oaicite:31]{index=31}
  • monitorcontrol 사용자 토론 (Raspberry Pi Forums). :contentReference[oaicite:32]{index=32}
  • monitorcontrol Linux 관련 논의 (openSUSE Forums). :contentReference[oaicite:33]{index=33}
반응형

댓글