A better AirPod Connection Widget: less space for the same information

This script is a remix of the script found in the AquaTouch Preset by @yuuiko and the Beautiful Airpods Battery Status by @rjayone.
Tap it to connect your AirPods! 5 Seconds later the battery of your connected AirPods will be shown - and here is the new thing, in two lines. Less space used, more information shown.

Before you connect

After connection

Just tap the widget again to disconnect :man_shrugging:t2:

Note Make sure you change AIRPODS_NAME_HERE in both scripts to your AirPods name (twice in the script itself, once in the Predefined action).

Find the JSON attached (just the AirPods widget, I did not include the rest of my Setup in order not to spam you with useless triggers :see_no_evil:), as well as the script below.

Have a great day everyone :clap:t3::smiley::+1:t3:

Caliguvara.bttpreset (1.5 MB)

Script

return checkStatus()

on checkStatus()

--set myString to button returned of (display dialog "Connected?" buttons {"Yes", "No"})
--set myString to "name: DR-BT101 Connected: " & myString

(uncomment line below when done testing)
set myString to do shell script "system_profiler SPBluetoothDataType"

--initial check if it's not even there
if myString does not contain "AIRPODS_NAME_HERE" then
return false
else

  --find out if connected/disconnected
  set AppleScript's text item delimiters to "name:"
  set myList to the text items of myString --each item of mylist is now one of the devices
  
  set numberOfDevices to count of myList
  set counter to 1
  repeat numberOfDevices times --loop through each devices checking for Connected string
  	if item counter of myList contains "AIRPODS_NAME_HERE" then
  		if item counter of myList contains "Connected: Yes" then
  			return checkBattery()
  		else if item counter of myList contains "Connected: No" then
  			return " "
  		else
  			display dialog "Error Parsing" --this shouldn't happen
  		end if
  	end if
  	set counter to counter + 1
  end repeat

end if
end checkStatus

on checkBattery()
set OUTPUT1 to do shell script "
OUTPUT1='';
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" "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}" ]] &&
OUTPUT1="${OUTPUT}$(awk '/BatteryPercent/{print substr($0)}'<<<"${I}")${!I}%";
done;
printf "%s" "${OUTPUT1}";
fi"

set OUTPUT2 to do shell script "
OUTPUT2='';
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" "BatteryPercentLeft");

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}" ]] &&
OUTPUT2="${OUTPUT}$(awk '/BatteryPercent/{print substr($0)}'<<<"${I}")${!I}%";
done;
printf "%s" "${OUTPUT2}";
fi"

return "L:" & OUTPUT1 & "
" & "R:" & OUTPUT2
end checkBattery

Already retouched it.
Worked on the Icons, much better now in my eyes!
AIRPODS
The small AirPods disappear when disconnected and the big pair turns just in the white outlines.
Caliguvara v1.1.bttpreset (44.1 KB)

(How do I export just one JSON file? In order not to export a whole new preset every time.)

1 Like

I changed the "Name_Here" int eh script and the action total of 3 locations. I see it saying blocked in BTT and then when I run the action it says false. Also says false on the touch bar next to the icon

Hum this is strange. When you compile/check the script, what happens?

EDIT: My bad - in the first script, you had to change "AIRPODS_NAME_HERE" to your AirPod's name (for example "Caliguvara's AirPods".
In the v1.1 I put "Name-Here".
Anyhow, for example if you AirPods are called "AirBeat" the final result should look like this:

Great you got this working!
May I merge to AquaTouch?

Also, right click the widget and select copy JSON to clipboard to export just the widget, or make a new preset with just that one widget in it.

1 Like

Working on improvements

  • If the airpods are not found / intitial connection, it will ask for the name of the airpods in a dialog box on-screen
  • visual improvements, such as layout adjustments and more pixel-perfect icons

Currently it looks like:
47%20pm

I have yet to implement point 1 fully.

@GoldenChaos

1 Like

Sure! If I'm sharing this it's not for keeping it afterwards! :wink:

Can I download this AirPods preset?

@idhun90
Work in progress! It's not complete as of yet.

@Caliguvara, @GoldenChaos,

I need some help with the new widget! (I don't have AirPods too).
I've done a heap but I need help with a few things. It's not ready to release yet but it's quickly getting there.

Visit the development thread:

Anyone who is snooping by, I don't recommend you download and use this developmental build as of yet. It is too unstable.

2 Likes

I will totally check this up! I have my exam session this week, but when I have time I'll sneak an eye into it!

1 Like

Hi, BetterTouchTool newbie here.
I'm also not experienced with AppleScripts, but I did encounter a minor "edge-case" that made using this widget a little difficult and wanted to share my experience if it's of any help!

In the v1.1 .bttpreset, we're required to change AIRPODS_NAME_HERE twice: wouldn't a variable be better? I included a small variable to make the user's life easier:
set airPodsName to "AIRPODS_NAME_HERE"
in line 10. Although ideally the popup widget yyuuiko implemented is best, or even better, rather than arbitrarily typing in a name, providing a dropdown of current options and saving that may be better (I can still make typoes haha).

The important point: AppleScripts seems to be really awkward with escaping single quotes. My AirPods are named:
Otanan's AirPods
and figuring out why I kept getting false and how to escape properly was annoying. I noticed that it still works if I include only part of the name without the single quotes, although this isn't ideal and is more of a hotfix and there are still some issues, but having something like a popup that handled that kind of string parsing or even better a dropdown would avoid this issue in the future.

I love the widget! Thank you!

For sure, changing the AirPods' Name with the Apple Script would do the work, but it's more to the script to adjust to the AirPods, not the other way round :wink:
@yuuiko has a great idea with the pop up at first connection, especially for "lambda users" who just want/need a working preset.
Idk, I didn't test it with the single quotes, but as long as both of the quotation marks are there (before and after Otanan's AirPods) this shouldn't cause any trouble.


