Compact AirPods widget with User-Friendly Setup

@K2DesignLab, @Noon_Chen

If you could post an isolated preset with your presets widgets I can put them for download up the top page.

Who has the best one tho? :wink:
Is it possible to make the icon automatically change for the different types? Again, I don't own AirPods of any kind so it's a little hard for me to test this stuff.

Do you mean upload .bttpreset file?

As for automatically change airpods icon based on the model, it's possible!!

There is a key-value pair in com.apple.Bluetooth.plist called ProductID, which uniquely identifies the product. The screenshot below shows all the information you can get, VendorID and ProductID uniquely determines a product, in my case, 76 stands for Apple, and 8206 stands for AirPods Pro.

Below shows an example code, you can do all the artwork or optimizations.

use framework "IOBluetooth"
use scripting additions

set deviceList to current application's IOBluetoothDevice's pairedDevices()
set devNames to (deviceList's valueForKey:"name") as list
set devStatus to (deviceList's valueForKey:"connected") as list
set devAddress to (deviceList's valueForKey:"addressString") as list

--Add AirPods base64 iconData here, add new line if newer model is released.
set airpods_iconData to "emmm"
set airpods_pro_iconData to "emmm_pro"

--Set default icon and battery info to make the code more tidy
set batteryText to formatValue("0", "πŸ…›") & "
" & formatValue("0", "πŸ…‘")
set currentModelIcon to airpods_iconData

tell application "BetterTouchTool" to set AirPodsName to get_string_variable "AirPodsWg_DevceName"

if devNames contains AirPodsName then
	--Device is found
	repeat with i from 1 to count devNames
		if (item i of devNames) = AirPodsName then
			--Get index of AirPods in the list and save connection status and MAC address value
			set connectValue to item i of devStatus
			set MAC_addr to item i of devAddress
			
			if connectValue = 1 then
				--Connected, update battery info using built-in tool "PlistBuddy"
				set BatteryLeft to do shell script "/usr/libexec/PlistBuddy -c \"print :DeviceCache:" & MAC_addr & ":BatteryPercentLeft\" /Library/Preferences/com.apple.Bluetooth.plist"
				set BatteryRight to do shell script "/usr/libexec/PlistBuddy -c \"print :DeviceCache:" & MAC_addr & ":BatteryPercentRight\" /Library/Preferences/com.apple.Bluetooth.plist"
				set ProductID to do shell script "/usr/libexec/PlistBuddy -c \"print :DeviceCache:" & MAC_addr & ":ProductID\" /Library/Preferences/com.apple.Bluetooth.plist"
				
				set batteryText to formatValue(BatteryLeft, "πŸ…›") & "
" & formatValue(BatteryRight, "πŸ…‘")
				
				--set corresponding icon based on product id, I ignored vendorID for simplicity
				if ProductID = "8206" then
					--AirPods Pro
					set currentModelIcon to airpods_pro_iconData
					--else if ProductID = "xxxx" then --Add product ID of new model here
					--set currentModelIcon to newModel_iconData
				else
					--Default model: AirPods
					set currentModelIcon to airpods_iconData
				end if
			end if
			
			--return to break repeat loop
			return jsonData(currentModelIcon, batteryText)
		end if
	end repeat
else
	--Device not found, return default data
	return jsonData(currentModelIcon, batteryText)
end if

--Adding utf icon and % character
on formatValue(BatteryLevel, prefix)
	if BatteryLevel = "0" then
		--If one of AirPods is in the case, battery would be 0
		return prefix & "NC"
	else
		return prefix & BatteryLevel & "%"
	end if
end formatValue

--Format into json data that BTT can recognize
on jsonData(icon, batteryInfo)
	return "{\"text\":\"" & batteryInfo & "\", \"icon_data\": \"" & icon & "\", \"background_color\": \"47,55,65,255\"}"
end jsonData

For the battery of the case, you can actually get the data from that plist, but it is only available when you open the case and it became 0 if the case is closed. My thought is to create another button to display the case battery, and we must update the case battery manually by long-press or whatever.
@K2DesignLab Can you share your thoughts?

Would be great if you two could get some .bttpreset up! :smiley:

Is there a download for this widget for general users, or is it still currently under development?

There is a download up top but I'm not sure how well it works on catalina. @K2DesignLab and @Noon_Chen seem to have something new cooking though.

Maybe this one. I encountered some trouble though depending on the AirPods used (1st, 2nd Gen / AirPods Pro). What are you interested in?

I use AirPods 1. I tried installing the files, and when I press the button it will help me toggle between connect/disconnect AirPods, however, it does not display the battery of each AirPod. So it only half works.

Did you install the trigger too? You might have to hold the widget once to set it up.

Yes, all installed. Held the button and copied + pasted AirPods name in, yet it still doesn't show battery. It does connect and disconnect when I press the button though

Sorry to interrupt, would you please do me a favor? I just want to check the ProductID of AirPods 1.

It's very simple, run defaults read /Library/Preferences/com.apple.Bluetooth in the Terminal, then press ⌘+F to search ProductID = 8194, see if there are any matches?

Yupp, there is a match @Noon_Chen :+1:t4:

What does the script return?

@Caliguvara Thanks! Now I can confirm the ProductID is related to the model of AirPods:
8206 stands for AirPods Pro
8207 stands for AirPods 2
8194 stands for AirPods 1.

@yuuiko AirPods Battery_auto icon.bttpreset (30.3 KB)
Here is my preset that can automatically change the icon based on the model and connection status. I only test with my airpods pro, it works, but I need other airpods users to help me test it.

(really need some sleep now...

2 Likes

I had same issue, renamed my airpods to remove all spaces and then it worked

ie: AirPod Pros > AirPod_Pros

Nothing. When the button is pressed, all that will happen is it will connect or disconnect from my airpods. When the airpods are connected, no battery level is displayed.

@Ryan_Mak You can copy the code in the widget and paste it into Script Editor (a mac built-in app), run the code to see if there's any error.

My guess is that the name of your airpods is not correct, because that's the reason why it didn't work for me at the 1st time :-/ Be ware of two different apostrophes: ' and ’.

Or you can run the following code in script editor to see the name of you airpods that stored in the bluetooth.plist

use framework "IOBluetooth"
use scripting additions

set deviceList to current application's IOBluetoothDevice's pairedDevices()
return (deviceList's valueForKey:"name") as list

Copy the airpods name in the result and try again.

BTW, Would you please to test the code that I uploaded for me?

1 Like

Thanks so much. It works now.

Regarding your AirPods widget, it seems to work (it shows the AirPods original icon)

@Noon_Chen Your preset works great! Just one question though: is it possible to make it so when it is connected or disconnected the icon itself doesn't move? So this would be making the icon be the same size and in the same space (the indicator of connected or not connected is just whether or not the icon is highlighted or not).
Thanks!

@Krieii The button length is changing because of the varied text length, you can check the following option in the Common setting to ensure the icon is not moving around.
image

@Noon_Chen Thanks for the suggestion, but I have tried that already!
Here is my settings:


Here is my touchbar with my AirPods connected:

And here is my touchbar with my AirPods not connected:

As you can see, even with the fixed width, the icon and text moves even with the button size remaining the same.

Thanks,
Krieii