So sum up, I have a device communicating via ble to my application. The application uses Corebluetooth to handle the connection and communication.
The problem:
When a device goes out of range it will disconnect -> it calls the diddisconnect() function where I check if its timed out and call the central.connect again.
it will then start the connection and immediately on some devices(only iOS14) at the moment, it will go to didfailtoconnect with an error saying:
"Error Domain=CBErrorDomain Code=15 "Failed to encrypt the connection, the connection has timed out unexpectedly." UserInfo={NSLocalizedDescription=Failed to encrypt the connection, the connection has timed out unexpectedly."
Only seem to exist on iOS14 devices as far as I have seen.
I also tested blocking signals, if i block signals from device the issue is not apparent. if I block signals from phone, the issue is apparent. Not sure how this is, feels like they both trigger timeout.
May be problem elsewhere aswell but it seem to handle fine on my iOS13 device.(mainly tested on 4 phones, 2 on each version)
Also to clarify, the application is acting as the central, and the device as the peripheral.
If I interpret the error message correctly from CBErrorEncryptionTimedOut (15), it means that the devices initiated a connection, then, suddenly after the iOS device initiated the encryption procedure, the connection unexpectedly died.
So it should be treated more or less the same way as CBErrorConnectionTimeout (6).
If this happens all the time, you should use a BLE sniffer to see what's going on; maybe it's some bug in iOS.
Related
I'm currently developing a react native app in combination with a device. The device and the app communicate via BLE. So far everything works as expected but I'm having issues with the connection stability of the iOS app and the device. What would happen is that the device would connect and I can update some characteristics but it would regularly either disconnect with a CBErrorDomain 7 or the response for a write would timeout. The implementation on the app or device side does not seem to be the problem as Android works stable and the device also disconnects when connecting with the LightBlue app.
I've already updated the BLE connection parameters as suggested here:
https://developer.apple.com/library/archive/qa/qa1931/_index.html.
This has increased the stability but did not resolve the problems completely. I've tried playing around with the values but so far no luck.
The current set of parameters we are using are:
conn_min_interval: 15
conn_max_interval: 15
conn_latency: 0
supervision_timeout: 2000
adv_min_interval: 1285
adv_max_interval: 1285
My question now would be if somebody has an idea what other things I could check or which parameter to tune?
Are you checking the maximumWriteValueLength and making sure your writes are smaller than this? A likely cause of your problems is overwhelming the device and it fails to keep up with sending ACKs. What version of Bluetooth does your device support, and does it implement DLE (Data Length Extension)?
Your conn_min_interval and conn_max_interval are suspicious. Asking for 15ms with no leeway is likely to negotiate to 30ms instead. (See 41.6 Connection Parameters) Is your device comfortable with being re-negotiated to something other than 15ms? Can your device actually keep up with 15ms and no connection latency if it does get that? I'm betting it can't. Try setting your connection interval to 30ms (or even a bit slower), and you might even try setting your connection latency to 1 to make the connection a bit more forgiving (though I'd focus more on slowing the CI than increasing latency; increasing latency would be more of a hack in this case).
All my suspicions are around your peripheral not keeping up with its side of the connection. If you have any synchronous activities in response to the data, you need to make sure that it's not blocking your BLE stack from sending the required responses.
Finally, I've found the answer to my problem. The problem was that the pairing procedure of the BLE server was faulty and thus iOS was unable to have a stable connection. Now that this is fixed the connection is very stable.
I'm still unsure why iOS was able to have any communication at all without the pairing but I hope that this helps some people in the future.
I am using CoreBluetooth for IOS app, after upgrading IOS version the central manager canĀ“t connect to peripheral and not showing any error.
Before starting te process to connect I receive this values from the device:
CBPeripheral: 0x1c0106e40, identifier = BE2B06BF-F385-82AC-95E6-65EA1CF8B11F, name = icomon, state = disconnected
and after I try to connect to the device the state changes:
CBPeripheral: 0x1c411bea0, identifier = BE2B06BF-F385-82AC-95E6-65EA1CF8B11F, name = icomon, state = connecting
and nothing more, nothing happen next, I do not receive any data from the central manager and the device state never change.
I was struggling with a problem that has the exact same symptoms. Hopefully it is the same problem, and this response is helpful.
In my case, the problem was caused by a link layer control PDU that my device was sending immediately after the connection was established. Specifically, I am running Apache Mynewt (http://mynewt.apache.org/), and its NimBLE controller initiates the Feature Exchange Procedure immediately after a connection is made. Since my device is the peripheral, while the iOS 11 device is the central, my device sends the LL_SLAVE_FEATURE_REQ PDU.
I don't know if it is the timing involved or the PDU itself, but whatever the case, the iOS device never sends any application-layer data after the feature exchange. When I change NimBLE so that it does not initiate the feature exchange, device interrogation happens normally, and the CoreBluetooth connected callback gets called.
I try to reconnect my peripheral after rebooting the phone.
I'm using the location update callback to start the BLE connection process in background.
The ble stack is correctly initialized in background (CBCentralManagerStatePoweredOn event sent)
The "connect" on the peripheral is started but no connection is established...
Any idea to reconnect a device after reboot ?
When you say that the "connect" on the peripheral is started, do you mean that you manually connect using connectPeripheral: ? I have in the past struggled with connection on iOS and noticed that CoreBluetooth has a lot of race conditions internally that you have to avoid. Typically what I recommend is to always do a dispatch delay on all connect requests of at lest 20ms that happens after a CoreBluetooth callback. This will avoid most race conditions. You can test this out yourself for example by setting a pending connection and then at a later point calling cancelPeripheralConnection: before the peripheral has connected. When you get the didFailToConnect callback then immediately call connectPeripheral: again. Now the connection should be in a "limbo" mode where the connection status is "connecting" but in fact the peripheral will never connect. Calling connect again will do nothing either at this point.
I don't know if this is the cause of your issue, but it could be. Also, upon CentralManager state restoration I would recommend letting the framework "settle" for around a second before starting interacting with it.
One other important thing is that you don't re-initiate the manager until after you get the applicationDidFinishLaunchingWithOptions: callback of your AppDelegate. Doing this earlier can cause strange behaviors.
Please do some more investigations and if you are still having issues then let me know. I may have some further tips. /Anton
I am getting unexpected behavior. I am making a simple wrapper on Corebluetooth and made 2 apps: one acts as client and other as server.
On the server end, whenever I am updating characteristic value through [updateValue: forCharacteristic: onSubscribedCentral] I am getting response as 0. According to Apple documentation, It will return YES if the update could be sent, or NO if the underlying transmit queue is full.I googled for this error and found that this can be handled by sending the data again in peripheralManagerIsReadyToUpdateSubscribers: method. This is working fine.
Issue comes in client end.
After connecting to device, and reading values successfully, my peripheral gets disconnected with error : The specified device has disconnected from us. This happens in spite of the fact my server is continuously sending values. My problem is somewhat similar to
Peripheral transmit queue issue
but in my case sometime peripheral remain connected and value is updated on client side. But most of time peripheral disconnects.
I have googled a lot for the solution even tried few advices given at:
CoreBluetooth repeatedly disconnecting. But of no use.
I am able to connect to a peripheral device using BLE, but shortly after reading some characteristics, the framework returns:
CoreBluetooth[WARNING] Unknown error: 14
and the peripheral is disconnected.
Looking at the BT Core_V4.0 spec, I am not sure what the error means. Is the 14 a hex value? does it mean the following error according to the spec: (Part D Section 2 - Error Codes)
2.20 REMOTE DEVICE TERMINATED CONNECTION DUE TO LOW RESOURCES (0X14)
The Remote Device Terminated Connection due to Low Resources error code indicates that the remote device terminated the connection because of low resources.
I tried changing the battery but did not have a different effect.
Also, I don't know how to catch these CB errors, I only see them logged, but when the device disconnects, it does not provide an error (it is null).
I do not directly control the source code for the peripheral but can ask for a bug fix. So any hints are appreciated it.
Thanks,
You cannot intercept these CB errors, they are just traces from lower layer BLE.
Error 13 for instance is when the length of written data is not as specified in the GATT database.
Error 14 means the connection was closed by other side (peripheral). I have seen this several times. Some times I read data too fast (You are not allowed to request next access before previous has been answered, there is only 1 "resource" in BLE per connection. Maybe this is what you also see?
As always it is best to get the TI BTLE USB Dongle with sniffer sw installed and then use the TI RF Sniffer tool in BLE mode with that dongle. You get a lot of information you can debug from in those traces. Like see if there are more than one read or write request without response.