NimBLE-Arduino
NimBLE-Arduino copied to clipboard
Apple watch connection only works 1 in 10 times
I've narrowed it down to something to do w/ LL negotiation. The mtu negotiation response seems to be delayed because of some other kind of negotiation. On your codebase not getting an mtu response severs the connection, i've worked around that in my fork and now I can see of the traffic:

Any idea on how to get this to work more of the time? capture-apple-watch.pdf
This is what success looks like:

Looks like the watch disconnects after a certain time to preserve battery power. That's just my guess, I do not have one to test with.
In both cases I immediately ask for 3 characteristics and discconect, but in failure mode NimBLE gets stuck after that first request. I'm not trying to stay connected at all. I think it's because it's trying to I think it's because it's trying to negotiate more link options, but I don't really understand Bluetooth enough to know.
https://github.com/ESPresense/ESPresense/blob/68f52e5b9eccbf0916ad4d0023fe3942f7a04ff9/lib/BleFingerprint/BleFingerprint.cpp#L435
More info from increasing log level:
1 Query | MAC: 68b20023ee2f, ID: apple:1005:9-26 5ms E NimBLEClient: Connection was made but no response from MTU exchange E NimBLEClient: serviceDiscoveredCB() rc=7 E NimBLEClient: Could not retrieve services E NimBLEClient: Disconnected, could not retrieve services -aborting
I don't know why this connection is failing as the logs do not contain the reason code (only LL_TERMINATE_IND, possibly the value 28 on that line is the indicator, may have something to do with bonding in that case). I can see in the logs that you are requesting 16bit uuid services/attributes that are not found, you may want to test using the 128bit version of these (newer releases do this for you).
E NimBLEClient: serviceDiscoveredCB() rc=7; This simply means the device disconnected while attempting to retrieve the services.
I'm not using any bonding, just characteristics that can be read without security. Nothing you've said explains why it's intermittent. The success case uses the exact same code. It seems to me like some kind of timing/race. The apple watch definitely wants to talk about options and upgrades, and the mtu response doesn't come as soon as NimBLE is expecting it. That was the initial hurdle that was killing the communication.
Sorry, I was assuming you had removed the MTU exchange as you had stated that previously, so I was looking for the connection failure reason. The feature request and link layer requests/responses that you are referring to should not be a cause of the connection problem you are experiencing. These are handled by the core host/controller code and do not provide any feedback to or take any input from the application code.
If you want to experiment with removing some of the feature request code you could remark this line: https://github.com/h2zero/NimBLE-Arduino/blob/c0d1ce06fc34de72f88cdfdd4ef577d0e783a40c/src/nimble/host/src/ble_gap.c#L1948
I made the mtu response optional, but not of the other stuff. I will try that and report back.
One other thing to try is altering your connection parameters to use the apple specs:
There are certain rules and formulae that the parameters must follow. If the parameters do not comply with all of these rules, the parameter request may be rejected, or the stability and the performance of the connection may be compromised.
Interval Min ≥ 15 ms (multiples of 15 ms)
Interval Min + 15 ms ≤ Interval Max (Interval Max == 15 ms is allowed)
Interval Max * (Slave Latency + 1) ≤ 2 seconds
Interval Max * (Slave Latency + 1) * 3 < connSupervisionTimeout
Slave Latency ≤ 30
2 seconds ≤ connSupervisionTimeout ≤ 6 seconds
https://developer.apple.com/library/archive/qa/qa1931/_index.html
Oh, I've tried all sorts of those combinations. But since I can sniff the connection being open and connected I don't think that's it.
I am seeing more success based on master vs 1.3.7. But master still has the stackoverflow that is fixed in 1.3.7. Is there any plans to get master and 1.3.7 more in line w/ each other?
They are very much inline, unless I missed something? Master has 658339b8fdee81c644608ea898a7294c2275574b which is the overflow fix in 1.3.7. Maybe this a new issue?
They are very much inline, unless I missed something? Master has 658339b which is the overflow fix in 1.3.7. Maybe this a new issue?
NM, It was something else.