I am able to access the bluetooth LE remote now on my Raspberry Pi Zero thanks to @ukBaz who pointed out how to access the HID over GATT (short HoG in Linux:
Pair the remote using bluetoothctl
This has to happen only once.
First I press and hold 1 and 3 simultaneously to clear any current pairing on the remote. This is specific for my remote model, but it is good to know that resetting a device prior to connecting it might be necessary.
sudo bluetoothctl
power on
agent on
# you might need to do `scan on` / `scan off` until you see the remote
pair AA:BB:CC:DD:EE:FF
# click ok on the remote or otherwise confirm the pairing
trust AA:BB:CC:DD:EE:FF
connect AA:BB:CC:DD:EE:FF # Pairing might perform a connect, but it does not hurt
info # info shows you if you're connected and or paired with the remote
Now reboot the RaspberryPi
Auto-Connect
In bluetoothctl
the prompt shows you if you're connected to the device. After 60 seconds the connection was disconnected. I thought that this was a problem and that the remote would not send commands to the PI now, but it's important to note that once the pairing is established the remote seems to auto-connects to my Raspberry Pi.
HoG in Linux and /dev/input
I first thought that I will need to hook into the GATT protocol stack and detect those GATT messages and events in order to detect the button events of my remote.
This is possible but since BlueZ on the Raspberry Pi supports HID over GATT which namely are Bluetooth Low Energy mice, joysticks, keyboards, game controllers or remote controls. This means that the Kernel on the Pi creates an input device which resides in /dev/input/
. So once I was paired and connected my BLE Remote two new entries did show up in /dev/input
: /dev/input/event1
and /dev/input/event0
.
I made a cat /dev/input/event1
and once I pressed a key on the remote I saw some byte-garbage flying through the terminal. So I could verify that the remote was sending events to the Pi.
Reading events using evdev
Update: The evdev has a module that let's you quickly output events for the device of your choice:
python3 -m evdev.evtest
@ukBaz pointed out that I can use the pip3 package evdev to access my device. And by running the following python code I was able to detect the buttons on my remote ??
Install evdev
and run the python3 console:
pip3 install evdev
python3
Run the python script
import evdev
device = evdev.InputDevice('/dev/input/event1')
print(device)
# device /dev/input/event1, name "Swisscom RC", phys "AA:BB:CC:DD:EE:FF"
for event in device.read_loop():
if event.type == evdev.ecodes.EV_KEY:
print(evdev.categorize(event))
This would output the following:
key event at 1550575506.080840, 2 (KEY_1), down
key event at 1550575506.230643, 2 (KEY_1), up
key event at 1550575506.410622, 3 (KEY_2), down
key event at 1550575506.560618, 3 (KEY_2), up
key event at 1550575506.730621, 4 (KEY_3), down
key event at 1550575506.880608, 4 (KEY_3), up
key event at 1550575507.080630, 5 (KEY_4), down
key event at 1550575507.230630, 5 (KEY_4), up
key event at 1550575507.430884, 6 (KEY_5), down
key event at 1550575507.580611, 6 (KEY_5), up
key event at 1550575507.770633, 7 (KEY_6), down
key event at 1550575507.930623, 7 (KEY_6), up
key event at 1550575514.040805, 104 (KEY_PAGEUP), down
key event at 1550575514.295156, 104 (KEY_PAGEUP), hold
key event at 1550575514.345174, 104 (KEY_PAGEUP), hold
key event at 1550575514.395158, 104 (KEY_PAGEUP), hold
key event at 1550575514.445154, 104 (KEY_PAGEUP), hold
key event at 1550575514.495155, 104 (KEY_PAGEUP), hold
key event at 1550575514.545187, 104 (KEY_PAGEUP), hold
key event at 1550575514.595153, 104 (KEY_PAGEUP), hold
key event at 1550575514.645155, 104 (KEY_PAGEUP), hold
key event at 1550575514.695154, 104 (KEY_PAGEUP), hold
key event at 1550575514.745153, 104 (KEY_PAGEUP), hold
key event at 1550575514.795154, 104 (KEY_PAGEUP), hold
key event at 1550575514.840643, 104 (KEY_PAGEUP), up
key event at 1550575517.290737, 116 (KEY_POWER), down
key event at 1550575517.440740, 116 (KEY_POWER), up
key event at 1550575520.110901, 158 (KEY_BACK), down
key event at 1550575520.230905, 158 (KEY_BACK), up
key event at 1550575658.372344, 113 (['KEY_MIN_INTERESTING', 'KEY_MUTE']), down
key event at 1550575658.375718, 113 (['KEY_MIN_INTERESTING', 'KEY_MUTE']), up
key event at 1550575520.530643, 164 (KEY_PLAYPAUSE), down
key event at 1550575520.680666, 164 (KEY_PLAYPAUSE), up
key event at 1550575520.880818, 167 (KEY_RECORD), down
key event at 1550575521.020807, 167 (KEY_RECORD), up
The event object has a value 0,1,2 which is down up and hold and a code like 104
which can be resolved to the corresponding code KEY_PAGEUP
which on my remote is the change program key.
Please note that the Mute key has some sort of double assignment which you may need to handle differently.
Gotcha #1 - Update Bluez
The bluez package does support HID over GATT and some fixes were made along the way. At some point you would have to add the --experimental
flag to the end of ExecStart
in the bluez service /etc/systemd/system/dbus-org.bluez.service
. However, HID over GATT was at some point added to the Default.
I did update bluez to the latest version which is bluez-5.50
. I did this from source which is not too hard and described here
bluetoothctl -v
5.43
sudo apt-get install libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev -y
wget www.kernel.org/pub/linux/bluetooth/bluez-5.50.tar.xz
tar xvf bluez-5.50.tar.xz
cd cd bluez-5.50/
./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental
make -j4
sudo make install
sudo reboot
bluetoothctl -v
# bluetoothctl: 5.50
Gotcha #2 - Run rpi-update
Just to be sure I did update the raspberry pi to the latest version using rpi-update
. As with all these gotchas, I don't know if they're required, but if in doubt it's ususally a good practise to update your system.