Skip to content

Instantly share code, notes, and snippets.

@Jahhein
Last active January 19, 2024 11:49
Show Gist options
  • Save Jahhein/45b8e8c9c36a0932189a5037f990bcdd to your computer and use it in GitHub Desktop.
Save Jahhein/45b8e8c9c36a0932189a5037f990bcdd to your computer and use it in GitHub Desktop.
Display Apple AirPods battery levels via Terminal

Update: New output icon glyph

You can find information on my terminal configuration here

#!/usr/bin/env bash
# Airpods.sh
# Output connected Airpods battery levels via CLI
AIRPOD_ICON=$'\uF7CC'
BATTERY_INFO=(
"BatteryPercentCombined"
"HeadsetBattery"
"BatteryPercentSingle"
"BatteryPercentCase"
"BatteryPercentLeft"
"BatteryPercentRight"
)
BT_DEFAULTS=$(defaults read /Library/Preferences/com.apple.Bluetooth)
SYS_PROFILE=$(system_profiler SPBluetoothDataType 2>/dev/null)
MAC_ADDR=$(grep -b2 "Minor Type: Headphones"<<<"${SYS_PROFILE}"|awk '/Address/{print $3}')
CONNECTED=$(grep -ia6 "${MAC_ADDR}"<<<"${SYS_PROFILE}"|awk '/Connected: Yes/{print 1}')
BT_DATA=$(grep -ia6 '"'"${MAC_ADDR}"'"'<<<"${BT_DEFAULTS}")
if [[ "${CONNECTED}" ]]; then
for info in "${BATTERY_INFO[@]}"; do
declare -x "${info}"="$(awk -v pat="${info}" '$0~pat{gsub (";",""); print $3 }'<<<"${BT_DATA}")"
[[ ! -z "${!info}" ]] && OUTPUT="${OUTPUT} $(awk '/BatteryPercent/{print substr($0,15)": "}'<<<"${info}")${!info}%"
done
printf "%s\\n" "${AIRPOD_ICON} ${OUTPUT}"
else
printf "%s Not Connected\\n" "${OUTPUT}"
fi
exit 0
@jajajaime
Copy link

Nice! This is the only script I've found that pulls info from AirPods. I'm using it in conjunction with BitBar to display the data on the menu bar.

@Jahhein
Copy link
Author

Jahhein commented May 1, 2020

Nice! This is the only script I've found that pulls info from AirPods. I'm using it in conjunction with BitBar to display the data on the menu bar.

Nice! Happy to see you found use! Definitely share that bitbar file if you wouldn’t mind.

@jajajaime
Copy link

jajajaime commented May 1, 2020

Of course! https://github.com/jajajaime/bitbar-plugins/blob/master/airpods.1m.sh
I removed a couple elements to suit my needs, and removed the else as I don't want anything showing when not connected.
If there was an actual AirPods emoji I would use that, but so is life.
image

@varenc
Copy link

varenc commented Dec 4, 2021

This script is great! And shows me some advanced shell-fu.

Though there's an issue with it when you have multiple pairs of Headphone/AirPods that were at one point paired to your system.

For me, this line returns multiple mac addresses, all of ones previously connected along with the actually connected one:

MAC_ADDR=$(grep -b2 "Minor Type: Headphones"<<<"${SYS_PROFILE}"|awk '/Address/{print $3}')

That means that later when $(awk -v pat="${info}" '$0~pat{gsub (";",""); print $3 }'<<<"${BT_DATA}") is called, it somehow fetches old battery data for every pair of old headphones. And my output ends up looking like this. Only one of those battery values matches my currently in-use airpods, the rest must be old cached battery values...?

My hacky fixes is just to limit the mac_addr fetch to the specific pair of airpods I actually use like this:

MAC_ADDR=$(grep -b2 "Minor Type: Headphones"<<<"${SYS_PROFILE}"|awk '/Address/{print $3}' | grep "<my airpods mac address>")

(I easily lookup the mac address for my airpods using the amazing BluetoothConnector util.)

@varenc
Copy link

varenc commented Dec 4, 2021

Instead of my hacky one-off solution, here's a more generalized solution. Though I'm sure there's a more elegant terser way of doing it.

Just replace the CONNECTED=$(...) line with this:

CONNECTED=""
for m in ${MAC_ADDR} ; do 
  grep -ia6 "${m}"<<<"${SYS_PROFILE}"|awk '/Connected: Yes/{print 1}' | grep 1 && MAC_ADDR="$m" && CONNECTED=1 && break ;
done

That just checks if each mac address is connected, and when it finds a connected one, redefines MAC_ADDR to just the value of the connected pair.

Edit: Put this in a fork available here: https://gist.github.com/varenc/6300183cc2be8a4d4a1dd941eb2f5766

@benthamite
Copy link

Running the script returns "Not connected", although my Airpods Max are connected. Is this no longer working?

@robertochello
Copy link

Running the script returns "Not connected", although my Airpods Max are connected. Is this no longer working?

Same problem with AirPods 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment