Background

I live in PG&E territory, where my current off-peak electricity cost is about $0.48 / kWh. So I occasionally get curious about how much power various appliances and devices are using. Today I decided to check my 2021 M1 Max Macbook Pro. It turns out it’s drawing about 25 watts at idle. But if I dim the screen all the way down, it’s only about 15 watts!

I generally use my Macbook with an external display in mirrored mode, i.e., the external display and the Macbook display show the same thing, but I look at the external display. I just keep the lid open because I like the fingerprint sensor. But I don’t actually need the display to be on.

So that got me thinking. If I keep the screen dimmed all the way down, I could use 40% less energy on my Macbook. Assuming I use this laptop ~8 hours / day, I can save a whopping 29 kWh / year, or about $14! Obviously this is peanuts, but it’s still a fun, quick exercise.

Requirements

The requirements are pretty simple:

  • The laptop should automatically dim the screen when it detects that it’s plugged into an external display.
  • I should be able to manually override this as-needed, i.e., it shouldn’t dim the screen after I’ve overridden it.

Research

I looked through the MacOS settings for like 10 minutes to see if there’s a built-in setting for this. I couldn’t find one.

I Googled around and found out you can use Applescript to simulate pressing the screen brightness buttons. I think I ultimately found this answer most helpful: https://apple.stackexchange.com/a/285907

Then I needed a way to detect whether the Macbook is connected to an external monitor. This answer does the trick: https://stackoverflow.com/a/20115806 It basically just returns some metadata and a list of displays. My monitor is the “DELL P2715Q”:

$ system_profiler SPDisplaysDataType
Graphics/Displays:

    Apple M1 Max:

      Chipset Model: Apple M1 Max
      Type: GPU
      Bus: Built-In
      Total Number of Cores: 24
      Vendor: Apple (0x106b)
      Metal Support: Metal 3
      Displays:
        DELL P2715Q:
          Resolution: 6016 x 3384
          UI Looks like: 3008 x 1692 @ 30.00Hz
          Main Display: Yes
          Mirror: On
          Mirror Status: Master Mirror
          Online: Yes
          Rotation: Supported
        Color LCD:
          Display Type: Built-in Liquid Retina XDR Display
          Resolution: 3456 x 2234 Retina
          Mirror: On
          Mirror Status: Hardware Mirror
          Online: Yes
          Automatically Adjust Brightness: No
          Connection Type: Internal

Solution

With those in hand, I assembled this bash script:

#!/bin/bash
set -e

# Check if my external display is connected.
# For some reason I have to use the full path, else crontab can't find the system_profiler binary.
# If you use this, chane the P2715Q to a string that's part of your display name when you run the system_profiler command.
if /usr/sbin/system_profiler SPDisplaysDataType | grep P2715Q
then
  if [ -f /tmp/brightness ]
  then
    # If the /tmp/brightness file already exists, that means the script has already set the brightness
    # (the file is created below, after setting brightness), so we just leave it as-is.
    # This prevents from reverting the brightness if I override it manually.
    echo "External monitor detected, but /tmp/brightness file already exists, so we're leaving brightness as-is."
  else
    # If the /tmp/brightness file does not exist, that means the script has not yet set the brightness.
    # Set the brightness and create the file.
    echo "External monitor detected, and /tmp/brightness file does not exist, so we're dimming brightness."
    # In theory it should be sufficient to call this once,
    # but for some reason it doesn't seem to actually repeat 16 times,
    # so I wrapped it in another loop for good measure
    for i in {1..5}
    do
      osascript <<SCRIPT
        tell application "System Events"
          repeat 16 times
            key code 145
          end repeat
        end tell
SCRIPT
    done
    touch /tmp/brightness
  fi
else
  echo "No external monitor detected"
  if [ -f /tmp/brightness ]
  then
    # If there's no monitor and the file exists, we delete the file.
    # The next time the script detects a monitor, it will set the brightness.
    echo "Deleting /tmp/brightness file"
    rm -rf /tmp/brightness
  fi
fi

I think the script comments should explain the logic adequately. It’s essentially using system_profiler to detect my monitor, using osascript to adjust the brightness, and using a file /tmp/brightness to signal whether the brightness has already been set.

When I ran it from iTerm, I received and approved a permissions request like this:

MacOS permissions request to run the script from iTerm

Then I configured it to run as a cron, once per minute:

* * * * * /path/to/script.sh > /dev/null

After about a minute, I received and approved another permissions request:

MacOS permissions request to run the script from cron

If I ever need to modify or revoke the permissions, they are stored in System Settings > Privacy and Security > Accessibility:

Permissions in System Settings > Privacy and Security > Accessibility

I added the >/dev/null redirect to the crontab because otherwise MacOS seems to “mail” me the output from stdout. Without the redirect, each time I open iTerm I see a message “You have new mail”. I can view and delete it using the mail program:

Last login: Thu Sep 12 19:26:45 on ttys009
You have new mail.
➜  ~ mail
Mail version 8.1 6/6/93.  Type ? for help.
"/var/mail/alex": 3 messages 3 new
>N  1 [email protected]  Thu Sep 12 19:27  19/719   "Cron <alex@AKMBPRO202"
 N  2 [email protected]  Thu Sep 12 19:28  19/719   "Cron <alex@AKMBPRO202"
 N  3 [email protected]  Thu Sep 12 19:29  19/719   "Cron <alex@AKMBPRO202
> delete *
> q

If you end up seeing this message, that probably means the script is printing to stderr, and you should check why it’s failing.

Conclusion

So now my Macbook automatically dims its screen all the way down when I connect to my external display. When I disconnect, I just turn the brightness back up. I’m saving about 10 watts.

Updated:

Comments