Skip to content

Indicating drive power state on the PR2100's front LEDs

If you've managed to set up HDD spindown on your PR2100, you may want to indicate the power state of the drives on the front LEDs.

Installation

Run sudo wget -O /usr/local/sbin/hdd-led.py https://raw.githubusercontent.com/Mtillmann/mtillmann.blog/master/public/resources/hdd-led.py or copy the script from below and paste it into a file at /usr/local/sbin/hdd-led.py

Run sudo crontab -e and add the following line at the bottom of the file:

* * * * * python3 /usr/local/sbin/hdd-led.py power -d /dev/sda

Add a new -d argument for each drive you want to include in the status, e.g.:

* * * * * python3 /usr/local/sbin/hdd-led.py power -d /dev/sda -d /dev/sdb

Arguments

ArgumentShort FormDefault ValueDescription
---power, usb or reset. first two select LED mode, reset resets the LEDs
disk-d-disk to include in check, can be given multiple times
blink-b-blink on idle - only for mode = power
probemode-phwhich tool to use for state probe: h=hdparm, s=smartctl
debug--print some debug info

Examples

sudo python3 /usr/local/sbin/hdd-led.py power -d /dev/sda Turns the main power LED green if the drive is spun down.

sudo python3 /usr/local/sbin/hdd-led.py power -d /dev/sda -p s Turns the main power LED green if the drive is spun down but uses smartctl instead of hdparm to probe the drive state.

sudo python3 /usr/local/sbin/hdd-led.py power -d /dev/sda -b Turns the main power LED green and blinks it if the drive is spun down.

sudo python3 /usr/local/sbin/hdd-led.py usb -d /dev/sda Turns the USB LED blue if the drive is spun down.

sudo python3 /usr/local/sbin/hdd-led.py reset Resets the LEDs to their default state (Power: steady blue, USB: off).

hdd-led.py

py
import os
import sys
import argparse
from datetime import datetime

parser = argparse.ArgumentParser()
parser.add_argument('mode', help='power, usb or reset')
parser.add_argument('-d','--disk',  action="append", help='disk')
parser.add_argument('-b', '--blink', action='store_true', help='blink on idle - only for mode = power')
parser.add_argument('-p','--probemode', default='h', help='h=hdparm,s=smartctl')
parser.add_argument('--debug', action='store_true', help='print some debug info')

args = parser.parse_args()
disks = args.disk

def debug(line):
  if args.debug:
    print(f"{datetime.now()} - {line}")

for key, value in vars(args).items():
  debug(f"{key}: {value}")

if args.mode != "reset" and len(disks) == 0:
  print("no disks specified")
  sys.exit(1)

if os.geteuid() != 0:
  print("this script needs to be run as root")
  sys.exit(1)

if args.mode == "reset":
  debug("resetting leds")
  cmd = "wdhwc led --power --steady --blue && wdhwc led --power --blink && wdhwc led --usb --steady && wdhwc led --usb --blink"
  debug(f"issuing command: {cmd}")
  os.system(cmd)
  print("LEDs reset")
  sys.exit(0)

active_disk_count = 0

for disk in disks:
  if args.probemode == 'h':
    cmd = f"hdparm -C {disk}"
  else:
    cmd = f"smartctl -i -n standby {disk} | grep -i \"power mode is\""

  debug(f"checking {disk} using command: {cmd}")

  stream = os.popen(cmd)
  cmd_output = stream.read().strip().lower()
  if "active" in cmd_output or "idle" in cmd_output:
    debug(f"{disk} appears to be awake")
    active_disk_count += 1
  else:
    debug(f"{disk} is sleeping")

led_cmd = ''
if args.mode == "power":
  if args.blink:
    if active_disk_count > 0:
      led_cmd = f'wdhwc led --power --steady --blue && wdhwc led --power --blink'
    else:
      led_cmd = f'wdhwc led --power --blink --green && wdhwc led --power --steady'
  else:
    if active_disk_count > 0:
      led_cmd = f'wdhwc led --power --steady --blue && wdhwc led --power --blink'
    else:
      led_cmd = f'wdhwc led --power --steady --green && wdhwc led --power --blink'
else:
  if active_disk_count > 0:
    led_cmd = "wdhwc led --usb --steady"
  else:
    led_cmd = "wdhwc led --usb --steady --blue"

debug(f"{active_disk_count} disks active")
debug(f"issuing command: {led_cmd}")

os.system(led_cmd)

Clicking this button loads third-party content from utteranc.es and github.com