[bluetooth] Graciously handle systems without DBus (#10153)

This commit is contained in:
Kai Kreuzer 2021-04-08 22:27:41 +02:00 committed by GitHub
parent c5a2882a16
commit 11b24a551a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 18 deletions

View File

@ -51,7 +51,7 @@ public class DeviceManagerFactory {
private final BlueZPropertiesChangedHandler changeHandler = new BlueZPropertiesChangedHandler(); private final BlueZPropertiesChangedHandler changeHandler = new BlueZPropertiesChangedHandler();
private @Nullable CompletableFuture<DeviceManager> deviceManagerFuture; private @Nullable CompletableFuture<@Nullable DeviceManager> deviceManagerFuture;
private @Nullable CompletableFuture<DeviceManagerWrapper> deviceManagerWrapperFuture; private @Nullable CompletableFuture<DeviceManagerWrapper> deviceManagerWrapperFuture;
public BlueZPropertiesChangedHandler getPropertiesChangedHandler() { public BlueZPropertiesChangedHandler getPropertiesChangedHandler() {
@ -79,7 +79,13 @@ public class DeviceManagerFactory {
// Experimental - seems reuse does not work // Experimental - seems reuse does not work
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// Exception caused by first call to the library // Exception caused by first call to the library
return DeviceManager.createInstance(false); try {
return DeviceManager.createInstance(false);
} catch (DBusException ex) {
// we might be on a system without DBus, such as macOS or Windows
logger.debug("Failed to initialize DeviceManager: {}", ex.getMessage());
return null;
}
} }
}, scheduler); }, scheduler);
@ -90,8 +96,10 @@ public class DeviceManagerFactory {
int count = tryCount.incrementAndGet(); int count = tryCount.incrementAndGet();
try { try {
logger.debug("Registering property handler attempt: {}", count); logger.debug("Registering property handler attempt: {}", count);
devManager.registerPropertyHandler(changeHandler); if (devManager != null) {
logger.debug("Successfully registered property handler"); devManager.registerPropertyHandler(changeHandler);
logger.debug("Successfully registered property handler");
}
return new DeviceManagerWrapper(devManager); return new DeviceManagerWrapper(devManager);
} catch (DBusException e) { } catch (DBusException e) {
if (count < 3) { if (count < 3) {
@ -103,7 +111,12 @@ public class DeviceManagerFactory {
}, scheduler); }, scheduler);
}).whenComplete((devManagerWrapper, th) -> { }).whenComplete((devManagerWrapper, th) -> {
if (th != null) { if (th != null) {
logger.warn("Failed to initialize DeviceManager: {}", th.getMessage()); if (th.getCause() instanceof DBusException) {
// we might be on a system without DBus, such as macOS or Windows
logger.debug("Failed to initialize DeviceManager: {}", th.getMessage());
} else {
logger.warn("Failed to initialize DeviceManager: {}", th.getMessage());
}
} }
}); });
} }
@ -114,7 +127,11 @@ public class DeviceManagerFactory {
if (stage1 != null) { if (stage1 != null) {
if (!stage1.cancel(true)) { if (!stage1.cancel(true)) {
// a failure to cancel means that the stage completed normally // a failure to cancel means that the stage completed normally
stage1.thenAccept(DeviceManager::closeConnection); stage1.thenAccept(devManager -> {
if (devManager != null) {
devManager.closeConnection();
}
});
} }
} }
this.deviceManagerFuture = null; this.deviceManagerFuture = null;

View File

@ -14,6 +14,7 @@ package org.openhab.binding.bluetooth.bluez.internal;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
@ -32,25 +33,32 @@ import com.github.hypfvieh.bluetooth.wrapper.BluetoothDevice;
@NonNullByDefault @NonNullByDefault
public class DeviceManagerWrapper { public class DeviceManagerWrapper {
private DeviceManager deviceManager; private @Nullable DeviceManager deviceManager;
public DeviceManagerWrapper(DeviceManager deviceManager) { public DeviceManagerWrapper(@Nullable DeviceManager deviceManager) {
this.deviceManager = deviceManager; this.deviceManager = deviceManager;
} }
public synchronized Collection<BluetoothAdapter> scanForBluetoothAdapters() { public synchronized Collection<BluetoothAdapter> scanForBluetoothAdapters() {
return deviceManager.scanForBluetoothAdapters(); if (deviceManager != null) {
return deviceManager.scanForBluetoothAdapters();
} else {
return Set.of();
}
} }
public synchronized @Nullable BluetoothAdapter getAdapter(BluetoothAddress address) { public synchronized @Nullable BluetoothAdapter getAdapter(BluetoothAddress address) {
// we don't use `deviceManager.getAdapter` here since it might perform a scan if the adapter is missing. DeviceManager devMgr = deviceManager;
String addr = address.toString(); if (devMgr != null) {
List<BluetoothAdapter> adapters = deviceManager.getAdapters(); // we don't use `deviceManager.getAdapter` here since it might perform a scan if the adapter is missing.
if (adapters != null) { String addr = address.toString();
for (BluetoothAdapter btAdapter : adapters) { List<BluetoothAdapter> adapters = devMgr.getAdapters();
String btAddr = btAdapter.getAddress(); if (adapters != null) {
if (addr.equalsIgnoreCase(btAddr)) { for (BluetoothAdapter btAdapter : adapters) {
return btAdapter; String btAddr = btAdapter.getAddress();
if (addr.equalsIgnoreCase(btAddr)) {
return btAdapter;
}
} }
} }
} }
@ -58,6 +66,10 @@ public class DeviceManagerWrapper {
} }
public synchronized List<BluetoothDevice> getDevices(BluetoothAdapter adapter) { public synchronized List<BluetoothDevice> getDevices(BluetoothAdapter adapter) {
return deviceManager.getDevices(adapter.getAddress(), true); if (deviceManager != null) {
return deviceManager.getDevices(adapter.getAddress(), true);
} else {
return List.of();
}
} }
} }