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:
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