NimBLE-Arduino icon indicating copy to clipboard operation
NimBLE-Arduino copied to clipboard

Apple watch connection only works 1 in 10 times

Open DTTerastar opened this issue 3 years ago • 14 comments

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:

image

Any idea on how to get this to work more of the time? capture-apple-watch.pdf

DTTerastar avatar Mar 09 '22 12:03 DTTerastar

This is what success looks like: image

DTTerastar avatar Mar 09 '22 13:03 DTTerastar

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.

h2zero avatar Mar 10 '22 02:03 h2zero

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.

DTTerastar avatar Mar 10 '22 11:03 DTTerastar

https://github.com/ESPresense/ESPresense/blob/68f52e5b9eccbf0916ad4d0023fe3942f7a04ff9/lib/BleFingerprint/BleFingerprint.cpp#L435

DTTerastar avatar Mar 10 '22 11:03 DTTerastar

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

DTTerastar avatar Mar 10 '22 15:03 DTTerastar

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.

h2zero avatar Mar 12 '22 01:03 h2zero

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.

DTTerastar avatar Mar 12 '22 16:03 DTTerastar

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

h2zero avatar Mar 12 '22 16:03 h2zero

I made the mtu response optional, but not of the other stuff. I will try that and report back.

DTTerastar avatar Mar 12 '22 16:03 DTTerastar

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

h2zero avatar Mar 12 '22 17:03 h2zero

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.

DTTerastar avatar Mar 12 '22 18:03 DTTerastar

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?

DTTerastar avatar Mar 14 '22 12:03 DTTerastar

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?

h2zero avatar Mar 15 '22 03:03 h2zero

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.

DTTerastar avatar Mar 19 '22 23:03 DTTerastar