change Bluetooth from master to slave using bluez library - bluetooth

Description:
I have a small in-house device with bluetooth capabilities.
At the moment , other devices connect to that box.
Requirement:
Now we have to make it slave so that it get connected with other devices. I am wondering how to do it ? I don't need source code or anything just your views.
Additional Information:
The application uses Bluez libraires to send command to firmware/hardware and we extensively use HCItool.
Operating system :
Fedora.
I am also wondering , do I need to change chipset? From google it doesnt look like we need to change it.
Any help will be beneficial to us.
Thanks

From the command line, the way to achieve what you want is to use the #hcitool. However, you must first be connected. Try this sequence:
hcitool cc AA:BB:CC:DD:EE:FF #Connect to the device
hcitool con #To make sure you are in a connection
hcitool sr AA:BB:CC:DD:EE:FF <role> #switch master/slave role
If the output of "hcitool con" indicates that you are not in a connection, try the following sequence:
hciconfig hci0 sspmode 1
hciconfig hci0 piscan
sdptool add SP
rfcomm connect /dev/rfcomm0 AA:BB:CC:DD:EE:FF 1 &
hcitool con
hcitool sr AA:BB:CC:DD:EE:FF <role>
The above code is specifically for the serial profile, but it has worked for me on several occasions when 'hcitool cc' failed.
If you want to see the source code for this, open the tools/hcitool.c source file in the bluez directory and navigate to the function:
static void cmd_sr(int dev_id, int argc, char **argv)
This is the function that fires up the sequence for switching between master and slave role. Following this function you can see what exactly happens through the bluez stack.
I hope this helps.

Related

Always assign the same bluetooth dongle the same linux identifier hci0

we have a Raspberry Pi that is always listening for Bluetooth devices and if some conditions for the peripheral apply, it opens a Bluetooth connection to write some data to the peripheral.
For performance optimizations, there is one Bluetooth Dongle only for listening and another one that does the connections/writing. In our scripts, we hardwired hci0 to be the listening device and hci1 to connect.
Now we have the problem, that if somebody unplugs the dongle during runtime and plugs it back in, the device will receive the name hci2. This of course breaks our scripts.
So, my question is: Can I configure my Raspberry Pi OS to always assign the same name to the dongle? I would imagine, as they are using the MAC of the Dongle as an identifier, this should be possible.
Thanks for your help!
Rather than hardcode hci0 and hci1 in your code, I would look up the value for the mac address.
I'll assume you are using the D-Bus API and so could use GetManagedObjects.
For example:
import pydbus
bus = pydbus.SystemBus()
mngr = bus.get('org.bluez', '/')
def get_hci(address):
mngd_objs = mngr.GetManagedObjects()
for path in mngd_objs:
device_info = mngd_objs[path].get('org.bluez.Adapter1', {}).get('Address', 'none')
if device_info == address:
return path
print(get_hci('B8:27:EB:22:33:44'))
# /org/bluez/hci0

Which BluetoothLE handle do I need to write on to enable notifications?

This is my first shot working with bluetooth and I'm confused about which channel I should be sending my write packet to enable notifications. I'm working with the Fitness Machine 0x1826 service and I'm trying to get the data from the 0x2AD2 characteristic, specifically the 0x0030 handle.
When I run "sudo gatttool -t random -b [MAC ADDRESS] -I --char-write-req -a 0x0030 - 0300 --listen" I get no response so I'm led to believe that I'm sending the packet to the wrong handle, as the device should be sending notifications with my actions.
Thanks for any help!
You should send your write packet to Client Characteristic Configuration Descriptor (CCCD), which has a UUID 0x2902. You first need to find the handle of that CCCD within the fitness machine service. You can find more information here:-
Reading Thermometer Data with BlueZ
Bluetooth Low Energy: listening for notifications/indications in linux
However, as ukBaz mentioned, gatttool is deprecated so you should look into using bluetoothctl instead. More information on using bluetoothctl as a gatt client is found here:-
bluetoothctl write on descriptor to enable notification
Using acquire-write and acquire-notify in bluetoothctl

Read data from bluetooth - Android, Raspberry Pi Zero, Bluetooth

