How do we get RSSI values from Bluetooth beacons (estimote to be specific) in Linux? - linux

I need to get distances from multiple bluetooth beacons for triangulation so that I can do indoor positioning.
I have tried to give as many relevant details as possible. This project is for an RPi, but I am currently trying to test it through my laptop first. I have tried most of what I can find on the internet about this:
The best way I could find to get the rssi values was hcitool rssi <address of beacon>
From here Bluetooth LE Signal Strength Linux
To test this, I tried to get it for my mobile first. It showed "Not Connected". I thought I need to connect first, so I tried many ways to connect my mobile:
a) hcittol cc <address of mobile>
b) gatttool -b <address of mobile> -t random --interactive
c) rfcomm connect 0 <address of mobile> 10
In each case, when I clicked pair in my mobile, connection terminated.
Then, I paired my mobile the usual way from bluetooth menu, and then tried hcitool rssi <Address of mobile> which then finally returned a value -8.
Now that I had it for my mobile, I now moved to beacons.
Then, I tried the same for my beacons. This time I had to
first do hcitool lescan to get addresses of available beacons
then connect to one of the beacons using the command hcitool lecc <address of beacon> which returned the error Could not create connection: Connection timed out
So next, I again tried connecting with the other two ways:
rfcomm connect 0 <address of beacon> 10 which returned the error Can't connect RFCOMM socket: Host is down when I can be sure hci0 was up.
Then I tried with sudo gatttool -b F1:15:A7:E3:17:63 --interactive after which interactive mode opened up and I gave the command connect. This gave different errors after Attempting to connect to <address of beacon>,
mainly connect error : Connection timed out
and Error: connect error: Connection refused (111)
Then I read I need to use -t random from Bluetooth LE on Raspbian , https://ubuntuforums.org/showthread.php?t=2204808 and one another source which I can't find right now.
So I entered sudo gatttool -b F1:15:A7:E3:17:63 -t random --interactive in which when I gave the connect command, I got error Error: connect error: Device or resource busy (16) and also sometimes Error: connect error: Input/Output Error
then I read that I perhaps need to restart my hci0 by hciconfig hci0 down and then hciconfig hci0 up which did the trick, the beacon now got connected.
But then, it quickly got disconnected after saying `GLib-WARNING **: Invalid file descriptor.
`
I read here https://raspberrypi.stackexchange.com/questions/53982/how-to-fix-gatttools-glib-warning-invalid-file-descriptor that this is because of poor connections. I tried keeping the beacons closer, but it did the same.
So I tried to anyway at least get one rssi value during the short duration it is connected. But, even when it was thus connected, I did hcitool rssi <address of beacon> the error came like this:
hcitool rssi F1:15:A7:E3:17:63
Get connection info failed: No such file or directory
To which I haven't yet found a proper solution.
I tried another way of reading the rssi value, which gave the following :
hcidump -R
HCI sniffer - Bluetooth packet analyzer ver 5.37
device: hci0 snap_len: 1500 filter: 0xffffffffffffffff
> 04 0E 04 01 0B 20 00
> 04 0E 04 01 0C 20 00
> 04 0E 04 01 0C 20 00
> 04 0F 04 00 01 0D 20
> 04 0F 04 00 01 16 20
> 04 0F 04 00 01 13 20
This was before it got disconnected.
I read here Obtain RSSI with hcidump which said to read the 14th byte. since all these seemed to be hex numbers, this would mean that each number is 1 byte. But this way, I only have 7 numbers per line, how can I read the 14th byte?
Getting distance from beacons has been troubling me a lot, and has used up a a lot of my time. Please help me out on this issue. If you can help me find a resource to help me do so, I'd appreciate the help.

You don't need to connect to a device to get the signal strength RSSI values, just use the following code and pipe that to a script that extracts values from the devices you are after:
btmon &
hcitool lescan --duplicates

Related

Is there a bug fix for sporadic SIGSEGV crashes of the BlueZ bluetoothd (version 5.50) in Debian 10?