Just pay attention to do the same in the predefined action script (lower right).
It's a pleasure to hear that the widget pleases you! There were several of them already here before, but as they displayed the battery as a line I preferred to condensate it a little bit. My Touch Bar tends to be full with my preset…

By the way, I found a little bug. I connected my Beats 3 yesterday, and the AirPods' Script gave me the battery level of them. Nice, but my OCD wasn't fine with it :smiley:
Could someone test if this happens with any bluetooth headphone, or just with devices with a W1 Chip? This could be helpful, thanks!

@otanan, @Caliguvara

I’d think a single quote would work fine though i can see the possibility of it not working

You can escape characters with a backslash e.g. Otonan\’s AirPods.

The script’s condition is also an “if contains”, so that’s why only typing in the name partially should work.

——

Regarding the new UI setup:
A dropdown is not native to applescript dialog boxes so creating one is waay out of my league, and also I’m not sure how that would work while not connected.. I’d need airpods myself to code for that too, right now I don’t have any W1 accessories so It would be hard to code for it.

Also thanks for bringing up the case of illegal characters! I’d need to implelent some sort of rejection or auto-escape into the UI setup now I guess.

——

@Caliguvara
My preset had a beats widget from @GoldenChaos, I never saw the code for it but maybe it could be similar and all it takes to work is just changing the reference name..

Edit: ah on second read I see your bug, its displaying what it’s not meant to right? I’m not sure how I can find the issue out since I don’t have these ‘phones, but maybe take a look again at my or GoldenChaoses beats and airpods widgets and see how they differentiate themselves

Hi @everyone, I've just uploaded improvements and fixes to my take of the AirPods widget.
It has:

  • Improved, Neater Aesthetics
  • Super Sharp and Crispy Sub-Pixel aligned icon!
  • Automatic, No-Code setup
  • Error Detection that lets you reset the name if it can't find your AirPods.
  • And of course, the two line battery display for L and R AirPods

I think it's pretty ready to head out properly, but since I don't have AirPods I'd like anyone to test it and give me some feedback over at the post below.

Download development build d1.1 there and tell me how it behaves! (and what you think, too.)

Hi,

This action is very nice! it works perfectly for me except for the alternate icon... I can't make it working...

The result when not connect is "\n" ("+new line+") but when I write that regex expression it does not works.. And obviously it does not works with an empty feild as well!

Does anybody have it working?

Which Version did you load?

I used the Caliguvara v1.1.bttpreset

Hm, it works for me here.
Try to paste this script and replace the YOUR_AIRPODS_NAMR_HERE with your AirPods name (twice).

Script
return checkStatus()

on checkStatus()
	
	--set myString to button returned of (display dialog "Connected?" buttons {"Yes", "No"})
	--set myString to "name: DR-BT101 Connected: " & myString
	
	(*uncomment line below when done testing*)
	set myString to do shell script "system_profiler SPBluetoothDataType"
	
	--initial check if it's not even there
	if myString does not contain "YOUR_AIRPODS_NAME_HERE" then
		return false
	else
		
		--find out if connected/disconnected
		set AppleScript's text item delimiters to "name:"
		set myList to the text items of myString --each item of mylist is now one of the devices
		
		set numberOfDevices to count of myList
		set counter to 1
		repeat numberOfDevices times --loop through each devices checking for Connected string
			if item counter of myList contains "YOUR_AIRPODS_NAME_HERE" then
				if item counter of myList contains "Connected: Yes" then
					return checkBattery()
				else if item counter of myList contains "Connected: No" then
					return " "
				else
					display dialog "Error Parsing" --this shouldn't happen
				end if
			end if
			set counter to counter + 1
		end repeat
	end if
end checkStatus

on checkBattery()
	set OUTPUT1 to do shell script "
OUTPUT1='';
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\" \"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}\" ]] && 
   OUTPUT1=\"${OUTPUT}$(awk '/BatteryPercent/{print substr($0)}'<<<\"${I}\")${!I}%\";
    done;
    printf \"%s\" \"${OUTPUT1}\";
fi"
	
	set OUTPUT2 to do shell script "
OUTPUT2='';
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\" \"BatteryPercentLeft\"); 

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}\" ]] && 
   OUTPUT2=\"${OUTPUT}$(awk '/BatteryPercent/{print substr($0)}'<<<\"${I}\")${!I}%\";
    done;
    printf \"%s\" \"${OUTPUT2}\";
fi"
	
	return OUTPUT2 & "
" & OUTPUT1
end checkBattery

The output for the alternative icon should be space (" ").
If it still doesn't work, could you just copy the JSON of the file to your clipboard (right click on the widget) and send it to me in a private message? So I can take a look into it.

In two or three weeks (just let me pass my exams plz xD) you will also find and update of my Caliguvara C2 Preset, with a way better version of that widget done in collaboration with @yuuiko.
It will also be kinda integrated into an all new AirPlay widget I just finished, more to come with the Update to C3, I don't want to spoil anything :wink: