package nodomain.freeyourgadget.gadgetbridge.util; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.widget.Toast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Coordinator; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleCoordinator; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; public class DeviceHelper { private static final Logger LOG = LoggerFactory.getLogger(DeviceHelper.class); private static final DeviceHelper instance = new DeviceHelper(); public static DeviceHelper getInstance() { return instance; } // lazily created private List coordinators; // the current single coordinator (typically there's just one device connected private DeviceCoordinator coordinator; public boolean isSupported(GBDeviceCandidate candidate) { if (coordinator != null && coordinator.supports(candidate)) { return true; } for (DeviceCoordinator coordinator : getAllCoordinators()) { if (coordinator.supports(candidate)) { return true; } } return false; } public GBDevice findAvailableDevice(String deviceAddress, Context context) { Set availableDevices = getAvailableDevices(context); for (GBDevice availableDevice : availableDevices) { if (deviceAddress.equals(availableDevice.getAddress())) { return availableDevice; } } return null; } /** * Returns the list of all available devices that are supported by Gadgetbridge. * Note that no state is known about the returned devices. Even if one of those * devices is connected, it will report the default not-connected state. * * Clients interested in the "live" devices being managed should use the class * DeviceManager. * @param context * @return */ public Set getAvailableDevices(Context context) { BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); Set availableDevices = new LinkedHashSet(); if (btAdapter == null) { GB.toast(context, context.getString(R.string.bluetooth_is_not_supported_), Toast.LENGTH_SHORT, GB.WARN); } else if (!btAdapter.isEnabled()) { GB.toast(context, context.getString(R.string.bluetooth_is_disabled_), Toast.LENGTH_SHORT, GB.WARN); } else { Set pairedDevices = btAdapter.getBondedDevices(); DeviceHelper deviceHelper = DeviceHelper.getInstance(); for (BluetoothDevice pairedDevice : pairedDevices) { GBDevice device = deviceHelper.toSupportedDevice(pairedDevice); if (device != null) { availableDevices.add(device); } } Prefs prefs = GBApplication.getPrefs(); String miAddr = prefs.getString(MiBandConst.PREF_MIBAND_ADDRESS, ""); if (miAddr.length() > 0) { GBDevice miDevice = new GBDevice(miAddr, "MI", DeviceType.MIBAND); if (!availableDevices.contains(miDevice)) { availableDevices.add(miDevice); } } String pebbleEmuAddr = prefs.getString("pebble_emu_addr", ""); String pebbleEmuPort = prefs.getString("pebble_emu_port", ""); if (pebbleEmuAddr.length() >= 7 && pebbleEmuPort.length() > 0) { GBDevice pebbleEmuDevice = new GBDevice(pebbleEmuAddr + ":" + pebbleEmuPort, "Pebble qemu", DeviceType.PEBBLE); availableDevices.add(pebbleEmuDevice); } } return availableDevices; } public GBDevice toSupportedDevice(BluetoothDevice device) { GBDeviceCandidate candidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN); if (coordinator != null && coordinator.supports(candidate)) { return coordinator.createDevice(candidate); } for (DeviceCoordinator coordinator : getAllCoordinators()) { if (coordinator.supports(candidate)) { coordinator.createDevice(candidate); } } return null; } public DeviceCoordinator getCoordinator(GBDeviceCandidate device) { if (coordinator != null && coordinator.supports(device)) { return coordinator; } synchronized (this) { for (DeviceCoordinator coord : getAllCoordinators()) { if (coord.supports(device)) { coordinator = coord; return coordinator; } } } return new UnknownDeviceCoordinator(); } public DeviceCoordinator getCoordinator(GBDevice device) { if (coordinator != null && coordinator.supports(device)) { return coordinator; } synchronized (this) { for (DeviceCoordinator coord : getAllCoordinators()) { if (coord.supports(device)) { coordinator = coord; return coordinator; } } } return new UnknownDeviceCoordinator(); } public synchronized List getAllCoordinators() { if (coordinators == null) { coordinators = createCoordinators(); } return coordinators; } private List createCoordinators() { List result = new ArrayList<>(2); result.add(new MiBand2Coordinator()); // Note: MiBand2 must come before MiBand because detection is hacky, atm result.add(new MiBandCoordinator()); result.add(new PebbleCoordinator()); return result; } }