Skip to content

Instantly share code, notes, and snippets.

@ralph089
Last active February 17, 2024 09:56
Show Gist options
  • Star 86 You must be signed in to star a gist
  • Fork 20 You must be signed in to fork a gist
  • Save ralph089/a65840c4f5e439b90170d735a89a863f to your computer and use it in GitHub Desktop.
Save ralph089/a65840c4f5e439b90170d735a89a863f to your computer and use it in GitHub Desktop.
Restarts Bluetooth Module on Mac OS X. You can use the script as shortcut to restart Bluetooth on demand or you can use it with "SleepWatcher" to automatically restart Bluetooth on wakeup (See README.md). I created it, because my Logitech Bluetooth Mouse doesn't stay connected after sleep-mode, so i had to manually re-pair my mouse.
#!/bin/bash
#
# Restart Bluetooth Module on Mac OS X
#
# Requires Blueutil to be installed: http://brewformulas.org/blueutil
BT="/usr/local/bin/blueutil"
log() {
echo "$@"
logger -p notice -t bt_restarter "$@"
}
err() {
echo "$@" >&2
logger -p error -t bt_restarter "$@"
}
if [ -f "$BT" ]; then
if [[ $("$BT" -p) == *1 ]];
then
echo "Bluetooth on, restarting ..."
($("$BT" -p 0) &> /dev/null && echo "Bluetooth Module stopped") || (err "Couldn't stop Bluetooth Module" && exit 1)
($("$BT" -p 1) &> /dev/null && echo "Bluetooth Module started") || (err "Couldn't start Bluetooth Module" && exit 1)
log "Successfully restarted Bluetooth" && exit 0
else
echo "Bluetooth is off, nothing to do ..."
fi
else
err "Couldn't find blueutil, please install http://brewformulas.org/blueutil" && exit 1
fi

