short question
Is it possible to disconnect from a bluetooth device in swift? If so, how?
background
I would like to disconnect from my bluetooth device programmatically using swift 4 because I am working with a 3rd party bluetooth library and am noticing that when I call their commands to 'close the connection', that my instance variable of type
EAAccessoryManager.shared().connectedAccessories.count
is still equal to 1, and my EAAccessory instance shows that my connection is open, however my 3rd party library ConnectionManager shows my connection as closed (because I call the command to close it). However, apparently calling this 3rd party library ConnectionManager's 'close connection' function is not enough to actually clear the instance variables of EAAccessoryManager.shared() and EAAccessory
EAAccessoryManager.shared().connectedAccessories
is get-only, so I cannot set the connected accessories to an empty array.
Related
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.
I'm a newbie of BLE programming on android.
In my first apps using BLE on android, I have a big problem.
I got a ScanRecord from Apple Bluetooth Headset using this function.
#Override
public void onScanResult(int callbackType, ScanResult result)
and I got a manufacturer data using Apple corp, ID(0x4C).
after that, I don't know how to decode a manufacturer data.
I want to auxiliary bluetooth headset information such as battery info, direction info etc. but I don't know how to decode the manufacturer data.
I also searched Apple development document(https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf)
But that guide document didn't help me.
Anyway, anyone who tell me how to resolve this problem?!!?!
Thank you to read my question.
Ok so from your comment it looks like you scanned the device over BLE and want to use one of the services it offers to get information like battery info.
The first thing you will need to do establish a connection to the BLE device.
The scanresult you pasted has a method getDevice you'll need to call
After you get the device you can call its connectGatt method. This will attempt to connect your phone and BLE device.
The connectGatt method from step 2 requires a callback. When the connection is successful or unsuccessful the callback will fire onConnectionStateChanged. If successful it will have the success status. This method will also give you a gatt device we will use in step 4.
If step 3 was successful we can assume your phone is connected. The next thing we want to do is discover services. You do this by using the gatt devices discoverServices method.
When the services are discovered your callback will fire onServicesDiscovered. At this point you can now use services. Depending on the API of the headphones they'll want you to read, or subscribe to a services characteristic and descriptor. Since I don't know the API I can't help you further. But you'll end up needing to use one or more of the following:
setCharacteristicNotification
readCharacteristic
readDescriptor
And the value will return to your callback on. Keep in mind you must wait for the callback for each request before write/reading/subscribing to another characteristic or descriptor.
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.
Is it possible to write a Chrome extension (or Android app) that creates multiple Senders, each connecting to a different Receiver?
In other words, I need to build an interface from which an operator can control the streams on multiple different Chromecasts in the vicinity - each will be playing a different video stream.
I understand from other posts that the chrome.cast API does not allow for this - that the Chrome extension may acts as a single Sender only? This restriction seems arbitrary - I read somewhere that someone was able to control two devices by running two different versions of Chrome, so if this restriction exists in the Chrome API, it's not due to any limitation of the underlying protocol, correct? (what then, politics?)
Is there a lower-level API (perhaps on Android?) that would permit you to create multiple Senders and connect them to different Receivers?
I've seen some apps (such as Videostream) which appear to continue to run on the Receiver after you've closed the Sender. Might it be possible to, for example, launch a Receiver app on multiple devices, one at a time, have them identify themselves and connect to a local webserver, e.g. via WebSockets, and then have my webserver send messages to those Receiver apps to ask them to change videostreams?
As a last resort, is there an open specification of the underlying protocol?
There is nothing to stop you from writing a sender app that connects to a chromecast, launches an app and then disconnects from that device while letting the chromecast continue running the app; you would need to make sure that you do not stop the receiver when it detects that there are no connected devices. Then, on the sender side, you can repeat the same process but this time connect to a second device and so on. The important thing to keep in mind is that your sender device cannot hold multiple concurrent connections to multiple devices (MediaRouter is a global instance); this means you cannot receive messages (status updates, etc) from different Cast devices except the one you are directly connected to at that time. Also, there is nothing to stop a different user to connect to one of these devices and launch a different app.
To answer your other question, the underlying protocol is not open.
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.