Skip to content

Commit

Permalink
[bluetooth] Graciously handle systems without DBus (openhab#10153)
Browse files Browse the repository at this point in the history
Signed-off-by: John Marshall <[email protected]>
  • Loading branch information
kaikreuzer authored and themillhousegroup committed May 10, 2021
1 parent 90ab7e1 commit 68b79cc
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class DeviceManagerFactory {

private final BlueZPropertiesChangedHandler changeHandler = new BlueZPropertiesChangedHandler();

private @Nullable CompletableFuture<DeviceManager> deviceManagerFuture;
private @Nullable CompletableFuture<@Nullable DeviceManager> deviceManagerFuture;
private @Nullable CompletableFuture<DeviceManagerWrapper> deviceManagerWrapperFuture;

public BlueZPropertiesChangedHandler getPropertiesChangedHandler() {
Expand Down Expand Up @@ -79,7 +79,13 @@ public void initialize() {
// Experimental - seems reuse does not work
} catch (IllegalStateException e) {
// 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);

Expand All @@ -90,8 +96,10 @@ public void initialize() {
int count = tryCount.incrementAndGet();
try {
logger.debug("Registering property handler attempt: {}", count);
devManager.registerPropertyHandler(changeHandler);
logger.debug("Successfully registered property handler");
if (devManager != null) {
devManager.registerPropertyHandler(changeHandler);
logger.debug("Successfully registered property handler");
}
return new DeviceManagerWrapper(devManager);
} catch (DBusException e) {
if (count < 3) {
Expand All @@ -103,7 +111,12 @@ public void initialize() {
}, scheduler);
}).whenComplete((devManagerWrapper, th) -> {
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());
}
}
});
}
Expand All @@ -114,7 +127,11 @@ public void dispose() {
if (stage1 != null) {
if (!stage1.cancel(true)) {
// 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand All @@ -32,32 +33,43 @@
@NonNullByDefault
public class DeviceManagerWrapper {

private DeviceManager deviceManager;
private @Nullable DeviceManager deviceManager;

public DeviceManagerWrapper(DeviceManager deviceManager) {
public DeviceManagerWrapper(@Nullable DeviceManager deviceManager) {
this.deviceManager = deviceManager;
}

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) {
// we don't use `deviceManager.getAdapter` here since it might perform a scan if the adapter is missing.
String addr = address.toString();
List<BluetoothAdapter> adapters = deviceManager.getAdapters();
if (adapters != null) {
for (BluetoothAdapter btAdapter : adapters) {
String btAddr = btAdapter.getAddress();
if (addr.equalsIgnoreCase(btAddr)) {
return btAdapter;
DeviceManager devMgr = deviceManager;
if (devMgr != null) {
// we don't use `deviceManager.getAdapter` here since it might perform a scan if the adapter is missing.
String addr = address.toString();
List<BluetoothAdapter> adapters = devMgr.getAdapters();
if (adapters != null) {
for (BluetoothAdapter btAdapter : adapters) {
String btAddr = btAdapter.getAddress();
if (addr.equalsIgnoreCase(btAddr)) {
return btAdapter;
}
}
}
}
return null;
}

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();
}
}
}

0 comments on commit 68b79cc

Please sign in to comment.