user1892304
user1892304

Reputation: 637

AppleScript to toggle Bluetooth

In OS X 10.8 I had a neat little AppleScript that I used to toggle Bluetooth quickly without using the mouse.

I updated to 10.9 which added several UI changes to System Preferences. Among other things it replaced the element that toggles Bluetooth from a checkbox to a button. My script is now broken, and consequently so is my workflow.

The problem is that the button's name changes from "Turn Bluetooth On" to "Turn Bluetooth Off" depending on its status. I don't have a sufficient grasp in AppleScript to figure out a workaround, and was wondering if you guys could help me out.

Upvotes: 9

Views: 10068

Answers (8)

retif
retif

Reputation: 1652

The AlterEgo's answer doesn't work for me on Mac OS 13.5.2, most likely because Apple has (yet again) renamed/reorganized stuff (just love it, always a nice surprise).

As far as I can tell, there are no IDs/labels on those controls anymore, so one just has to rely on controls ordinals (after some trial-and-error to discover the right ones).

I wanted to get exactly AlterEgo's recipe working, because it uses Menu Bar controls, which is less "obstructive" than opening a rather big System Preferences window in the middle of the screen.

So here's my current solution for toggling Bluetooth state via Control Centre:

tell application "System Events"
    tell process "ControlCenter"
        set mbiControlCentre to a reference to first item of (get menu bar items of menu bar 1) whose description is "Control Centre"
        if mbiControlCentre exists then
            click mbiControlCentre
        else
            error "Couldn't find Control Centre on Menu Bar"
        end if

        # no IDs or labels, have to rely on ordinals
        click checkbox 3 of group 1 of window "Control Centre"

        key code 53 -- ESC
    end tell
end tell

Here's also a script that accepts a CLI argument for desired state and takes into account the current state of the toggle.

As a bonus, if one has added Bluetooth icon to the Menu Bar, it can be toggled there as well:

tell application "System Events"
    tell process "ControlCenter"
        # check if user has added Bluetooth to Menu Bar
        set mbiBluetooth to a reference to first item of (get menu bar items of menu bar 1) whose description is "Bluetooth"
        if mbiBluetooth exists then
            click mbiBluetooth
        else
            error "There is no Bluetooth icon on Menu Bar, you need to add it there first"
        end if

        # no IDs or labels, have to rely on ordinals
        click first checkbox of group 1 of window "Control Centre"

        key code 53 -- ESC
    end tell
end tell

And here's a script version for this one too.

Upvotes: 0

Ptujec
Ptujec

Reputation: 1

Here is a GUI script that should work for macOS 12. It is also language independent:

tell application "System Preferences"
    set current pane to pane "com.apple.preferences.Bluetooth"
    delay 0.5
end tell

tell application "System Events"
    tell application process "System Preferences"
        click button 1 of window "Bluetooth"
    end tell
end tell

Upvotes: 0

AlterEgo
AlterEgo

Reputation: 147

AppleScript Solution

Steps

  1. Open Automater.app.
  2. Type Run AppleScript in the search bar and select to open a new script window.
  3. Set Workflow receives to no input in any application in the settings at the top of the screen.
  4. Copy & paste the scripts below and save the file.
  5. Create a keyboard shortcut: System Preferences > Keyboard > Shortcuts > Services > The new script shows under General under the saved name. > Set a shortcut.

macOS Big Sur 11.5

Bluetooth Toggle.workflow

tell application "System Events"
    tell process "ControlCenter"
        set BluetoothButton to menu bar item "Bluetooth" of menu bar 1
        click BluetoothButton
        delay 1
        set OnSwitch to checkbox "Bluetooth" of group 1 of window "Control Center"
        click OnSwitch
    end tell
    key code 53
end tell

See: Setting Bluetooth with AppleScript in Big Sur - r/applescript, 12/1/20

macOS Monterey 12.0.1

Bluetooth Toggle.workflow

tell application "System Events"
    tell application process "Control Center"
        click menu bar item "Bluetooth" of menu bar 1
        tell window "Control Center"
            try
                click checkbox "Bluetooth"
            on error
                click checkbox "Bluetooth"
            end try
        end tell
    end tell
    key code 53 -- # escape key
end tell

See: AppleScript Error - Can’t get group 1 of window "Control Center" - StackExchange, 11/10/21

