Toggle Bluetooth AppleScript not Working in Yosemite

Updated/Better Answer:

1) This new script doesn't flash.

2) For reasons unbeknownst to man and logic (or just me), applescript sometimes/almost-always fails to Turn Bluetooth Off, if the System Preference window is in the background. Instead of turning off, what actually occurs is that Bluetooth immediately re-enable itself, so the pane is in a fresh state: it's ON, but no connections.

To overcome that, one way to to bring SysPref to the front, as in the original answer. Or, run a loop that click the button again (or for a 3rd time) until Bluetooth is really off. That's why there are two variables and a loop in the script. This should make the script more reliable. statName variable records the original status. Loop will continue clicking the button until status has changes. failSafe makes sure the script will not run forever in case of error. All at the cost of aesthetics of the code.

tell application "System Events"

    tell process "System Preferences"
        activate
    end tell

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

    tell process "System Preferences"

        set statName to name of button 3 of window 1 as string
        set failSafe to 0

        repeat until statName is not name of button 3 of window 1 as string ¬
            or failSafe is 10
            click button 3 of window 1
            set failSafe to failSafe + 1
            delay 0.1
        end repeat

    end tell

    tell application "System Preferences"
        quit
    end tell

end tell

Original Answer:

tell application "System Preferences"
    activate --Change 1/2
    reveal pane "com.apple.preferences.Bluetooth"
end tell
tell application "System Events" to tell process "System Preferences"
    click button 3 of window 1 --Change 2/2
end tell
quit application "System Preferences"

From Accessibility Inspector:

enter image description here

button 3 in the the no.6 item on the list. The 6th button is no.11 in the list. When you call button 6 Preference Window goes Genie. I guess Mavericks had all the buttons bunched up at the front.


I've learned a lot here, I hope this contribution helps someone too! I found using "launch" instead of "activate" will open the app visibly, but not as the foreground window. The other trick, or at least "neat thing I learned recently was possible", is using an empty repeat loop to wait for the window to load (and so the button to exist) instead of a "delay" value, which I also use to verify the change worked before showing a notification. The rest of my code is about retaining System Preference's state if it was open already, or quitting it, otherwise.

    set bundleID to "com.apple.systempreferences"

-- Check for System Preferences running already
tell the application "System Events" to set runningApps to (bundle identifier of every application process)
if bundleID is in runningApps then
    set stayOpen to true
else
    set stayOpen to false
end if

tell application id "com.apple.systempreferences"
    -- Problem with this setting is that the toggle doesn't work if the prefPane is open in the background — the window /must/ be visible
    if not (stayOpen) then launch

    -- If it's already running, save the current prefPane for later
    if (stayOpen) then set prevPane to current pane

    set current pane to pane id "com.apple.preferences.bluetooth"
end tell

tell the application "System Events"
    -- An empty repeat loop to keep checking for the window
    -- Here I am lazy and don't use the identifier
    repeat until window "Bluetooth" of process "System Preferences" exists
    end repeat

    tell window "Bluetooth" of process "System Preferences"
        if button "Turn Bluetooth Off" exists then
            -- Click and wait for it to change, then send a notification
            click button "Turn Bluetooth Off"
            repeat until button "Turn Bluetooth On" exists
            end repeat
            display notification "Bluetooth Off"
        else
            click button "Turn Bluetooth On"
            repeat until button "Turn Bluetooth Off" exists
            end repeat
            display notification "Bluetooth On"
        end if
    end tell

end tell

tell application id "com.apple.systempreferences"
    if (stayOpen) then
        if prevPane is not missing value then set current pane to prevPane
    else if not (stayOpen) then
        quit
    end if
end tell

Simple toggle on or off that does not need to check state first.

property thePane : "com.apple.preferences.bluetooth"

tell application "System Preferences"
    activate
    set the current pane to pane id thePane
    --delay 1
end tell

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

tell application "System Preferences" to quit