NB: Updated March 2024.
I recently purchased the XDO BT802 from Amazon. It’s on the list of “Known Working Adapters” on the Bluetooth Integration Page. I had some trouble getting this working on my Raspberry Pi 4 running Raspbian 11 / Bullseye with Home Assistant Core, so while I’m not an expert at either Linux or Bluetooth I thought I’d post how I got this working.
Short answer: you need to download the driver, which is two Linux commands which I provide below. For other similar adapters I some hints on how to find appropriate drivers.
Posts below suggest the ZEXMTE Long Range Bluetooth Adapter has the same chipset, and the process below works for it as well.
You may also find my Xiaomi Mijia LYWSD03MMC Tutorial useful.
NB: if you want an easier option (though downloading two files is pretty easy) the Sena UD100-G03 is recommended by Home Assistant and I found it was picked up immediately by the Raspberry Pi with no issues at all. However, the ZEXMTE with the Realtek Bluetooth 5.1 chipset seems to pick up signals more easily than the older Sena adapter with Bluetooth 4. The Sena reports higher signal strengths, but my more distant sensors say “Unknown”. With the ZeXMTE / Realtek the reported signal strengths are lower, but all of my sensors report it more reliably.
Core Problem
The key problem is that Linux requires a “firmware” / aka Driver to get a piece of hardware working. The firmware for this device is not installed in Raspbian by default, so getting it installed is the key. The error message I was getting in the home assistant user interface was
Failed to start Bluetooth: adapter ‘hci0’ not found
The XSO BT802 appears to have a Realtek RTL8761BU chipset. To download the firmware / driver for this chipset ssh into your Raspberry Pi and run the following commands.
cd /lib/firmware/rtl_bt
sudo wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/rtl_bt/rtl8761bu_config.bin
sudo wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/rtl_bt/rtl8761bu_fw.bin
If you have a different model of Realtek chipset you may find it here or here. If they don’t have the “.bin” extension when you download them you’ll have to reload it.
Disable Bluetooth
It’s simple to disable the built in Bluetooth adapter by editing the config file. This doesn’t disable USB bluetooth adapters, as @targettadams pointed out to me.
New distros: sudo nano /boot/firmware/config.txt' Older distros
sudo nano /boot/config.txt`
Add the lines below. The [pi4] section is power saving by turning off LEDs, you can add it, or not. Of course, if you want the Pi4 WiFi to work, don’t disable it.
dtoverlay=disable-wifi
dtoverlay=disable-bt
[pi4]
# Disable the PWR LED
dtparam=pwr_led_trigger=none
dtparam=pwr_led_activelow=off
# Disable the Activity LED
dtparam=act_led_trigger=none
dtparam=act_led_activelow=off
# Disable ethernet port LEDs
dtparam=eth_led0=4
dtparam=eth_led1=4
# Turn off mainboard LEDs
dtoverlay=act-led
If this doesn’t work for, you can try the Appendix “Disabling Bluetooth - Alternate Option”
Finding Chipset / Firmware Required
If you’re not sure which driver you need run the command below and look for messages that contain something like the “not found” message below. This should tell you the chipset model and the file you need to find.
dmesg|egrep -i "blu|hci|bt"
[ 1280.353319] bluetooth hci0: Direct firmware load for rtl_bt/rtl8761bu_fw.bin failed with error -2
[ 1280.353343] Bluetooth: hci0: RTL: firmware file rtl_bt/rtl8761bu_fw.bin not found
Once you’ve copied the correct driver onto your Pi reboot the pi with the "sudo reboot"
command. Run the “dmesg” command from above to verify the firmware has been found and installed.
Install Packages
Installing these OS packages seemed to help reduce error messages in the HA logs.
sudo apt-get install libcap2 libpcap0.8-dev tcpdump
sudo apt-get install bluez*
USB Extension Cable
I don’t know if this helps at all, but I have put the USB adapter on a 2m extension cable, with the antenna up as high as I could easily get it. I read that some drives in the Pi can cause Bluetooth interference, and it’s also good to keep the adapter away from WiFi antennas. I’ll have a play with this and update at some point.
List USB Connected Devices
This command lists devices plugged into the Pi USB ports. This doesn’t mean the device is working or has a driver / firmware, just that it’s attached and the Pi can see it.
lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0bda:a725 Realtek Semiconductor Corp. Bluetooth 5.1 Radio
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
List Bluetooth Devices / Interfaces
This command lists the Bluetooth devices plugged into to the Pi.
hciconfig -a
When I run that command I get the following - with some information redacted / removed for brevity. Given I know my external bluetooth device has a Realtek chipset I can tell that hci0 is the device I need to tell Home Assistant to use. Once you’ve done the step to disable the built in bluetooth above it will look different.
hci1: Type: Primary Bus: UART
BD Address: E4:5F:... ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING
Name: '...'
Service Classes: Rendering, Capturing, Audio
Manufacturer: Cypress Semiconductor (305)
hci0: Type: Primary Bus: USB
BD Address: 00:E0:... ACL MTU: 1021:6 SCO MTU: 255:12
UP RUNNING
Name: '... #1'
Manufacturer: Realtek Semiconductor Corporation (93)
List Bluetooth IDs
This seems to list the bluetooth adapter IDs.
hcitool dev
Devices:
hci1 E4:5F:01:xx:xx:xx
hci0 00:E0:42::xx:xx:xx
RFKill
I don’t really have any idea what this is, but if your output looks much different from mine maybe look into it.
rfkill
ID TYPE DEVICE SOFT HARD
0 bluetooth hci0 unblocked unblocked
1 bluetooth hci1 unblocked unblocked
Scan for Bluetooth Devices
This scans for bluetooth devices near you. Before I did this I plugged in a bluetooth receiver, enabled Bluetooth on my Android phone, and hit “add new device” to wake it up. The output is the IDs of the Bluetooth devices near you.
hcitool scan
If your built in bluetooth is enabled the range will be poor and likely nothing or only the closest bluetooth devices will be picked up.
Bluetooth Ping
Once you have device Bluetooth IDs you can ping the devices.
sudo l2ping -c 1 88:54:xx:xx:xx:xx
Ping: 88:54:xx:xx:xx:xx from E4:5F:xx:xx:xx:xx (data size 44) ...
44 bytes from 88:54:xx:xx:xx:xx id 0 time 7.31ms
1 sent, 1 received, 0% loss
You can also choose which Bluetooth device to ping from with the -i switch. I can ping my Android phone from either bluetooth adapter - see the third post in this thread.
l2ping -c 1 -i hci1 88:54:xx:xx:xx:xx
l2ping -c 1 -i hci0 88:54:xx:xx:xx:xx
Rename Bluetooth Broadcast ID
sudo hciconfig hci0 name ‘NewNameHere’
Python 3.10 Upgrade Error
If you get an error that looks anything like this
[custom_components.ble_monitor] HCIdump thread: Something wrong - interface hci0 not ready, and will be skipped for current scan period.
[custom_components.ble_monitor] HCIdump thread: Trying to power cycle Bluetooth adapter hci0 00:E0:42:8B:77:03, will try to use it next scan period
Try this - tweak it for your setup
sudo setcap 'cap_net_raw,cap_net_admin+eip' /usr/local/bin/python3.10
sudo systemctl restart home-assistant@homeassistant
This answer is documented in the BLE Monitor FAQ, and was originally found in this github question. Both have more detail and options.
Incidentally, to upgrade Python to 3.10 (and probably higher in future) there’s a good tutorial here.
Appendix - Disabling Bluetooth - Alternate Option
Try the method up the top of the doc first, as of 2024 it seems to work and is very easy.
As of HA 2022.09 you also seem to see your bluetooth adapters in the HA dashboard. You will need to go in and disable it in there. It was autodetected for me, then I disabled it.
That might be enough, but you may want to disable the built-in Bluetooth for some reason. If you’re happy using the HA method skip to the next step, otherwise you can try this. This information was picked up from here with tips from a few other places.
Note: I’m not a Linux expert, I know enough to find things with Google and usually get things working. If any expert wants to correct any of this please comment below, I’d be happy for the advice.
First we add a new target which runs after ‘multi-user.target’.
nano /etc/systemd/system/run-last.target
Add this to the file
[Unit]
Description=Custom Target - starts last
Requires=multi-user.target
After=multi-user.target
AllowIsolate=yes
Then run this to make it executable
chmod 755 /etc/systemd/system/run-last.target
Create the systemd service that calls the script to stop bluetooth on startup
sudo nano /etc/systemd/system/bluetooth-disable.service
Put this into the file
[Unit]
Description=Disable R.Pi4 built in bluetooth on startup
After=default.target
[Service]
ExecStart=/opt/bluetooth/disable_builtin_bluetooth.sh
[Install]
WantedBy=run-last.target
Now create the script that disables bluetooth. Run this to get a list of your bluetooth adapters
hciconfig -a
Look at the output. In this case I want to disable hci1 which is on the UART bus, rather than hci0 on the USB bus. This seems to swap around, each of my Pi4’s seem to be different.
hci1: Type: Primary Bus: UART
UP RUNNING
RX bytes:1616 acl:0 sco:0 events:93 errors:0
TX bytes:2916 acl:0 sco:0 commands:73 errors:0
Link policy: RSWITCH SNIFF
Name: 'XXX'
Class: 0x2c0000
Service Classes: Rendering, Capturing, Audio
Device Class: Miscellaneous,
HCI Version: 5.0 (0x9) Revision: 0x156
LMP Version: 5.0 (0x9) Subversion: 0x6119
Manufacturer: Cypress Semiconductor (305)
hci0: Type: Primary Bus: USB
UP RUNNING PSCAN
RX bytes:9516 acl:0 sco:0 events:385 errors:0
TX bytes:32162 acl:0 sco:0 commands:264 errors:0
Link policy: RSWITCH HOLD SNIFF PARK
Link mode: SLAVE ACCEPT
Name: 'USB'
Class: 0x2c0000
Service Classes: Rendering, Capturing, Audio
Device Class: Miscellaneous,
HCI Version: 5.1 (0xa) Revision: 0x9a9
LMP Version: 5.1 (0xa) Subversion: 0x8a6b
Manufacturer: Realtek Semiconductor Corporation (93)
sudo nano /opt/bluetooth/disable_builtin_bluetooth.sh
Put this into the file - change the hci based on what you found above. I found that if I didn’t include the sleep command it didn’t work. I don’t know why, I figure some other system service or startup item is starting bluetooth and we have to wait until it’s fully started before we turn it off. That’s a guess though, if anyone has any suggestions please reply below.
#!/bin/bash
sleep 10
echo "Disabling hci1 built-in bluetooth adapter"
/usr/bin/hciconfig hci1 down &
Make both of the scripts executable (I think this is necessary)
chmod a+x /opt/bluetooth/disable_builtin_bluetooth.sh
chmod a+x /etc/systemd/system/bluetooth-disable.service
Run the script, then check that the built in bluetooth has been disabled
/opt/bluetooth/disable_builtin_bluetooth.sh
hciconfig -a
It should look something like this
hci0: Type: Primary Bus: USB
UP RUNNING PSCAN
hci1: Type: Primary Bus: UART
BD Address: AA:BB:CC:DD:EE:FF ACL MTU: 1021:8 SCO MTU: 64:1
DOWN
RX bytes:4447 acl:0 sco:0 events:431 errors:0
Finally run this command to run this script every time the server starts
sudo systemctl enable bluetooth-disable.service
Next reboot and check built in bluetooth is down with the hciconfig -a
command. If it’s not, and you work out why, please comment below with the solution.