RetroPie forum home
    • Recent
    • Tags
    • Popular
    • Home
    • Docs
    • Register
    • Login

    Detect Idle State - Power Off Screen

    Scheduled Pinned Locked Moved Ideas and Development
    scripthdmipower offidle
    4 Posts 4 Posters 2.5k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Q
      QuixoticDev
      last edited by QuixoticDev

      I needed a solution to power off (not just blank) the display if the system is idle for a while.
      Spent some time searching for an existing solution but the closes I got was the hdmi_blanking=1 option but I couldn't get it to work properly.

      I wrote this script to monitor joystick activity and shutdown the monitor if it's idle.
      It's hacky but it works well and has minimal overhead, might need to revisit using tvservice instead vcgencmd to control the display as there's some reports of vcgencmd not working with some displays.

      Please let me know if you've tried it and have any issues, suggestions, feedback, etc...
      The script was thoroughly commented to make it easier to review and hack at :|
      I'll be posting it to my github at some point, should make it easier to track.

      Script Functionality

      • HDMI On
        • Monitor joystick device for activity
          • Check for input in a 5 second window
          • Check every 30 seconds
        • If idle for longer than idle timeout, power off HDMI
      • HDMI Off
        • Joystick exists
          • Wait for input (blocking) - power on HDMI when detected
        • Joystick doesn't exist (ex. XBOX 360 Wireless controller timeout)
          • Sleep 1s and keep checking

      Installation Instructions

      • Copy script to user home ex. /home/pi/idle-screenoff.sh
      • Make it executable
        chmod +x /home/pi/idle-screenoff.sh
        
      • Edit the script variables to suit your timeouts and device
        # inputDevice = Device to monitor for activity
        # - Tested with XBOX 360 Controller (first joystick js0)
        inputDevice=/dev/input/js0
        
        # inputWindow = Time window (s) to monitor the device for input
        # - Check for input in a 5 second window
        inputWindow=5
        
        # inputCount = How many inputs constitute activity + 1
        # - Add 1 to desired, might be XBOX 360 unique behavior
        inputCount=2
        
        # inputInterval = Time interval (s) between input checks
        # - Wait 30 seconds between idle input checks
        inputInterval=30
        
        # inactivityTimeout = Idle time before powering off screen
        idleTimeoutM=10
        
      • Reference the script in /etc/rc.local before the exit 0 command
        #!/bin/sh -e
        #
        # rc.local
        #
        
        # Power off screen when idle
        /home/pi/idle-screenoff.sh &
        
        exit 0
        

      Script: idle-screenoff.sh

      #!/bin/bash
      #=============================================================
      # Title        : idle-screenoff.sh
      #
      # Description  : Power off the display when idle
      #                - Detects idle by monitoring joystick input
      #
      # Author       : QuixoticDev
      #
      # Version      : v1.0 - 05/23/2018
      #
      #=============================================================
      
      #--------------------
      # User Variables
      #--------------------
      # inputDevice = Device to monitor for activity
      # - Tested with XBOX 360 Controller (first joystick js0)
      inputDevice=/dev/input/js0
      
      # inputWindow = Time window (s) to monitor the device for input
      # - Check for input in a 5 second window
      inputWindow=5
      
      # inputCount = How many inputs constitute activity + 1
      # - Add 1 to desired, might be XBOX 360 unique behavior
      inputCount=2
      
      # inputInterval = Time interval (s) between input checks
      # - Wait 30 seconds between idle input checks
      inputInterval=30
      
      # inactivityTimeout = Idle time before powering off screen
      idleTimeoutM=10
      
      #--------------------
      # Script Variables
      #--------------------
      # Dont change
      idleTimeoutS=$(( ${idleTimeoutM} * 60 ))
      idleFlag=0
      
      #--------------------
      # Loop Forever
      #--------------------
      while true; do
      
          # Check if HDMI is ON
          # 1 = ON
          # 0 = OFF
          tvStatus=$(vcgencmd display_power |  awk -F'=' '{print $2}' )
      
      
          if [ ${tvStatus} -eq 1 ]; then
              #-------------------------------------------------------------------------
              # HDMI Status = ON
              #-------------------------------------------------------------------------
              # - Query joystick for input with a timeout (inputWindow)
              # - Check if idle
              #   - idle (first time) = start counter and set idle flag
              #   - idle (subsequent) = Do nothing, keep looping
              #   - Active            = Reset idle flag
              # - Sleep between checks (inputInterval)
              # - Check if idle flag has been active for longer than the idleTimeoutM
              #   - Longer  = Shutdown Display
              #   - Shorter = Keep looping
              #-------------------------------------------------------------------------
      
              # Check if joystick active
              # 0   = Joystick input detected, user active
              # 1   = Joystick device not available
              # 124 = No input received during inputWindow
              inputAcive=$(timeout ${inputWindow} dd if=${inputDevice} of=/dev/null count=${inputCount} >/dev/null 2>&1; echo $?)
      
              if [ ${inputAcive} -eq 0 ]; then
                  # Active - Clear idle flag
                  idleFlag=0
              else
                  # Not Active
                  # Skip if already inactive
                  if [ ${idleFlag} -eq 0 ]; then
                      # Start timer
                      SECONDS=0
      
                      # Set to state to inactive
                      idleFlag=1
                  fi
              fi
      
              # Sleep
              sleep ${inputInterval}
      
              # Poweroff display if longer than timeout and idle
              if [ ${SECONDS} -ge ${idleTimeoutS} ] && [ ${idleFlag} -eq 1 ]; then
                  vcgencmd display_power 0
              fi
          else
              #-------------------------------------------------------------------------
              # HDMI Status = OFF
              #-------------------------------------------------------------------------
              # - Query joystick for input
              #   - Block script until input is received
              #   - If device is not valid return and keep checking
              # - If Activity is detected
              #   - Yes = Power on display
              #   - No  = Sleep for a second and repeat
              #-------------------------------------------------------------------------
      
              # Check if joystick active
              # 0   = Joystick input detected, user active
              # 1   = Joystick device not available
              # 124 = No input received during inputWindow
              inputAcive=$(dd if=${inputDevice} of=/dev/null count=${inputCount} >/dev/null 2>&1; echo $?)
      
              if [ ${inputAcive} -eq 0 ]; then
                  vcgencmd display_power 1
              else
                  sleep 1
              fi
          fi
      done;
      
      1 Reply Last reply Reply Quote 3
      • N
        neonlightning
        last edited by

        is there a way to make it so any controller not just a specific one work?

        1 Reply Last reply Reply Quote 0
        • Z
          zzz
          last edited by

          I was able to get this working without the script!

          Like you mentioned, add a new line with "hdmi_blanking=1" to /boot/config.txt.
          You must also add "consoleblank=600" to the existing line (not a new line!) in /boot/cmdline.txt.

          Reboot and your screen should turn off after 600 seconds (10 minutes) of idle time.

          This goes against the recommendation in the RetroPie manual install instructions (here), though I'm not sure why they recommend using consoleblank=0 in the first place.

          Hope this helps!

          C 1 Reply Last reply Reply Quote 2
          • C
            crawsome @zzz
            last edited by

            @zzz

            Thanks for your solution, it's doing most of the job for me, but neither of my joysticks seem to wake the device back up. A keyboard stroke does wake the device though.

            They are cheapo $40 amazon joystick kits, registering as js0/js1. Pi 3b+.

            I tried OP's script, but it appears to not stay off for more than a couple seconds.

            Were you able to find a workaround perhaps?

            1 Reply Last reply Reply Quote 0
            • First post
              Last post

            Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

            Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.