I am currently attempting to connect to multiple BLE devices using BlueZ 5.0 and Linux. I have one host BLE adapter and I have modified the gatttool to connect and perform this function. If I run an instance of the modified gatttool, I successfully connect and receive notification data from the BLE device. If I run another instance of the modified gatttool and connect to another BLE device, this application starts receiving notification data from both BLE devices and the initial application no longer receives any data. I believe this is due to the socket setup, where both applications are configuring their sockets to the same address and PSM (the newest instance receives the data whereas the other is starved). Is there a way to prevent this condition? Ideally, I want one application to connect to multiple devices. I assume that the application can only have one socket for the reason that multiple sockets will have the same issue as the multiple instances above. My BLE device is a TI CC2540 keyfob acting as a heartrate monitor.
I started an answer so I could have more space...
I'm using a combination of Python and C to get my code to work, so my "code" may look funny because it could be from either. Also, I used Bluez 4 as the 5 didn't support the kernel I was using. Let me know if there's an issue and I can clarify.
It seems like there's several ways of doing things, but I ended up opening separate sockets for different tasks. You can open a single socket and then set the socket options to take filtering off and you should get all the packets in one place. However, that was my initial way of doing it and I found that my connections would die within seconds.
To scan for connections I opened a socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI) then did a bind on device 0. (there's a function called hci_get_route to get an available device number) You can then call hci_le_set_scan_parameters to set options, setsockopt(SOL_HCI, HCI_FILTER, filter) to just get LE scan events, and then called hci_le_set_scan_enable to turn on scanning.
Each device connection was made with a socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) which you then tell to connect to a particular device by calling connect on the socket with a struct sockaddr_l2 that has the particular device address in it. On that socket you should only get packets from that device. (one caveat... I found that my dongle wouldn't allow a connection while active scanning was taking place.. I had to temporarily shut it off just before connecting and then turn it back on. Otherwise I got a BUSY error from errno)
After saying all that, though... I think the way you're supposed to do everything in Bluez 5 is to use DBUS. Unfortunately that wasn't really an option for what I was doing. The functions I mentioned are in the shared lib that apparently isn't installed by default in 5 (you have to explicitly ask for it to be installed with configure). They stopped installing the shared lib by default because they wanted to encourage people to use DBUS instead.
WE have combined the code from hcitool and gatttool. The code works well for 2 device (scan, hci_le_create_conn and gatt_connect). I believe there is no limitation on the number of devices used.
1 Start cmd_lescan (from hcitool.c)
2.For each device scanned -
cmd_lecc (from hcitool.c)
gatt_connect (from gatttool.c)
This way one process can manage multiple BLE device. We do not have to turn OFF the scanning, just have ignore non advertisement messages:
if (meta->subevent != 0x02)
continue;
Thanks and looking forward to comments.
Related
first of all: What i am trying to do is only for private interest.
I'd like to connect a AT-09/HM-10 BLE-Module with Firmware 6.01 to another device which provides also a BLE Module, which it is not based on the CC254X-Chip,
I am able to communicate with this Device using my Laptop with integrated Bluetooth, Linux and the bluepy-helper. I am also able to make a connection using the HM10 through a USB-RS232-Module and "Hterm", but after that quite Stuck in my progress.
By "reverse-engineering" the Android-Application for controlling this particular device i found a set of Commands, stored as Strings in Hex-Format. The Java-Application itself sends out the particular Command combined with a CRC16-Modbus-Value in addition with a Request (whatever it is), to a particular Service and Characteristic UUID.
I also have a Wireshark-Protocol pulled from my Android-Phone while the application was connected to the particular device, but i am unable to find the commands extracted from the .apk in this protocol.
This is where i get stuck. After making a connection and sending out the Command+CRC16-Value i get no response at all, so i am thinking that my intentions are wrong. I am also not quite sure how the HM-10-Firmware handles / maps the Service and Char-UUIDs from the destination device.
Are there probably any special AT-Commands which would fit my need?
I am absolutely not into the technical depths of Bluetooth and its communication layer at all. The only thing i know is that the HM-10 connects to a selected BLE-Device and after that it provides a Serial I/O and data flows between the endpoints.
I have no clue how and if it can handle Data flow to certain Service/Char UUIDs from the destination endpoint, althrough it seems to have built-in the GATT , l2cap-Services and so on. Surely it handles all the neccessary communication by itself, but i donĀ“t know where i get access to the "front-end" at all.
Best regards !
I am trying to configure a bluetooth scatternet with esp32-wrover v3 or esp32-wrover-E. At this time, if one device acting as a bridge in scatternet exists at the same time as the GATT server and the client, wouldn't the problem occur?
The problem I want to know is:
Q1. Is it possible that the connection between the client (Master) and the bridge (Client+server) and the server (slave) are connected at the same time? (means when one device acts as a bridge)
Q2. 1:10 Bluetooth low energy tried to connect 1 master and 10 slaves, but failed.
I understand that this is a situation where the physical connection of the ESP32 is only up to 7. Is this the cause?
Q3. I want to configure 3 scatternets to connect 1:10 at the same time with ESP32.
What I am trying to configure is one master and two bridges, and four of each bridge are connected to slave(server).
At this time, if this connection method is connected at the same time, does not a problem occur?
Q4. The example source I used in the esp-idf framework is as follows.
https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/ble/gattc_multi_connect
https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/ble/gatt_server
In the original source, 1 application and 1 profile are combined and connected to 1 device. Using this source, I tried to manage multiple devices with one application and one profile through conditional statements that classify multiple devices in the callback function using only one application. However, at this time, there is no problem when connecting one, but when trying to connect a second device, the device connected in front of it is disconnected. Do you know what is causing this?
Or, if you know about the process of esp GATT Client event occurring, please answer.
(Additional question. Can I know the operation process and management of tasks managed through FreeRTOS in esp32 bluetooth?)
Thank you.
I am fairly new to working with Bluetooth and the ESP32 Bluetooth stack, so forgive me if I don't use the right terminology.
I can get the ESP-IDF Development example "A2DP_Source" working perfect only if I enable the headphones pairing mode first. After it is paired, and the bonding is stored in the Bluetooth, it will reconnect to the headphones without issue, but it then does not notify the app through the call back functions that it has connected. The app then continues to search for a bluetooth device and the audio streams sporadically, or not at all.
I've tried multiple speakers, and headphones, all with the same results.
I can see the bonded device list also and the device is there.
Is there callback function in the bluetooth stack that needs to be initialized to notify the app that the bluetooth connected to a previously paired device instead of just a device in pairing mode?
These are the three callback functions setup currently that run when connected through pairing mode, but don't run when the bluetooth connects in non-pairing mode.
...
/* register GAP callback function */
esp_bt_gap_register_callback(bt_app_gap_cb);
/* initialize AVRCP controller */
esp_avrc_ct_init();
esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
/* initialize A2DP source */
esp_a2d_register_callback(&bt_app_a2d_cb);
esp_a2d_source_register_data_callback(bt_app_a2d_data_cb);
...
Any help or pointers would be appreciated. Thanks.
Did you mean ESP32 A2DP cannot connect a device without the push of a PAIR button?
The example "A2DP_Source" does not seem to connect the bonded device.
It just tries to discover the device with the certain name ("ESP_SPEAKER" in the original code) calling the function esp_bt_gap_start_discovery.
If the device is found, bt_app_gap_cb is called and then the connect to peer will start via esp_a2d_source_connect.
So I suggest fixing the code so as to connect peer instead of calling esp_bt_gap_start_discovery if there is any bonded device.
You can use the function esp_bt_gap_get_bond_device_list and find out the address of the bonded device which is required by esp_a2d_source_connect.
The API reference is available in https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/esp_gap_bt.html and https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/esp_a2dp.html.
Working through this problem more, I found that using C++ to call the native C code was the issue. I don't have a strong enough background in coding to understand the "why" it did not work, but once I returned all the code back to "C" it started working without issue. Hope this helps someone else who may make the same mistake.
We are currently working on an application on linux (a.o. RasPi running latest Debian Jessie) that connects to a BLE device (developed by us). This tool has evolved from cherry-picking files from the bluez (5.46) stack and adding an application layer on top. This all works quite nicely, except for the fact that connecting is incredibly slow. From the output of our tool, I understand that a truckload of messages need to be exchanged to communicate GATT services and characteristics, and each of those costs one connection interval of time. Since it is a low power device, we want the connection interval to be relatively high, and thus the high delay.
When connecting with Android BLE Scanner, I see (on the device side) that BLE Scanner manipulates the connection interval to a low value, gets all the requested data, and then sets the connection interval back to its original value. Note, btw, that neither BLE Scanner nor our Bluez-derived application take the preferred connection parameters into account.
Now I want to have our application do the same: set the connection interval to 8ms, get all info about characteristics and services, and set the connection interval back. In the Bluez stack I even find a nice function in the HCI layer for this: hci_le_conn_update.
But now the challenge: the rest of the application is built on top of the GATT functionality and even though the BLE specification defines a hierarchy between those two (with some layers in between), in code they seem absolutely independent of each other.
There are two parameters to the hci_le_conn_update function that are HCI specific: 'dd' (file descriptor to device) and 'handle' (some value that identifies the connection). The hcitool tells me that when I create a connection, the first handle is 64, so I tried with that value. For 'dd' I used hci_dev_open to get a file descriptor for the device. This worked. Sort of.
As I said before, the min/max values are not entirely taking into account. So when I set it to 6/10, I get 11 and when I set it to 6/50, I get 60. This is a bit too undeterministic for my taste, and I would prefer a function that directly changes the connection interval instead of giving a range that is mostly ignored anyway. Also the fact that I have to use a hardcoded magic number 64 gives me a bad itch. I can actually control the connection interval on the embedded device's side, but I want the control at the side of the client application.
The goal is to update the connection interval in a Bluez-GATT-based application. Within certain limits, I do not mind that much how I get there. Any suggestions?
In the official dbus API, there is no method to change connection parameters. (See https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt and https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt). The key is therefore to send the Connection Parameter Update Request from the peripheral side. You can of course experiment with sending a raw hci command but that is a bit "hacky" and has no guarantees to not mess up the BlueZ daemon.
If you would like to discuss the features of BlueZ such as an connection parameter update request api, you should do that on the BlueZ mailing list (http://www.bluez.org/contact/) rather than here.
I have programmed a D-Link GSM modem on a windows machine to send and receive SMS, for testing I used Hyperterminal.
In windows the connection manager initiates the COMx ports, modem uses one unlisted COMx port through which I can send an SMS, and through a listed NMEA port I receive incoming SMS, calls like +CMTI: "ME", 11 or RING +CLIP: XXXXXXXXXXXX
I'm successfully interpreting the message and programming it to my requirements in windows. While trying the same in linux(Fedora), I see the modem initialises /dev/ttyUSB0 and /dev/ttyUSB1 as the two newly identified devices. I use minicom to set the device ports and communicate AT commands to the same.
In both the devices (/dev/ttyUSB0 and /dev/ttyUSB1) I'm not receiving unsolicited AT result code like +CMTI indication whenever I'm expecting a new SMS. FYI I've set the CNMI setting according to the manual and several other combinations.
A strange thing is that I'm able to see RING when I'm calling but not +CLIP: <callerinfo>. Similarly I'm not getting ++PSBEARER: XX, Y or +CMTI: "ME", XX
The only alternative solution is to poll the UNREAD messages at regular intervals, which is generally a bad design. Please tell me if I'm doing anything wrong with regards to the configuration, should I change some thing else apart from these?
RING is the only UR code you can assume that will always come without any specific configuration (just because this is such an old relic that it just behaves that way...). For all other UR codes, you must explicit enable each and every one of them, e.g. AT+CLIP=1, etc, otherwise they will not be enabled. And enabling those are per serial interface, e.g. running AT+CLIP=1 on /dev/ttyUSB0 will not make +CPLIP: ... be printed on /dev/ttyUSB1.
So when you get them on windows the connection manager, it must be because it has those included in it init strings. Minicom I think defaults to no init string or possibly just a very classical one like ATS0=0 E1Q0V1.