I am developing software for a commercial product that runs on a Moxa MPC-2070 panel computer (Intel Atom based) under Debian 10 (Buster) with BlueZ (5.50) bluetooth support. The application has been developed using Qt Creator. I have been struggling to find a robust and reliable method to scan for Bluetooth Low Energy devices.
Because of an extreme performance problem associated with the QBluetoothDiscoveryAgent::start() method in Qt (which I won't go into here), I am using the bluetoothctl command to perform BLE device scanning. A wrapper around bluetoothctl provides it with input commands and parses the output from bluetoothctl. Sporadically (once every 1 - 150 times) that I launch bluetoothctl to perform the BLE scan, the bluetooth daemon process (bluetoothd) crashes with a SIGSEGV.
Here is the tail of syslog after the bluetoothd crash:
[315398.536280] show_signal_msg: 8 callbacks suppressed
[315398.536293] bluetoothd[523]: segfault at a8ec8148fd ip 00007f681ba3e143 sp 00007ffc8110a858 error 4 in libdbus-1.so.3.19.11[7f681ba2f000+2e000]
[315398.536343] Code: 85 ed 74 13 0a 18 88 18 48 83 c4 08 5b 5d c3 0f 1f 84 00 00 00 00 00 f7 d3 22 18 88 18 48 83 c4 08 5b 5d c3 0f 1f 00 48 8b 07 <0f> b6 40 02 85 f0 0f
95 c0 0f b6 c0 c3 55 48 89 fd 53 89 f3 48 83
I have restarted bluetoothd with the -d flag to enable debug output via:
$ sudo bluetoothd -d &
And again ran the bluetoothctl scans in a loop until bluetoothd again crashed. The full syslog showing the bluetoothd crash can be found here: Complete syslog with bluetoothd SIGSEGV
In the above syslog, the initial bluetoothd (without -d) crash can be found at Jan 14 09:58:55.
The restart of bluetoothd with the -d flag is at Jan 14 10:03:16.
The looping use of bluetoothctl begins at Jan 14 10:06:03.
bluetoothd again SIGSEGVs at Jan 14 10:05:13.
Sometimes the bluetoothd crashes happen after only 1 or 2 bluetoothctl commands, and other times it takes many iterations before the crash occurs.
This shell script will reproduce the bluetoothd crash. It loops performing essentially the same function as my C bluetoothctl wrapper program, but without the bluetoothctl output processing. Note that this script must be run as root or by a user id which is a member of the 'bluetooth' group.
#! /bin/bash
COUNT=0
RESULT=0
while [ "${RESULT}" != "9" ]
do
COUNT=`expr ${COUNT} + 1`
echo "Loop #${COUNT}"
# uveTagScanner -s FEA0 ${#} # The compiled bluetoothctl wrapper program with output processing
# RESULT="$?"
( echo "menu scan" # Enter the bluetoothctl scan sub-menu
echo "clear" # Clear all filter parameters
echo "transport le" # Filter scanning for low-energy devices only
echo "duplicate-data off" # Disable reporting of duplicate-data
echo "back" # Exit the bluetoothctl scan sub-menu & return to main menu
echo "scan on" # Start scanning for LE devices
sleep 10 # Let scanning proceed for 10 seconds
echo "scan off" # Stop scanning for LE devices
echo "quit" # Quit the bluetoothctl command
) | bluetoothctl
done
Within my C wrapper program (uveTagScanner) which fork()/exec()s bluetoothctl and performs the output processing, I am able to detect if bluetoothd has crashed and then restart it. But this is only a band-aid solution, as it still leaves me with instances where the scanning for BLE devices does not provide the needed information.
I'm running out of ideas on how to reliably perform BLE device scanning! I could try using the BlueZ libraries and Dbus interface APIs instead of bluetoothctl, but I fear that the same bluetoothd crash would occur.

BlueZ, How to turn off br/edr without using btmgmt?

I'm new to Bluetooth and BlueZ, I was working on a BLE project using BlueZ, for some reason I cannot use btmgmt -i hci0 bredr off command to turn off br/edr. I was wondering how to turn of br/edr using hcitool or any other util provided by BlueZ. Thanks in advance.
After a few days reading some question on Stackoverflow and reading Bluetooth specification. I finally found a way to use hcitool to do it. The command is
hcitool -i hci0 cmd 0x08 0x0008 12 02 01 04 02 0A 0C 0B
where 01 04 is the key 01 referred to the flag, 04 referred to bredr not supported. Thank u all.

iBeacon Dynamic Minor Value

I am using a Raspberry Pi as an iBeacon by creating a LaunchService that runs on startup executing the following (using BlueZ):
sudo hciconfig hci0 up
sudo hcitool -i hci0 cmd 0x08 0x0006 40 [...] 00
sudo hcitool -i hci0 cmd 0x08 0x000A 01
sudo hcitool -i hci0 cmd 0x08 0x0008 1E [...] 02 C0 00 00 00 00 C5 00
So far this has worked beautifully. The service runs and as long as the Pi is powered, the iBeacon is advertised.
Now I would like to send some Information with the advertising data. I have a brightness sensor wired up to the Pi that simply returns true if a certain threshold of brightness has been exceeded.
My idea is to use the Minor identifier and use 1 to represent "it is bright" and 0to represent "it is dark". My app can then interpret this without having to poll the Pi via a network request what the current sensor status is.
But since I set the advertisement package statically, I won't be able to use this approach going forward I believe.
I have no idea how else to do this however, so I was hoping someone might have some insight and could point me in the right direction.
Thanks for your time!
Easy. You can simply re-issue those commands, specifically the last one:
sudo hcitool -i hci0 cmd 0x08 0x0008 1E [...] 02 C0 00 00 00 00 C5 00
Just change the last byte before the C5 above to be 01 if you want to send out a minor of 1, and change it back to 00 if you want to send out a minor of 0.

Zengge BLE bulb protocol

I've just got a smart led bulb from Zengge and want to control it from my Linux machine with Bluetooth 4.0. I've installed latest bluez 5.x package, so I have a gatttool available. I am able to connect to my bulb and list it's services. But I have no ideas how to control it. Maybe someone have already done that (I was unable to Google for ready solution)? Or have some developments in this area? Or maybe someone have the specs?
For those who are interested, here are my findings about the bulb protocol.
1) Check if your bluetooth device is up: hcitool dev
2) If device is down: hciconfig hci0 up
3) Scan for bluetooth le devices: hcitool lescan
4) Turn on device: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x001a -n 04
5) Turn off device: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x001a -n 63
6) Dim warm light: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x0013 -n 56000000ff0faa where ff is the hex code for the intensity.
7) Colored light: gatttool -b YOUR:LE:DEVICE:MAC:ADDRESS --char-write-req -a 0x0013 -n 56e92fff99f9aa where e9 is hex red intensity, 2f is hex green intensity, 2f is hex blue intensity
(I'v got the codes by turning on the Bluetooth HCI-snoop-log in Android wile using the Magic Light app and analysing it with Wireshark)

Bluetooth Low Energy: listening for notifications/indications in linux

I'm trying to communicate with a BLE module through a Linux machine (the module is running a heart rate profile). So far, I've been able to do everything I need except listening for Notifications and indications (e.g. listening for the Heart Rate Measurement Notification). I'm using kernel version 3.5 and bluez-5.3.
Succcessful commands used so far:
hcitool lescan
hcitool lecc
gatttool -b <Mac Address> --primary
gatttool -b <MAC Address> --characteristics
gatttool -b <MAC Address> --char-read
gatttool -b <MAC Address> --char-desc
gatttool -b <MAC Address> --interactive
Failed commands:
gatttool -b <MAC Address> --listen
Any help is greatly appreciated.
Try this...
Run gatttool -b <MAC Address> --interactive like you did before. You'll get a prompt and then you type connect. You should see a CON in the prompt indicating that you've connected to the device. Then type char-read-uuid 2902. You should get a list of all CCC (Client Characteristic Configuration) attributes on the device. You can try setting them all to 0100 to get notifications, 0200 for indications, 0300 for both, or 0000 for everything off. Type help to see all the commands and their arguments.
EDIT:
The use of the --listen argument requires you to couple it with other commands to turn on the notifications and/or indications. So here's an example that works in Bluez 4.101:
gatttool -b <MAC Address> --char-write-req --handle=0x0031 --value=0100 --listen
Obviously you need to change the handle to the handle of the CCC that you want to turn on notifications for. However, I still find it way easier to just use the interactive mode.
Looks like the older version of Bluez (hcitool & gatttool) don't allow you to write to Bluetooth Low Energy devices. I ended up installing a newer version (5.17 as of this writing) in order to enabled notifications, etc.
To get a list of all your handles you can run the following:
char-desc
You can then read from a handle:
char-read-hnd 0x000e
(the above handle is for my nrf51822 battery level)
Where the handle is one from the list you got from char-desc.
Just like Tim said above, you can write to the notification related handle to get indications or notifications. (in my case my device only had notifications)
char-write-req 0x000f 0100
(the above handle is for my nrf51822 battery level notification)
In my case the battery notification shouldn't send anything until the battery level has changed.
I wrote a pretty lengthy blog post on getting setup with Bluez. You can find it here: Get Started with Bluetooth Low Energy Feel free to check it out!
Final answer for reading heart rate on Mio Alpha :
gatttool -b xx:xx:xx:xx:xx:xx -t random --char-write-req -a 0x0025 -n 0100 --listen
Characteristic value was written successfully
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4a 3e 03
Notification handle = 0x0024 value: 10 4c 28 03 28 03
Notification handle = 0x0024 value: 10 4c 28 03
Notification handle = 0x0024 value: 10 4b 33 03
Notification handle = 0x0024 value: 10 4a 3e 03 3e 03
to retain the CCC value you need to pair the two device. once they are paired you do not need to set the CCC again. on next reconnection it will find the setting , which will be saved in thec FLASH of Key fob. try to configure after pairing via SMP.

Resources