Using AppleScript to Connect to Bluetooth Headset

2 minute read

Updated:

I learned how to use AppleScript to write a macro that would connect to a bluetooth headset (airpods). AppleScript is a scripting language for MacOS that can be used to automate UI things. I’m using it to click through menu items for me automatically.

General Design

Scripts can be written in applescript or javascript. I found applescript to be easy enough to grok and pick up, given enough examples.

OSX menus are designed in a tree hierarchy. You can navigate down the tree specifying menu items by index, title, or with a filter.

Method Example
Index menu item 1
Title menu item “Foo’s AirPods”
Filter menu item whose title “Foo’s Airpods”

Note: these use “curly quotes”, not regular apostrophes. What are curly quotes? I won’t get into it here but snobby typographers decided to complicate things, instead of letting computers do all the smarts. Why apple chose to use it here, as the identifier for device is beyond me.

Edit: I got around to writing a post about smart quotes.

OS Menulet

tell application "System Events" to tell process "ControlCenter"
    -- Click the Control Center icon in menu bar
    click menu bar item "control center" of menu bar 1

    -- Control popdown
    tell checkbox "bluetooth" of group 1 of group 1 of window "Control Center"
        -- Checkbox's primary action is toggling, we want to get the full menu
        perform action 2
        delay 0.8
    end tell

    -- Bluetooth menu
    tell group 1 of group 1 of window "Control Center"
        tell (checkbox 1 whose name starts with "Foo’s AirPods")
            set disconnected to (value = 0)
            if disconnected then
                click
            end if
        end tell
    end tell

    -- Close out control center
    click menu bar item "control center" of menu bar 1
    click menu bar item "control center" of menu bar 1
end tell

Third-Party Menus

The menu bar at the top consists of OS and third-party menu items. OS menu bar items belong to SystemUIServer process. Items such as bluetooth, battery, volume, etc.

Third-party menu items are accessed through their respective processes, as menu bar 2. menu bar 1 is the main menu bar when the application is active: file, window, format, help.

tell application "System Events" to tell process "Alfred 3"
    set alfredMenu to menu bar item 1 of menu bar 2
    tell alfredMenu
        click
        set toggle to menu item "Preferences..." of menu 1
        click toggle
    end tell
end tell

Gotchas

From my observations, most applications’ menu bar 2 will only have a single menu bar item, the icon. The other gotcha I discovered was that the menu items for third-party apps are lazy loaded, unlike OS menu items. This means you need to click the menu bar and wait for SystemUIServer to refresh. Only then can you access the menu items of sub-menus.