I have an application in Android which connects with my Raspberry Pi Zero via Bluetooth.
I start connection in my phone and I only confirm a pairing in RPI.
I send a data from my Android to RPi and I know, this data is received in RPi because when I use:
sudo hcidump -a hci0
I see this data
But I don't have idea how can I write a programm (in python for example) which will read this data and run of led or something else with GPIO.
I tried pybluez.service but I have only:
Waiting for connection on channel 2
I tried
sudo rfcomm watch hci0
but I have:
"Can't bind RFCOMM socket : Address already in use
And others,I tried the first 5-10 tutorials in google or youtube and nothing.
The Bluetooth error "Can't bind RFCOMM socket: Address already in use": means that the bind() function used by the command producing the error (in your case, rfcomm) failed because there is another local socket with the same number (in your case, referred to channel 2) already bound by a local application.
A way to solve this problem is to find the local application in your system which is currently binding that socket (maybe another instance of rfcomm on the same channel). Close the socket in that application, or simply terminate it.

Bluetooth in Terminal

I want to see the Bluetooth adapter details in terminal without using Bluetooth GUI. Initially Bluetooth is turned off both in terminal and GUI.
My commands for different functions in Terminal
View status of Bluetooth (it will show active/inactive and status in some cases, and just active/inactive in some other cases)
sudo /etc/init.d/bluetooth status
Turn on Bluetooth
sudo /etc/init.d/bluetooth start
Turn off Bluetooth
sudo /etc/init.d/bluetooth stop
View the Bluetooth adapter details
hciconfig
I can see the adapter details with the help of Bluetooth GUI in Settings GUI.
I researched the status of Bluetooth in different cases by doing following steps in order:
1. Turn on Bluetooth via terminal
Status = "Running"
Active = "active (running)"
Bluetooth adapter details: Doesn't display anything
2. Turn off Bluetooth via terminal
Status = Not shown
Active = "inactive (dead)"
Bluetooth adapter details: Doesn't display anything
3. Turn on Bluetooth via GUI
Status = "Running"
Active = "active (running)"
Bluetooth adapter details: Shows the adapter details
4. Turn off Bluetooth via terminal, but doesn't change in GUI
Status = "Quitting"
Active = "inactive (dead)"
Bluetooth adapter details: Shows the adapter details
5. Turn on Bluetooth via terminal
Status = "Running"
Active = "active (running)"
Bluetooth adapter details: Shows the adapter details
6. Turn off Bluetooth via terminal, but doesn't change in GUI
Status = "Quitting"
Active = "inactive (dead)"
Bluetooth adapter details: Shows the adapter details
7. Turn off Bluetooth in GUI
Status = Not shown
Active = "inactive (dead)"
Bluetooth adapter details: Doesn't display anything
Can someone please help me what's wrong in my commands? Also, why it works fine along with GUI? What does GUI actually do?
Give this tool a try:
bluetoothctl
Here is the installation guide:
(https://wiki.archlinux.org/index.php/bluetooth#Installation)
it gives you a lot of posibilities:
Menu main:
Available commands:
-------------------
advertise Advertise Options Submenu
scan Scan Options Submenu
gatt Generic Attribute Submenu
list List available controllers
show [ctrl] Controller information
select <ctrl> Select default controller
devices List available devices
paired-devices List paired devices
system-alias <name> Set controller alias
reset-alias Reset controller alias
power <on/off> Set controller power
pairable <on/off> Set controller pairable mode
discoverable <on/off> Set controller discoverable mode
agent <on/off/capability> Enable/disable agent with given capability
default-agent Set agent as the default one
advertise <on/off/type> Enable/disable advertising with given type
set-alias <alias> Set device alias
scan <on/off> Scan for devices
info [dev] Device information
pair [dev] Pair with device
trust [dev] Trust device
untrust [dev] Untrust device
block [dev] Block device
unblock [dev] Unblock device
remove <dev> Remove device
connect <dev> Connect device
disconnect [dev] Disconnect device
menu <name> Select submenu
version Display version
quit Quit program
exit Quit program
help Display help about this program
you can even drill down into the advertise policies and more:
# menu advertise
Menu advertise:
Available commands:
-------------------
uuids [uuid1 uuid2 ...] Set/Get advertise uuids
service [uuid] [data=xx xx ...] Set/Get advertise service data
manufacturer [id] [data=xx xx ...] Set/Get advertise manufacturer data
tx-power [on/off] Show/Enable/Disable TX power to be advertised
name [on/off/name] Configure local name to be advertised
appearance [on/off/value] Configure custom appearance to be advertised
duration [seconds] Set/Get advertise duration
timeout [seconds] Set/Get advertise timeout
clear [uuids/service/manufacturer/config-name...] Clear advertise config
back Return to main menu
version Display version
quit Quit program
exit Quit program
help Display help about this program
That is a lot of information you can pull (and set) directly.

Connecting to BT LE device using org.bluez.Adapter.CreateDevice fails with org.bluez.Error.Failed: Operation canceled Error

I'm trying to set up a connection to a Bluetooth 4.0 LE device on Linux using the BlueZ 4.X DBus interface.
To test this I use the following command:
dbus-send --system --dest=org.bluez --print-reply /org/bluez/<PID of bluetoothd>/hci0 org.bluez.Adapter.CreateDevice string:<MAC of BT device>
This command seems to work most times, giving a result like:
method return sender=:1.238 -> dest=:1.262 reply_serial=2
object path "/org/bluez/9652/hci1/dev_BC_6A_29_26_C2_1C"
and enabling me to interact with the device DBus object.
However, starting from yesterday, this seems to fail very frequently returning the following error:
Error org.bluez.Error.Failed: Operation canceled
When debugging the bluetooth daemon, (using bluetoothd -n -d) I notice the following things when executing the method call:
bluetoothd[340]: src/adapter.c:create_device() BC:6A:29:26:C2:1C
bluetoothd[340]: src/adapter.c:adapter_create_device() BC:6A:29:26:C2:1C
bluetoothd[340]: src/device.c:device_create() Creating device /org/bluez/340/hci0/dev_BC_6A_29_26_C2_1C
bluetoothd[340]: src/device.c:btd_device_ref() 0xb7ad8: ref=1
bluetoothd[340]: src/device.c:device_set_temporary() temporary 1
bluetoothd[340]: src/device.c:btd_device_ref() 0xb7ad8: ref=2
bluetoothd[340]: plugins/mgmtops.c:mgmt_event() cond 1
bluetoothd[340]: plugins/mgmtops.c:mgmt_event() Received 14 bytes from management socket
bluetoothd[340]: plugins/mgmtops.c:mgmt_connect_failed() hci0 BC:6A:29:26:C2:1C status 4
bluetoothd[340]: src/event.c:btd_event_conn_failed() status 0x04
bluetoothd[340]: src/device.c:device_remove() Removing device /org/bluez/340/hci0/dev_BC_6A_29_26_C2_1C
bluetoothd[340]: src/device.c:device_set_temporary() temporary 1
bluetoothd[340]: src/device.c:btd_device_unref() 0xb7ad8: ref=1
bluetoothd[340]: src/device.c:btd_device_unref() 0xb7ad8: ref=0
bluetoothd[340]: src/device.c:device_free() 0xb7ad8
As far as I can see, my Bluetooth dongle sends me an error event (status 4) when I try to connect to the device.
However, when I use hcitool ot gatttool to connect to the device, everything works perfectly.
I found that this happens mostly after I try to connect to the device using a different program (i.e cinnamon-settings), and cancel the connection prematurely. I also noticed this with other programs like bluetooth-properties on Angstrom.
My guess is that Bluez sends the wrong HCI commands to my bluetooth dongle in certain conditions. I think this is because the gui programs try to pair with the device instead of just connecting to it, which may cause BlueZ to think my device is a Bluetooth 2.0 device.
Thus far I seemed to be able to resolve this problem by connecting to my BT device using a gui application, waiting till it fails, and restarting my computer. However, the problem seems to reoccur occasionally, making this very painful.
I have seen this problem on systems running both BlueZ version 4.99 and 4.101.
Does anyone know how I can solve this correctly?
It seems like my predictions where more or less correct. After many hours of debugging the Bluetooth daemon I discovered that connecting to BT LE devices without a preliminary scan causes the daemon to try to connect to the device as a BR/EDR device. This is because the daemon's "internal cache" is filled with the EIR information at the time the device is discovered. If this information is not available when connecting to a LE device the CreateDevice method will fail.
A simple solution is to always make sure to discover devices before connecting to them.
The BlueZ 5 API introduction and porting guide also describes this problem, and how it is solved in BlueZ 5:
Bluetooth Low Energy essentially extended Bluetooth addresses with one extra bit, requiring one to always know whether an address is “random” or “public”. This caused issues with the BlueZ 4 API where the address was given to BlueZ in the CreateDevice and CreatePairedDevice calls. Since the parameter didn’t contain any of this extra random/public information bluetoothd had to maintain an internal cache to look up the necessary info. Another complication to the matter is that the BlueZ D-Bus API doesn’t differentiate between traditional BR/EDR devices and LE devices so there are essentially three possible address types: BR/EDR, LE public and LE random.

Resources