AirPods Power In TouchBar

Here’s a fun little project I did to put the AirPods battery level on my MacBook’s Touch Bar. Heads up: This is a not a guide for beginners!
First part is a quick how to, then I’ll go into detail about how each part works.
Bonus points: I had to work out how to get a lot of bluetooth information via the command line, so there’s some nice shell scripts for it too!
TouchBarAirPodsPhoto.jpg

 UPDATE 1 – The script is updated to V1.2 thanks to ankushg and spetkowski. It’s more efficient and works on BeatsX Headphones too!
UPDATE 3 – It works with TextBar to show the status in the menubar if you like too (See Here) 😀
UPDATE 4: You can skip creating a .sh file and paste the code straight into Better Touch Tool. I’ve updated the How To to reflect this.

How To

You’ll need a copy of Better Touch Tool for this, grab it from here.
Note: As of Update 4 of this post, I’ve rewritten this section!! The script will automatically grab the MAC Address of your AirPods, and you can even skip downloading the script and copy/paste in the code 😀
Fire up Better Touch Tool, go to the TouchBar section, click the “+ Widget” button.
Under Select Touch Bar Widget, go to “Run AppleScript and Show Return Value”
In here enter the following:
return do shell script "OUTPUT='🎧'; BLUETOOTH_DEFAULTS=$(defaults read /Library/Preferences/com.apple.Bluetooth); SYSTEM_PROFILER=$(system_profiler SPBluetoothDataType); MAC_ADDR=$(grep -b2 \"Minor Type: Headphones\"<<<\"${SYSTEM_PROFILER}\"|awk '/Address/{print $3}'); CONNECTED=$(grep -ia6 \"${MAC_ADDR}\"<<<\"${SYSTEM_PROFILER}\"|awk '/Connected: Yes/{print 1}'); BLUETOOTH_DATA=$(grep -ia6 '\"'\"${MAC_ADDR}\"'\"'<<<\"${BLUETOOTH_DEFAULTS}\"); BATTERY_LEVELS=(\"BatteryPercentCombined\" \"HeadsetBattery\" \"BatteryPercentSingle\" \"BatteryPercentCase\" \"BatteryPercentLeft\" \"BatteryPercentRight\"); if [[ \"${CONNECTED}\" ]]; then for I in \"${BATTERY_LEVELS[@]}\"; do declare -x \"${I}\"=\"$(awk -v pat=\"${I}\" '$0~pat{gsub (\";\",\"\"); print $3 }'<<<\"${BLUETOOTH_DATA}\")\"; [[ ! -z \"${!I}\" ]] && OUTPUT=\"${OUTPUT} $(awk '/BatteryPercent/{print substr($0,15,1)\": \"}'<<<\"${I}\")${!I}%\"; done; printf \"%s\\n\" \"${OUTPUT}\"; else printf \"%s Not Connected\\n\" \"${OUTPUT}\"; fi" # Version 2.3
Click Compile/Check Syntax, then Run Script to make sure it runs okay. Hit Save and you’re good!

Old How To

Below is the old version, I’m leaving this here if you want to use a .sh file for AirPods Power (for programmers etc, you can use the output to do more fun things)
There’s a little command line script you’ll need.  Click here to download it.
Put the .sh file somewhere nice, I put mine in /Users/duck/Scripts/AirPodsPower.sh
For the rest of this article, wherever you see /Users/duck/Scripts/AirPodsPower.sh, replace it with wherever you put the file.
Open up your favourite text editor (I like Sublime Text), you’ll want to change the line at the top that says: MACADDR to be the MAC address of your AirPods.
EnterMACAddr.png
You can get this by holding option down, clicking on the Bluetooth Icon in your menu bar, then going to your AirPods (when they’re connected).
GetMACAddr.png
Open up a Terminal window and type:
chmod +x /Users/duck/Scripts/AirPodsPower.sh
(Change this to wherever you put the script)
You can test the script by typing:  /Users/duck/Scripts/AirPodsPower.sh
AirPodsTerminalCheck.png
Now, to the Better Touch Tool part of it:
Go to the TouchBar section, click the “+ Widget” button.
Under Select Touch Bar Widget, go to “Run AppleScript and Show Return Value”
In here enter the following:
return do shell script "/Users/duck/Scripts/AirPodsPower.sh"
Click Compile/Check Syntax, then Run Script to make sure it runs okay. Hit Save and you’re good!

