Steam's automatic controller disconnect on idle doesn't work for some controllers, 2 types of Sony Dualshocks in my case. Steam can't even disconnect them with an explicit action, it's not just idle detection that's broken. The Dualshock Edge has a small battery so leaving it running when not in use is particularly bad.
This has two short scripts: one to detect connected Bluetooth controllers and the other to disconnect the Bluetooth connection for all connected controllers. Both these scripts can be used with Waybar, configs for which are also included.
The scripts assume controllers are Bluetooth devices with "controller" in their name.
bluetoothctl- used to enumerate and disconnect controllerszsh- script languagenotify-send- notifications, but it's easy to remove those lines if you don't want pop-ups
Both scripts assume you have zsh installed as /bin/zsh. If you don't, it should be straightforward to translate to the shell or scripting language of your choice. One of the scripts uses associative arrays which are present in basically all modern shells.
This line is probably the most mysterious if you're not familiar with zsh: devices=( ${(f)"$(bluetoothctl devices Connected)"} ). It splits the output of bluetoothctl into a list, one entry per line in the output.
The exit codes and output are for easy use with Waybar. The strings will display when hovering over the icon.
This doesn't need to be used with Waybar. You could do, for e.g., check-connected-contollers.sh && echo "Controllers present!" from anywhere you like.
#!/bin/zsh
#
# Waybar module to display if any bluetooth controllers are connected.
devices=( ${(f)"$(bluetoothctl devices Connected)"} )
count=0
controllers=
for device in "$devices[@]"; do
name=$(echo $device | cut -d ' ' -f3-)
if echo $name | grep -i controller >&/dev/null; then
if [[ -z $controllers ]]; then
controllers=$name
else
controllers="$controllers, $name"
fi
(( count++ ))
fi
done
if [[ -n $controllers ]]; then
echo "Connected: $count ($controllers)"
exit 0
fi
echo "No connected controllers"
exit 1As it says on the tin: disconnects any connected Bluetooth devices with the word "controller" in their name.
To show progress since forced BT disconnects can take a few seconds, the script uses notify-send to pop up notifications. Remove/comment those lines if you don't want these.
This is very much a zsh script, using several extended features from it. Should be easy enough to translate to the shell/language of your choice.
I use this two ways: as a Niri keybinding and as the click action from a Waybar module. You can also run it from a shell prompt. It doesn't assume anything about the environment it's executing in.
Waybar currently seems to have a bug where it exits when some BT devices disconnect. The script works around this by checking if Waybar is running before it disconnects things and restarting Waybar if it's no longer running once the disconnects are done. The problem seemed to be within Waybar's scanning code - though I didn't dig too deep to be honest - so a quick but sufficient workaround is all that's done here.
#!/bin/zsh
#
# Disconnect all BT devices with "controller" in their name.
devices=( ${(f)"$(bluetoothctl devices Connected)"} )
typeset -A disconnects=()
for device in "$devices[@]"; do
mac=$(echo $device | awk '{print $2}')
name=$(echo $device | cut -d ' ' -f3-)
if echo $name | grep -i controller >&/dev/null; then
disconnects[$mac]=$name
else
notify-send "Skipping disconnect: $name"
fi
done
if (( ${#disconnects[@]} > 0 )); then
# waybar can crash on bt disconnects so track & restore if needed
waybar_pid=$(pgrep -x waybar)
for mac name in ${(kv)disconnects}; do
notify_id=$(notify-send -p "⏳️ Disconnecting: $name")
bluetoothctl disconnect $mac >&/dev/null
notify-send -r $notify_id "✅ Disconnected: $name"
done
if [[ -n $waybar_pid ]] && ! pgrep -x waybar >&/dev/null; then
setsid -f uwsm-app -- waybar >&/dev/null
fi
else
notify-send "No controllers to disconnect"
fiTo integrate the above into Waybar, define a custom Waybar module using the detection script to show a controller icon when a connection is detected; set the module's on-click action to be the disconnection script.
I set the detection script to run every 3 minutes here, tweak to your taste.
The Waybar module is defined and used from $HOME/.config/waybar/config.jsonc like any other Waybar configuration.
The gibberish in the center of the "format" value is a Nerd Font icon for a controller. Search for "controller" here to see some options: Nerd Fonts Cheat Sheet. I'm using nf-md-microsoft_xbox_controller or f05ba.
Add it to one of modules-left, modules-center or modules-right as you prefer. I have it show up in the center.
"modules-center": ["clock", "custom/check-bt-controllers"],