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.
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.
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.
I know the default connection interval for CoreBluetooth is 30 ms. I've read couple of articles that claim they can reduce it 30 ms > by changing the min and max of the interval. I didn't see any explanation of how they were changing the parameters of it? I am assuming this is all in the iOS end.
Currently I am working on a project where the iOS device is sending packets to the bluetooth le device. When I was writing without response, there were a lot of packets being dropped so I added a handshake so once the bluetooth device receives a packet the iOS sends the next packet. This is currently taking a long time to upload a file since the connection interval is 30 ms which I am trying to reduce.
Any suggestions would be helpful
td;lr How do I change the connection interval on iOS
Solution So after doing research there is no public API that allows iOS devices to request for a connection interval change request. For Android this is possible.
There is no API on iOS for a app as master (using CBCentralManager) to modify the initial Connection Parameters when connecting to a peripheral.
However, the slave can suggest new connection parameters using a L2CAP Connection Parameter Update Request (see Bluetooth 4.0 specification, Volume 3, Part A, Section 4.20), which iOS will accept if they are reasonable (see Bluetooth Accessory Design Guidelines for Apple Products section 3.6 “Connection Parameters”). Peripherals should do this because different operating systems have different default connection parameters that might not be optimal for a particular peripheral. For example, if you rare implementing your peripheral in iOS or OSX, call -[CBPeripheralManager setDesiredConnectionLatency:forCentral:. Or, if you are using the TI BLE stack to program a CC2540 or the like, call the function L2CAP_ConnParamUpdateReq.
I have an app that acts as a Bluetooth LE peripheral. I have a single service with four characteristics. 2 out of the 4 are read and write only, the other two are configured as notify.
If I subscribe to one of the "notify" characteristics then the app will not disconnect until I do so manually, works well.
My issue is, If I read or write to the other characteristics, and the then am inactive for around 30 seconds, the BTLE connection disconnects from the peripheral. This may be a limitation set by apple, not sure.
Anyone know of a solution to keep the peripheral active even when there aren't any subscribers and no read or write command has been received in 30 seconds??
This is a by-product of the BLE 4.0 specs. Bluetooth Low Energy is explicitly designed to not maintain a connection for long periods which is what you are describing.
The only way to bypass this (beyond subscribing to a characteristic as you have found) would be to modify the implementation of the BLE stack on the peripheral you are connecting to and removing or elongating the interval of connection to a point that you find satisfactory.
Although this may not help you either as both sides of the BLE communication negotiate these values and iOS may impose a maximum below your requested threshold.
In my case reason was in a mismatch between characteristic properties. I wrote data to a characteristic with "waiting for response" option, but characteristic was in 'without response' state.
The symptom: write callback in delegate does not work when BLE peripheral did not write a response.
I have an app that creates a TCP socket and receives data from different kinds of hardware. The majority of my customers are happy users, but some have the problem that the TCP connection is interrupted after some time (could be 30 seconds or 5 minutes).
I'm using the CFStreamCreatePairWithSocketToHost - approach, and do all my handling in the "handleEvent" method.
I've got some customers loggings of the failure, and I get this event:
ErrorOccurred "The operation couldn’t be completed. Socket is not
connected (Code = 57)"
After a couple of successful reconnections I might get this event when I try to reconnect:
ErrorOccurred "The operation couldn’t be completed. No route to host
(Code = 65)"
The easy explanation would be that their devices that create the WiFi network and stream the data are bad, but some customers are also using other apps that connects to the same devices, and those apps don't lose their connections.
I'm running out of ideas what to change or improve to solve the problem.
I've checked that the size of the data available, and it's never more than 1 sentence, so it's not like any buffers are running full.
I actually also have a small test app that does nothing but connect to the broadcasting device and log the received data - and that also loses the connection for these customers.
I also tried to use AsyncSocket instead but I am having the same problem.
My hairs are turning grey... :-) Any help would be appreciated.
A lot of testing, logging and speculating finally solved the case.
The only thing the customer had to do was to lower the baud rate, and the problem disappeared.
Case closed.