Extra Notes

While I was working this out, I worked out a bunch of extra bits that I couldn’t easily google.  These pretty much *only* apply to AirPods in their current form, but can be modified to read all sorts of other bits.
First up, here’s how to see if a Bluetooth device is connected via the command line (Replace $MACADDR with the MAC Address of the device):
system_profiler SPBluetoothDataType | /usr/local/bin/pcregrep -Mi "$MACADDR(\n.*){6}" | grep "Connected: Yes" | sed 's/.*Connected: Yes/1/'
Using system_profiler, you can get the state of a whole bunch of stuff on the system in either XML (using the -xml switch) or indented form. I just run that command showing me all the Bluetooth Devices, grep for the MAC Address of my AirPods, grab the next 6 lines of text (this includes the line saying “Connected: Yes”, then replaces the words “Connected: Yes” with a 1 to make it neater for working with the shell script.
This was built just for AirPods, so for other devices you may need to change the pcregrep bit to check for more/less lines after the MAC address is found.
Secondly, getting the data for the battery levels from a device via Command Line (again, replace $MACADDR with the MAC Address of the device).
BTDATA=`defaults read /Library/Preferences/com.apple.Bluetooth | /usr/local/bin/pcregrep -Mi "\"$MACADDR\".=\s*\{[^\}]*\}"`

CASEBATT=`echo "$BTDATA" | grep BatteryPercentCase | sed 's/.*BatteryPercentCase = //' | sed 's/;//'`
defaults read /Library/Preferences/com.apple.Bluetooth will return all the info about bluetooth in json form, which seems to include every bluetooth device that has farted anywhere near the machine, so the next part will pcregrep for the MAC Address and include everything until the closing tag.
Then the next line grabs just the BatteryPercentCase part.
Also note it’s only really reading a cached value rather than a “live” value. So it’ll be a little bit behind (little bit being like 10-30seconds or so, good enough for what I want to do).
Hopefully this helped you! If you like this article, leave a comment and say hi 🙂

Update 4 – Skipping the .sh file part

In Better Touch Tool, when you get to the step to paste in the AppleScript, paste the following:

return do shell script "OUTPUT='🎧'; BLUETOOTH_DEFAULTS=$(defaults read /Library/Preferences/com.apple.Bluetooth); SYSTEM_PROFILER=$(system_profiler SPBluetoothDataType); MAC_ADDR=$(grep -b2 \"Minor Type: Headphones\"<<<\"${SYSTEM_PROFILER}\"|awk '/Address/{print $3}'); CONNECTED=$(grep -ia6 \"${MAC_ADDR}\"<<<\"${SYSTEM_PROFILER}\"|awk '/Connected: Yes/{print 1}'); BLUETOOTH_DATA=$(grep -ia6 '\"'\"${MAC_ADDR}\"'\"'<<<\"${BLUETOOTH_DEFAULTS}\"); BATTERY_LEVELS=(\"BatteryPercentCombined\" \"HeadsetBattery\" \"BatteryPercentSingle\" \"BatteryPercentCase\" \"BatteryPercentLeft\" \"BatteryPercentRight\"); if [[ \"${CONNECTED}\" ]]; then for I in \"${BATTERY_LEVELS[@]}\"; do declare -x \"${I}\"=\"$(awk -v pat=\"${I}\" '$0~pat{gsub (\";\",\"\"); print $3 }'<<<\"${BLUETOOTH_DATA}\")\"; [[ ! -z \"${!I}\" ]] && OUTPUT=\"${OUTPUT} $(awk '/BatteryPercent/{print substr($0,15,1)\": \"}'<<<\"${I}\")${!I}%\"; done; printf \"%s\\n\" \"${OUTPUT}\"; else printf \"%s Not Connected\\n\" \"${OUTPUT}\"; fi" # Version 2.3

When you’ve pasted that in, press Compile/Check Syntax, then Run Script and make sure it works (I’m not sure if WordPress will mangle the code on me).

Thanks to Danoz for his help with this script!

1 comment

Leave a Reply