Is This Thing On?

5 minute read

Questioning my hatred of LEDs.

One of the most difficult problems I’ve had with using this machine headless, is knowing whether it’s turned on or not. Seriously.

If I connect the external monitor (ok, not headless in that case), no image on the screen might mean:

  • The Macbook is not turned on
  • The Macbook is asleep
  • There is a problem with the monitor or connection (eg bad cable)

If I try to connect over NoMachine or VNC and fail, that might mean:

  • The Macbook is not turned on
  • The Macbook is asleep
  • The Macbook is not connected to the network
  • NoMachine/VNC is not started on the Macbook
  • I’ve configured something wrongly with NoMachine/VNC

I really dislike the millions of blinking LEDs designers love to stick on electronic devices. They constantly nag or distract, I think they are bad. But I’d kill for one one this Macbook!

Things I’ve tried

I have a small USB-C SD card reader. It has a red LED which lights up when it is receiving power. For a while I used this, but it’s impractical. Although it’s small, it still sticks out to be breakage risk. A nice bit of leverage on the USB port, just waiting to wrench it off if it catches on something (a bit like the 1st-gen Apple Pencil when it was charging).

At some point I noticed that the caps lock button on the keyboard had an LED which lit when caps was locked. And (remembering I’d usually be using a Bluetooth keyboard and pointing device), the caps lock could be applied to the built-in keyboard without affecting the Bluetooth keyboard. I could just leave caps lock on and the LED would stay lit.

The showstopper problem with both of the above ideas was that they both only worked when the Macbook was fully booted and ready to rock. I guess the ports and caps lock LED are powered off at other times. Most of my periods of confusion as to whether it was powered on or not were happening when it was half-on, during boot, sleep, shutdown etc.

My current-best solution

I noticed that my router, in its list of ‘attached clients’ was providing relatively quick/up-to-date information about whether the Macbook was connected or not. It seemed to connect to Wi-Fi quite early in the boot process, and disconnect soon after I initiated a shutdown.

Following on from that, I started pinging the Macbook in a terminal window, which I could keep nearby while I worked. This was getting close enough for my purposes.

The obvious next step was to script it properly. My aim was to get a brief status line telling me if the Macbook was connected or not, and its battery charge level. The following script did the job:

#!/bin/bash

# Ping a Mac on the LAN
# If it's alive, check its battery level using a seperate script `battery-check` (present on the
# Mac)
# Return the result with coloured text to indicate off/on status, and rough battery level
# Loop repeatedly, overwriting the results text each time onto the same single line

ip_to_check=192.168.8.123
hostname=AIR

wht='\033[1;15m'
red='\033[1;31m'
ylw='\033[1;33m'
ong='\033[38;5;208m'
grn='\033[1;32m'
nc='\033[0m' # No Colour

update_battery () {
  # Log in with SSH and call script to get battery charge info.
  battery_check_output=$(ssh AIR "bash --login -c battery-check")

  # `battery-check` returns a string like `battery: 18%`, we want to extract the number.
  percentage=$(echo "${battery_check_output}" | tr -dc '0-9')

  if [[ $percentage -lt 15 ]]; then
    battcolor=$red
  elif [[ $percentage -lt 30 ]]; then
    battcolor=$ong
  elif [[ $percentage -lt 80 ]]; then
    battcolor=$ylw
  else
    battcolor=$grn
  fi 
}

# Hide cursor
tput civis

update_battery
sleep 1
update_battery
sleep 1


i=0
while :
do

  # -c 1 ... count 1 (only ping once)
  if ping -c 1 ${ip_to_check} &> /dev/null; then
    # Temporarily go white to indicate battery has just been checked/updated (2 * 5 = 10secs)
    if [[ $i -lt 2 ]]; then
      color=$wht
    else
      color=$battcolor
    fi

    echo -ne "  ${hostname} ${grn}    ON     ${nc}${color}${percentage}%${nc}\r"

    # i ends up incrementing every 5secs or so
    ((i++))
    
    # Increment and every n counts update battery
    # 5sec * 36 = 180secs = 3mins
    if [[ $i -eq 36 ]]; then
      i=0
      update_battery
    fi
  else
    echo -ne "  ${hostname} ${red}   OFF       ${nc}\r"
  fi

  sleep 5
done

Fromhttps://codeberg.org/mm-dev/shell-scripts/raw/branch/termux-proot-ubuntu/mac-get-status

I already had a little script on the Mac to report the battery level (a very simple wrapper around a Mac built-in system_profiler, just to shorten the output).

#!/bin/sh

percent=$(system_profiler SPPowerDataType | grep "State of Charge (%)" | awk '{print $5}')
echo "battery: ${percent}%"

Then I wanted to be able to float the mac-get-status script in a tiny window.

This next script opens up a terminal in a new window, gives it a specific title macmonitor, and runs mac-get-status:

#!/bin/bash

$TERMINAL --title macmonitor -e "mac-get-status" &

Fromhttps://codeberg.org/mm-dev/shell-scripts/raw/branch/termux-proot-ubuntu/mac-monitor

Then I tell my window manager (DWM) to apply a special rule to windows with that specific title. This is how it’s done in DWM but other window managers may have ways of achieving the same thing.

static const Rule rules[] = {
    // If an Xfce4-terminal window has title 'macmonitor':
    // - Make it float
    // - Make its dimensions 150px x 22px
    {"Xfce4-terminal", NULL, "macmonitor", 0, 1, -1, 0, 0, 150, 22, 1},

    // other rules...
};