Linux startup script to connect to bluetooth and cron to keep it connected

I have a mini Bluetooth keyboard and a Raspberry Pi running a Debian-based distro. I know the MAC address of the keyboard but for this question, let’s just use AA:BB:CC:DD:EE:FF. Right now I have to have a wired keyboard connected as well as my Bluetooth dongle for the mini-keyboard. On the wired keyboard, I have to run the following when the device boots up:

sudo hidd --connect AA:BB:CC:DD:EE:FF

If the device goes idle for too long, then the Bluetooth disconnects and I have to pull out my wired keyboard and retype that same command.

What I’m looking for is a way to have that command run at startup and a way to sense if it gets disconnected so that it will auto reconnect.

The annoying thing is that the keyboard has to be in pairing mode (even though it has already been paired) when I run that command, otherwise it tells me the host is down. So perhaps the script needs to prevent it from disconnecting due to inactivity, otherwise I’ll have to put it back in pairing mode to reconnect.

So to recap:

  • A script to connect at startup. I can make sure to put the keyboard into pairing mode before turning it on.
  • A script to prevent it from disconnecting. Maybe some sort of signal to send to it every 60 seconds or something?

(Replace XX:XX:XX:XX:XX:XX with your device's Bluetooth address)

Install Bluetooth support.

# pacman -S bluez

Create the device configuration file.

# nano /etc/bluetooth/hcid.conf
device XX:XX:XX:XX:XX:XX {
  name "Apple Wireless Keyboard";
  auth enable;
  encrypt enable;
}

Enable bluetooth.

# nano /etc/conf.d/bluetooth
DAEMON_ENABLE="true"
HIDD_ENABLE="true"

Add daemons. Make sure dbus appears first.

# nano /etc/rc.conf
DAEMONS=(… dbus bluetooth)

Reboot.

Test the connection (make sure the keyboard is discoverable or this will fail).

# hidd --connect XX:XX:XX:XX:XX:XX

To enable reconnecting from the keyboard after it has entered sleep mode we create our own daemon which checks to see if the keyboard is connected once per second. If it is, it does nothing that cycle, otherwise it tries to connect to the address specifed in address.

Create the script to run the daemon.

# nano /etc/rc.d/connect-bt-devs
#!/bin/bash
/etc/rc.d/connect-bt-devs.sh &
exit 0

Create the script.

# nano /etc/rc.d/connect-bt-devs.sh

#!/bin/bash
address="XX:XX:XX:XX:XX:XX"
while (sleep 1)
do
  connected=$(hidd --show) > /dev/null
  if [[ ! $connected =~ .*${address}.* ]] ; then
    hidd --connect ${address} > /dev/null 2>&1
  fi
done

Make them executable.

# chmod +x /etc/rc.d/connect-bt-devs
# chmod +x /etc/rc.d/connect-bt-devs.sh

Add daemon.

# nano /etc/rc.conf
DAEMONS=(… connect-bt-devs)

Reboot.

When I first did this, it worked when the script first connects but then I got nasty crash reports on the console whenever the custom daemon tried to reconnect with a re-awakened keyboard. After a bit more investigation it turned out this was because the Belkin dongle was buggy and didn't disconnect from the device when the device powered down. I switched to a no-brand cheapo dongle and it works perfectly.

Combination of information from the arch wiki and Benny Bottema's blog post.