[bluetooth.generic] Only poll linked characteristics and recover without dropping intent - #21529
Draft
vkolotov wants to merge 2 commits into
Draft
Conversation
… intent A handler that is connected but has not been able to resolve the GATT services recovers by bouncing the link and retrying service discovery. The only way to express that was disconnect(), which is also how a handler says "I no longer want this device connected". A transport that tracks connection intent (to keep an alwaysConnected device connected, for example) cannot tell the two apart, and reads the recovery attempt as a request to stop connecting. The result is a connect/disconnect flap. Add BluetoothDevice#reconnect() for the recovery case. The default implementation delegates to disconnect(), so transports that do not track intent keep their current disconnect-then-reconnect behaviour unchanged. Signed-off-by: Vlad Kolotoff <vkolotoff@pm.me>
…out dropping intent Three related fixes to the characteristic polling job, each behind a binding config switch that defaults to the new behaviour and can be turned off to restore the old one. Poll only linked characteristics. The job read every readable characteristic on every tick, whether or not the channel had a linked item, which is needless GATT traffic on the device. Notification enable/disable already tried to key off links, but used isLinked(), which the existing TODO in the code notes reports true for channels that are not linked. Use ItemChannelLinkRegistry#getLinkedItemNames() instead, and apply the same test to reads. Switch: pollOnlyLinkedCharacteristics. Recover unresolved services with reconnect() rather than disconnect(), so a transport that tracks connection intent does not read the recovery as "stop wanting this device" and flap. Switch: reconnectOnUnresolvedServices. Guard the tick body. An uncaught RuntimeException from a transport call would cancel the repeating job, and polling then stopped for good with nothing in the log. Catch and log instead, so the next tick retries. Also poll once as soon as service discovery completes, instead of leaving a freshly resolved device idle until the next scheduled tick, which is up to a full polling interval of dead air after every reconnect. Signed-off-by: Vlad Kolotoff <vkolotoff@pm.me>
vkolotov
force-pushed
the
vkolotov/bluetooth-generic-reconnect-and-linked-polling
branch
from
August 29, 2026 06:09
470864b to
6e163cb
Compare
vkolotov
marked this pull request as ready for review
August 29, 2026 06:17
vkolotov
marked this pull request as draft
August 29, 2026 12:34
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a supporting PR for a larger project (new bluetooth binding for direct access).
Four fixes to the generic binding's characteristic polling job, plus the core API change one of them needs. Each behaviour change sits behind a binding config switch that defaults to the new behaviour, so it can be turned off if it misbehaves on some device or transport.
Poll only linked characteristics.
Recover unresolved services without dropping connection intent. When a device is connected but its GATT services never resolve, the job bounced the link with
disconnect(), which is also how a handler says it no longer wants the device connected. A transport that tracks intent cannot tell the two apart and reads the recovery as a request to stop connecting, so it flaps.Guard the tick body. An uncaught RuntimeException from a transport call cancells the repeating job, and polling then stopped and nothing in the logs.
Also polls once as soon as service discovery completes, rather than leaving a freshly resolved device idle until the next scheduled tick.