There is a program called [SleepWatcher] (http://www.bernhard-baehr.de/) that monitors sleep, wakeup and idleness of a Mac. To restart Bluetooth everytime your Mac comes up from sleep, you have to tell SleepWatcher to execute the script from above automatically. Restarting Bluetooth takes approximately 2s, so it doesn't attract negative attention.

The script makes use of BlueUtil, so you have to install it too. (I'm assuming you have HomeBrew installed)

brew install sleepwatcher
brew install blueutil

To make use of SleepWatcher, you have to put the gist to ~/.wakeup (For more information about sleepwatcher open terminal and insert: man sleepwatcher)

After you put your script to ~/.wakeup do the following:

chmod +x ~/.wakeup

Now you can test the script. Add the following command to your terminal:

/usr/local/sbin/sleepwatcher --verbose -w ~/.wakeup

Now you have to enter sleep mode and wakeup your Mac again. After that, you should see the following console output:

Bluetooth on, restarting ...
Bluetooth Module stopped
Bluetooth Module started
Successfully restarted Bluetooth
sleepwatcher: wakeup: /Users/ralph/.wakeup: 0

If it works, you can set up launchd to start sleepwatcher at login by using brew services.

brew services start sleepwatcher

For debugging purposes you can enter Console App and search for "bt_restarter". Maybe there are some messages indicating a problem.

@flamda
Copy link

flamda commented Jul 15, 2016

Thank you, working perfectly and really helpful!

@ralph089
Copy link
Author

I'm glad I could help.

@RonanDrouglazet
Copy link

thanks thanks thanks ! I was thinking this was coming from my JBL Bluetooth speaker, because for me, a bug like this since at least two OSX version was crazy... but true !

@miemo
Copy link

miemo commented Dec 27, 2017

Thanks, this is a lifesaver! And works even in High Sierra, https://github.com/toy/blueutil seems to be kept well up to date.

@vb-git
Copy link

vb-git commented Mar 6, 2018

in high sierra i had to edit the script and replace 3x "power" with "-p" and then it seemed to work

also, the last part to set up LaunchAgent seems to be able to be replaced with running "brew services start sleepwatcher" once after installing sleepwatcher; it will take care of adding the script to autostart.

@ralph089
Copy link
Author

Thanks vb-git! The author of blueutil changed the argument specification. I also hadn't heard of Homebrew Services yet, but it works very well and it simplifies the installation.

I've edited the script accordingly.

@ingageco
Copy link

ingageco commented Jul 4, 2018

Thank you for this - works like a charm

@coolaj86
Copy link

coolaj86 commented Aug 18, 2018

Error: Could not symlink sbin/sleepwatcher

I got an error and had to do some manual steps to install sleepwatcher. I imagine most people technical enough to use brew and install a script like this will be able to figure that out with asistance, but just in case:

Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink sbin/sleepwatcher
/usr/local/sbin is not writable.

You can try again using:
  brew link sleepwatcher
$ brew link sleepwatcher
Linking /usr/local/Cellar/sleepwatcher/2.2...
Error: Could not symlink sbin/sleepwatcher
/usr/local/sbin is not writable

Solution

sudo mkdir -p /usr/local/sbin
brew link sleepwatcher
sudo chown -R $(whoami):staff /usr/local/sbin/

@coolaj86
Copy link

coolaj86 commented Aug 18, 2018

Pulling out the big guns

/usr/local/bin/blueutil -p 0 alone didn't work for me, I did this:

~/.local/bin/restart-bluetooth:

#!/bin/bash

# Docs I read
# https://gist.github.com/nicolasembleton/afc19940da26716f8e90
# https://gist.github.com/ralph-hm/a65840c4f5e439b90170d735a89a863f
# https://github.com/max-lobur/dotfiles/blob/master/sh/bt.sh

# Things I had to do beforehand
#brew install blueutil
#brew install sleepwatcher
#sudo mkdir -p /usr/local/sbin
#sudo chown -R $(whoami):staff /usr/local/sbin/
#brew link sleepwatcher
#/usr/local/sbin/sleepwatcher --verbose -w ~/.local/bin/restart-bluetooth
#brew services start sleepwatcher

# Stop all the bluetooth stuff
sudo kill -9 $(pgrep bluetoothd)
/usr/local/bin/blueutil -p 0
sudo kextunload -b com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport
sudo kextunload -b com.apple.iokit.IOBluetoothHostControllerUARTTransport
sudo launchctl stop com.apple.blued

# Start enough of the bluetooth stuff
/usr/local/bin/blueutil -p 1
sudo launchctl start com.apple.blued
sudo kextload -b com.apple.iokit.BroadcomBluetoothHostControllerUSBTransport

It's only sometimes that my bluetooth doesn't reconnect after sleep & wake (may be related to docking to my Thunderbolt Display) and I don't know how to immediately cause the problem, so I don't know what about that process is required. Obviously some of it is superfluous, but if I run that script my bluetooth dies and comes right back, so I know it's working well enough.

If someone can pare it down to just what's necessary I'd love to hear the explanation (ping me @coolaj86).

@danielharada
Copy link

/usr/local/bin/blueutil -p 0 was also insufficient for me on Sierra 10.12.6, so I walked through solderjs's steps. The kextunload calls failed for me, but the following seemed to be sufficient in my case:

/usr/local/bin/blueutil -p 0
sudo launchctl stop com.apple.blued
/usr/local/bin/blueutil -p 1

@masterslovar
Copy link

Sorry if the question is too stupid but what does this mean -"To make use of SleepWatcher, you have to put the gist to ~/.wakeup"
I dont know how to do this, please help!

@ralph089
Copy link
Author

ralph089 commented Apr 13, 2023

@masterslovar: You can do this for example using vscode or nano using the Terminal.app. Create the file using nano by executing the following command:

nano ~/.wakeup

paste the script from above and press CTRL + O to save the file and then CTRL + X to exit nano.

@JoeOIVOV
Copy link

JoeOIVOV commented Apr 21, 2023

On Ventura 13.3.1 and encountering small issue:

administrator@Mac-Pro ~ % /usr/local/sbin/sleepwatcher --verbose -w ~/.wakeup
Bluetooth on, restarting ...
Failed to switch bluetooth power off in 10 seconds
Couldn't stop Bluetooth Module
Bluetooth Module
started
Successfully restarted Bluetooth
sleepwatcher: wakeup: /Users/administrator/.wakeup: 0

It works nicely... but, it has about a 10 sec wait time after waking until the bluetooth starts working. Would be nice to iron that out if at all possible.

I tried editing the first part of the command in the .\wakeup script out:
($("$BT" -p 0) &> /dev/null && echo "Bluetooth Module stopped") || (err "Couldn't stop Bluetooth Module" && exit 1)
, so that it didn't try to turn Bluetooth off, skipping that failure and 10 sec wait, but Bluetooth didn't work after waking it up.
So even though theres that failure in the verbose output, seems to function with the 10 second delay.

Any ideas to speed it up?

Thank you!!

@ralph089
Copy link
Author

@JoeOIVOV there is a similar issue on Ventura here toy/blueutil#78

Not sure if the reporter found a solution, but you could try to ask.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment