mirror of
https://github.com/danieldemus/openhab-addons
synced 2026-07-29 12:34:21 +02:00
[bluetooth] Fix BlueZ events stopping after reconnect (no SERVICES_DISCOVERED) (#20950)
#20903 changed onServicesResolved() to call discoverServices() instead of firing SERVICES_DISCOVERED unconditionally. discoverServices() only notified when the openHAB-side service list *grew* (getGattServices().size() > getServices().size()). That list (supportedServices) is only cleared on BlueZ object removal, so on a normal reconnect BlueZ re-fires ServicesResolved=true while the list is already fully populated, the "grew" check is false, and SERVICES_DISCOVERED is never re-fired. Consumers built on ConnectedBluetoothHandler re-arm their notifications and polling off onServicesDiscovered() (e.g. grundfosalpha enables notifications and schedules its read loop there; the generic binding rebuilds channels). Swallowing the event leaves the Thing ONLINE but silent after every reconnect - no events are received, matching #20947. Fire SERVICES_DISCOVERED whenever the GATT is resolved with services present, not only when the list just grew. Population still happens only when the list grows, but the notification now always reaches listeners on a resolve. The event is idempotent for all consumers (generic only adds missing channels; ConnectedBluetoothHandler/grundfosalpha re-enabling notifications is a no-op when already notifying). Fixes #20947 Signed-off-by: Vlad Kolotoff <vkolotoff@pm.me>
This commit is contained in:
+11
-3
@@ -386,13 +386,13 @@ public class BlueZBluetoothDevice extends BaseBluetoothDevice implements BlueZEv
|
||||
@Override
|
||||
public void onServicesResolved(ServicesResolvedEvent event) {
|
||||
if (event.isResolved()) {
|
||||
// Populate our service/characteristic list from the now-resolved GATT before notifying
|
||||
// Populate our service/characteristic list from the now-resolved GATT and notify
|
||||
// listeners. BlueZ can deliver ServicesResolved=true while our own supportedServices list
|
||||
// is still empty (e.g. right after a reconnect, before discoverServices() has run); firing
|
||||
// SERVICES_DISCOVERED then makes listeners (e.g. the generic handler's channel builder) run
|
||||
// against an empty list and miss every characteristic. discoverServices() populates the
|
||||
// list and fires SERVICES_DISCOVERED itself once it has added services, so it is the
|
||||
// correct trigger here. If the services are already known it is a cheap no-op.
|
||||
// list and fires SERVICES_DISCOVERED once the GATT is resolved with services present -
|
||||
// including on a reconnect where the list is unchanged - so it is the correct trigger here.
|
||||
discoverServices();
|
||||
}
|
||||
}
|
||||
@@ -505,6 +505,14 @@ public class BlueZBluetoothDevice extends BaseBluetoothDevice implements BlueZEv
|
||||
}
|
||||
addService(service);
|
||||
}
|
||||
}
|
||||
// Notify whenever the GATT is resolved with services present, not only when our list just
|
||||
// grew. On a reconnect BlueZ re-fires ServicesResolved=true while our supportedServices map
|
||||
// is already fully populated from the previous connection (it is only cleared on object
|
||||
// removal), so the "grew" check above is false. Consumers such as ConnectedBluetoothHandler
|
||||
// re-arm their notifications/polling off SERVICES_DISCOVERED, so swallowing it here leaves the
|
||||
// Thing online but silent after every reconnect. The notification is idempotent for listeners.
|
||||
if (!getServices().isEmpty()) {
|
||||
notifyListeners(BluetoothEventType.SERVICES_DISCOVERED);
|
||||
}
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user