Trigger HUD via AppleScript

Is there a way to trigger a HUD via AppleScript or shell script?

Intent:

AppleScript gets current battery of AirPods via bluetooth menu bar and displays it in a HUD.

(I know there are some presets here in the community for showing this on the touchbar, and I may end up using this, but I'd also like to give the HUD a try.)

Attempts:

I tried using the custom url scheme to trigger a BTT predefined action (see below), but either my json was incorrect (very possible, given the double-escaping necessary), or there was some kind of bug with this particular btt://trigger-action/. The sample in the docs worked fine.

set hudShellScript to "open \"btt://trigger_action/?json={\\\"BTTPredefinedActionType\\\" : 254, \\\"BTTPredefinedActionName\\\" : \\\"Show HUD Overlay\\\", \\\"BTTHUDActionConfiguration\\\" : \\\"{\\\"BTTActionHUDDetail\\\":\\\"some text\\\",\\\"BTTActionHUDTitle\\\":\\\"HUD via applescript\\\",\\\"BTTActionHUDDuration\\\":0.90000000000000002,\\\"BTTActionHUDBackground\\\":\\\"34.582522, 49.511016, 186.141509, 255.000000\\\",\\\"BTTActionHUDSlideDirection\\\":2}\\\"}\""
do shell script hudShellScript

This custom url scheme method would suffice if I could get it to work, but if there was a more direct way to trigger a HUD using variables/parameters, that would be great! I've also found this app for controlling an HUD. This could likely be used to get to the same goal, but is not nearly as straightforward.

@Andreas_Hegenberg, does BTT trigger HUDs though AppleScript or shell script or via BezelUI or another API, of sorts?

Thanks!

For full flexibility I'd recommend to do it like this ( using Java Script for automation gets rid of the escaping stuff, but it will also work with normal Apple Script if everything is escaped properly)

var BetterTouchTool = Application('BetterTouchTool');

var hudDescription = {
  "BTTActionHUDDetail": "hud detail text",
  "BTTActionHUDTitle": "hud title",
  "BTTActionHUDDuration": "0.7",
  "BTTActionHUDBackground": "38.719535, 38.720697, 38.720067, 213.662109",
  "BTTActionHUDSlideDirection": 0
};

var actionDefinition =  {
    "BTTPredefinedActionType" : 254,
    "BTTHUDActionConfiguration" : JSON.stringify(hudDescription)

  }

BetterTouchTool.trigger_action(JSON.stringify(actionDefinition));

If you are using normal apple script you can use this, although I agree that the double escaping is super ugly, maybe I can get rid of that in the future :slight_smile:

tell application "BetterTouchTool"
	
	trigger_action "{\"BTTPredefinedActionType\": 254, \"BTTHUDActionConfiguration\": \"{\\\"BTTActionHUDDetail\\\":\\\"hud detail text\\\",\\\"BTTActionHUDTitle\\\":\\\"hud title\\\",\\\"BTTActionHUDDuration\\\":\\\"0.7\\\",\\\"BTTActionHUDBackground\\\":\\\"38.719535, 38.720697, 38.720067, 213.662109\\\",\\\"BTTActionHUDSlideDirection\\\":0}\"}"
	
end tell
1 Like

Ah, the direct AppleScript method is cleaner, especially going the javascript route. Oddly enough, even though I write in javascript all day, when it comes time for these scripts, I stay with AppleScript. Probably wouldn't take much to get used to the js, but now that I'm fairly familiar with AppleScript, I want to keep improving there :slight_smile:

Thanks for the help!

yeah the java script for automation is super buggy and apple has basically abandoned it. So totally reasonable to stick with normal Apple Script.

1 Like

Oh, that's good to know; I feel better about sticking to AppleScript now :slight_smile:

@Andreas_Hegenberg, is there a way to put a line break in BTTActionHUDDetail? I tried \n and \r.

Here's the current version. I may post this more officially in the presets section eventually, but here it is for thread context.

tell application "System Events" to tell process "SystemUIServer"
	set bt to (first menu bar item whose description is "bluetooth") of menu bar 1
	click bt
	tell (first menu item whose title contains "AirPods") of menu of bt
		click
		tell menu 1
			if exists menu item "Connect" then
				click menu item "Connect"
				return
			else
				# assumed already connected
				set leftBattery to name of menu item 3
				set rightBattery to name of menu item 4
				
				# esc to get out of the menu bar
				key code 53
			end if
		end tell
	end tell
end tell


# modify variables (find/replace)
set rightBattery to findAndReplaceInText(item 1 of rightBattery, "Right Battery Level", "R")
set leftBattery to findAndReplaceInText(item 1 of leftBattery, "Left Battery Level", "L")

tell application "BetterTouchTool"
	trigger_action "{\"BTTPredefinedActionType\": 254, \"BTTHUDActionConfiguration\": \"{\\\"BTTActionHUDDetail\\\":\\\"" & leftBattery & " | " & rightBattery & "\\\",\\\"BTTActionHUDTitle\\\":\\\"🔋\\\",\\\"BTTActionHUDDuration\\\":\\\"1.2\\\",\\\"BTTActionHUDBackground\\\":\\\"38.719535, 38.720697, 38.720067, 213.662109\\\",\\\"BTTActionHUDSlideDirection\\\":2}\"}"
end tell




on findAndReplaceInText(theText, theSearchString, theReplacementString)
	set AppleScript's text item delimiters to theSearchString
	set theTextItems to every text item of theText
	set AppleScript's text item delimiters to theReplacementString
	set theText to theTextItems as string
	set AppleScript's text item delimiters to ""
	return theText
end findAndReplaceInText