How to handle initializeDevice failure? #2996
Labels
No Label
device mi band 7
activity post processing
activity/health
Android 12
Android 13
android integrations
architecture
Bangle.js
bug
changes requested
charts
details not provided
developer documentation
device amazfit band 5
device amazfit bip
device amazfit cor
device Casio
device fossil
device garmin
device gtr 2e
device gts 2 mini
device h30
device hplus
device huami
device Huawei
device liveview
device mi band
device mi band 2
device mi band 3
device mi band 4
device mi band 5
device mi band 6
device no.1 f1
device pace
device pebble
device pebble 2
device pinetime infinitime
device request
device sony
device support
device watch 9
device xiaomi
discussion
documentation
duplicate
enhancement
feature request
Gadgetbridge
good first issue
help wanted
i am developing my own app can you help
icebox
intent api
internationalisation
invalid
needs work
network companion app
new device
no feedback
not a bug
notifications
one of the 1000 issues about disconnection
pairing/connecting
potentially fixed / confirm and close
question
research
security
seems abandoned
Solved, waiting for F-Droid release
suggest to close
task
user interface / UX
wear os
weather
wontfix
Zepp OS
No Milestone
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Freeyourgadget/Gadgetbridge#2996
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Before reporting a bug, please confirm the following:
Where did you get Gadgetbridge from:
Your Gadgetbridge version is:
0.71.3-banglejs (this has been an issue since Bangle.js got added though)
Your issue is:
Under some circumstances a device's
initializeDevice
can be called without the relevant Bluetooth characteristics having been found. In this case, getCharacteristic returnsnull
and thenTransactionBuilder
write
calls to that all fail.It's quite rare, and it's possible it's due to an Android implementation issue, or maybe even just radio interference while the characteristics are being fetched.
(Also AbstractBTLEDeviceSupport.performInitialized can call it, seemingly without ever getting the services)
But the repurcussions are bad: In Bangle.js, initializeDevice still runs through, although a bunch of stuff fails. The device stays connected, but nothing works, and eventually Bangle.js is buffering up data to send and the watch just hangs, waiting for Gadgetbridge to enable notifications so it can send its data.
I checked and I can't find any other devices that check if getCharacteristic returns non-null, so I think this must apply to other watches too.
So, what I'd like to do is when getCharacteristic returns null in initializeDevice, just ask Gadgetbridge to disconnect and retry the connection which should fix it.
Can I literally just add:
Or it seems this will break stuff? It seems like AbstractBTLEDeviceSupport may be expecting that initializeDevice will always complete. Is there a better way? Can
mQueue.disconnect()
be called? I'm not sure it's ever used.I also wonder if the fix for this could maybe help with #2880
Log of this happening is attached, the issue happens around 11:10:22.931.
Sorry for the ACTION_DEVICE_CHANGED spam messages - I just fixed this.
Expected
When it occasionally breaks
Your wearable device is:
Bangle.js
Your Android version/manufacturer flavor is:
Android 11 (MIUI 12.5.8)
But it happens on many other phones too.
Hi - does anyone have any thoughts on this? @joserebelo ?
I realise the issue posted was a bit long, but basically:
How do I force a device reconnect from within the
initializeDevice
function?@gfwilliams sorry, I missed this issue.
I think this is actually not as rare as you think. I'm fairily sure this is what's causing reconnects to fail on my Amazfit GTR 4, and probably a lot of other devices - the symptoms are similar:
Logs here
Fixing this would probably fix reconnects across all devices.
As for your question - I have no idea. This is actually one of the few areas of Gadgetbridge in which I do not yet have a lot of experience, I have to take some time in the weekend to dive into the code. We will probably have to run a few tests and see how it behaves.
I do get this issue multiple times per day, so once we have some changes that we want to test I can probably just use them for a while.
No offense, but it's great news that it's affecting you! I had it happen once or twice but it hasn't happened in months for me (although it is affecting others).
We'd have to look but if
getCharacteristic
was always used in such a way that it shouldn't give a non-null response, we could add a check in there and it'd fix all watches.Either that or for each watch we just check that the characteristics it cares about are non-null, and if they are we force a reconnect. I guess that could be safer.
I have a Casio GW-B5600 and all the characteristics are null on the first connectino (when pairing), but I did not observe this on any later connection.
For me the following workaround works:
2d0cd54136
The workaronud consists of calling
mQueue.disconnect()
followed byconnect()
.@gfwilliams @johannesk I was experimenting with my Amazfit GTR 4, and managed to make the issue somewhat reproducible by turning bluetooth off and on on the watch.
Instead of disconnecting and reconnecting, I set the device as waiting for reconnect, and let the reconnection mechanism trigger the reconnect at a slightly later time - this includes a back-off mechanism, which does not exist when calling disconnect and connect - which might actually enter a loop in quick succession?
This seems to have fixed the issue on my side, I will now run it for a while to check if it keeps reconnecting without issues through normal usage.
See #3219
That sounds perfect! Exactly what I was after - do you think you could add it to the Bangle.js build as well, or shall I do that?
Just looking at #3219 you call
builder.add(new SetDeviceStateAction(getDevice(), State.WAITING_FOR_RECONNECT, getContext()));
if either of the characteristics is null?That doesn't actually cause a disconnect though? Or does
WAITING_FOR_RECONNECT
automatically disconnect if the watch was connected?It seems to only trigger a connect, without disconnecting first:
a02a6cba14/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/receivers/AutoConnectIntervalReceiver.java (L87)
I can add it to the Bangle if you want, just need to try and reproduce the issue there first, maybe by toggling bluetooth on the watch too.
Thanks for checking that! Maybe wait a bit then - I think at least for Bangle.js it would probably help to force a disconnect first.
Maybe if this is a common thing we should have a method in AbstractBTLEDeviceSupport.java for it?
At least one user is reporting problems still: https://forum.espruino.com/conversations/378217/?offset=25#comment17199563
So I just pushed a potential fix for this that copies that line - let's hope it has some effect.