Third-Party

For macOS Big Sur, Enrique Scherer's answer no longer works. However, the blueutil utility has been updated and can be installed for example from homebrew.

Upvotes: 3

Carlos Diaz
Carlos Diaz

Reputation: 15

Sometimes my Mac drops its connection to my Logitech MX Master 3, necessitating a quick Bluetooth toggle. But I work with my laptop closed so once I toggle Bluetooth off, I lose my input to the computer until I physically open it up

This script solves the problem by turning Bluetooth off, waiting 5 seconds, and turning it back on

When my mouse's connection drops, but I still have keyboard access, I navigate to the directory containing this script, command + down arrow to open it, and command + R to run it. 5 seconds later and my mouse is back!

Toggle Bluetooth.scpt:

display dialog "Toggle Bluetooth?"

-- turn bluetooth off
tell application "System Events" to tell process "SystemUIServer"
    tell (menu bar item 1 of menu bar 1 where description is "bluetooth")
        click
        click menu item "Turn Bluetooth Off" of menu 1
    end tell
end tell

-- wait 5 seconds
delay 5

-- turn bluetooth on
tell application "System Events" to tell process "SystemUIServer"
    tell (menu bar item 1 of menu bar 1 where description is "bluetooth")
        click
        click menu item "Turn Bluetooth On" of menu 1
    end tell
end tell

display dialog "Welcome Back!"

Upvotes: 0

Enrique Scherer
Enrique Scherer

Reputation: 21

This worked for me in 10.15.6, I might have over complicated my solution which is running script 1 (turn bluetooth off) and then script 2 (turn bluetooth on).

Script 1. This is for turning bluetooth OFF

tell application "System Events" to tell process "SystemUIServer"
    tell (menu bar item 1 of menu bar 1 where description is "bluetooth")
        click
        click menu item "Turn Bluetooth Off" of menu 1
    end tell
    tell window 1
        click button "Turn Bluetooth Off"
    end tell
end tell

Script 2. This is for turning bluetooth ON

tell application "System Events" to tell process "SystemUIServer"
    tell (menu bar item 1 of menu bar 1 where description is "bluetooth")
        click
        click menu item "Turn Bluetooth On" of menu 1
    end tell
end tell

So I execute one command which will run one script after the other, the sleep is for the UI to update properly.

osascript bluetooth_off.scpt && sleep 3s && osascript bluetooth_on.scpt

You can just save the command in a file and execute it using: (they have to be in the same directory).

~ bash <fileName>

Upvotes: 2

matt
matt

Reputation: 1

Worked for me, no blue util:

tell application "System Preferences"
    reveal pane id "com.apple.preferences.Bluetooth"
    -- activate

    set the current pane to pane id "com.apple.preferences.Bluetooth"

    try
        tell application "System Events" to tell process "System Preferences"
            click button "Turn Bluetooth Off" of window "Bluetooth"

            click button "Turn Bluetooth Off" of sheet 1 of window "Bluetooth" of application process "System Preferences" of application "System Events"
        end tell

        delay 1

    on error
        tell application "System Events" to tell process "System Preferences"
            click button "Turn Bluetooth On" of window "Bluetooth"
            quit
        end tell

    end try

end tell

Upvotes: 0

AndrewK
AndrewK

Reputation: 79

tell application "System Preferences"
    reveal pane "com.apple.preferences.Bluetooth"
end tell
tell application "System Events" to tell process "System Preferences"
    repeat until exists window "Bluetooth"
    end repeat
    try
        click button "Turn Bluetooth Off" of window "Bluetooth"
        do shell script "networksetup -setairportpower airport off"
    on error
        click button "Turn Bluetooth On" of window "Bluetooth"
        do shell script "networksetup -setairportpower airport on"
    end try
end tell
tell application "System Preferences" to quit

Upvotes: 2

Lri
Lri

Reputation: 27623

This worked for me in 10.9:

tell application "System Preferences"
    reveal pane "com.apple.preferences.Bluetooth"
end tell
tell application "System Events" to tell process "System Preferences"
    click button 6 of window 1
end tell
quit application "System Preferences"

You could also use blueutil:

/usr/local/bin/blueutil|grep -q 'Power: 1';/usr/local/bin/blueutil power $?

Upvotes: 12

Related Questions