Ever since Alex pointed me to Keyboard Maestro, I’ve been thinking up new ways to use it to shave a few seconds – or minutes – off repetitive, mundane tasks. The latest: switching Bluetooth on and off from the keyboard.
(I’m a bit of an edge case: my desk has an external monitor, an external USB keyboard and a Bluetooth trackpad. And when I plug in my laptop, it’s on top of a stand that makes it a pain to use the MacBook’s trackpad to turn on Bluetooth so it will recognize the external trackpad. Yeah, first-world problem… but it’s my first-world problem.)
Keyboard Maestro lets you trigger all sorts of things from the keyboard, but turning Bluetooth on and off isn’t one of them. (There are lots of other utilities to do this, of course. Quicksilver is a popular free one.) My next stop would normally be AppleScript… but it doesn’t seem to be able to throw the switch on Bluetooth, either.
Open-source software to the rescue, in the person of Frederik Seiffert. He has written a dandy little command-line utility called blueutil that can do one of three things, depending on how you type the command: query Bluetooth’s status (on or off), turn it on, or turn it off.
Unfortunately, unless I’m misreading the documentation, Keyboard Maestro isn’t up to the task of issuing Terminal commands and parsing their results. But AppleScript is.
So having installed blueutil, I wrote this little script to toggle Bluetooth on and off:
tell application “Terminal”
do shell script “/usr/local/bin/blueutil status”
set _Result tothe result
if _Result is “Status: on” then
do shell script “/usr/local/bin/blueutil off”
endif
if _Result is “Status: off” then
do shell script “/usr/local/bin/blueutil on”
endif
endtell
I saved the script, and then created a Keyboard Maestro macro using cmd-shift-option-B to execute it. Voila: a keyboard shortcut that turns Bluetooth on and off.
Hi Rob, Keyboard Maestro can do this but because it uses a non-interactive bash it does not know where you look for blueutil so you need to use the full path as you also did in your AppleScript. Here is what I used which also checks if it is installed and prevents you from calling the script again while it is still running:
#!/bin/bash
if [ -f /usr/local/bin/blueutil 2>/dev/null ]; then
status=$(/usr/local/bin/blueutil status)
mv /usr/local/bin/blueutil /usr/local/bin/blueutil.lock
if [ “$status” == “Status: on” ]; then
/usr/local/bin/blueutil.lock off
status=$(/usr/local/bin/blueutil.lock status)
printf “\n Bluetooth $status \n”
else
/usr/local/bin/blueutil.lock on
status=$(/usr/local/bin/blueutil.lock status)
printf “\n Bluetooth $status \n”
fi
else
if [ -f /usr/local/bin/blueutil.lock ]; then
printf ‘\n Blueutil is currently running \n’
exit 1
else
printf ‘\n You need to install blueutil \n’
exit 1
fi
fi
if [ -f /usr/local/bin/blueutil.lock 2>/dev/null ]; then
mv /usr/local/bin/blueutil.lock /usr/local/bin/blueutil
else
exit 1
fi
Marvellous – I’ll look forward to trying this! Thanks!
Hi Rob,
For me I only use bluetooth when travelling (for a personal hotspot) so to save battery and connection prompts I also wanted to turn off wifi when using bluetooth, or vice versa e.g. turn off bluetooth when using a stable office wifi connection.
This may be useful for someone else so I thought I would post it; I took Martin’s script and here is a simple version that also toggles WiFi at the same time:
#!/bin/bash
#Reference http://superuser.com/questions/353928/how-can-i-set-up-a-keyboard-shortcut-to-toggle-the-airport-wifi-card-on-os-x
status=$(/usr/local/bin/blueutil status)
device=”$(networksetup -listallhardwareports |
grep -E ‘(AirPort|Wi-Fi)’ -A 1 | grep -o “en.”)”
if [ “$status” != “Status: on” ]
then
/usr/local/bin/blueutil on
wifi=off
else
/usr/local/bin/blueutil off
wifi=on
fi
networksetup -setairportpower $device $wifi
What would be really cool is if you could somehow connect to a certain bluetooth device via the shell script. I still have to use my trackpad to select the bluetooth menu item and select the device I want to connect to (which is always the same device)
I tried the script based on bluetooth and wifi on KM in Mavericks but apparently the Applescript doesn’t work. Instead, it gives me an error “script error: Expected expression but found unknown token. (-2741)”. Do I have to modify anything? I am not good at scripting at all so help is much appreciated since the script serves my needs perfectly. Blueutil works fine btw.
Hi Rob,
Thanks for this article. It looks great for turning on my bluetooth when I plug in my USB keyboard so my wireless trackpad can connect, however I get the same error as Chris above back in 2013 gets. I have the latest KM. I also tried #!/bin/bash script. My knowledge about scripting is near nothing so I’m suspecting it’s something basic.
I have my USB trigger executing Applescript and then ‘execute text script’ is chosen, with the text just cut and paste into that. Should that work?
Many thanks,
Damian
OK, a little bit of Applescript self-educating and I’ve discovered it.
For the newbs (as I understand it):
applescript needs to be compiled in script editor. All of the inverted commas (“) above need to be retyped so they are not ‘smart’ inverted commas and can be understood by script editor.
There needs to be a space in ‘end if’ and ‘end tell’
I may be misunderstanding basic principles but that’s what got it working for me. Now my bluetooth turns on and off plus connects/disconnects with my trackpad whenever I plug in my USB keyboard. Excellent! Thanks!
I have succes with those to commands used in BetterTouchTool with a keyboard combination cmd+alt+b and blueutil installed:
/usr/local/bin/blueutil on
/usr/local/bin/blueutil off
Sincerely,
Jonas Dalmose
I have succes with those to commands used in BetterTouchTool with a keyboard combination cmd+alt+b to invoke to terminal commands and blueutil installed:
/usr/local/bin/blueutil on
/usr/local/bin/blueutil off
Sincerely,
Jonas Dalmose
If you have homebrew installed, you can “brew install blueutil”. Combine that with Hammerspoon, and you’ve got some fried gold.
Thanks for your work.
Here I can’t get it to work. Only if I keep the lines about turning off or on, without the conditional result.
Is there a change to make in the up posted code?
Any help appreciated.
Christophe.
Sorry to say I haven’t followed AppleScript’s evolution enough in the years since I published this to offer you any guidance here. Any readers have some suggestions for Christophe?