Skip to content

Commit

Permalink
Merge branch 'device_filter'
Browse files Browse the repository at this point in the history
  • Loading branch information
lz1asl committed Mar 10, 2021
2 parents fb43a49 + 08ca7f6 commit 4ed7a38
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 87 deletions.
75 changes: 54 additions & 21 deletions src/main/java/com/astoev/cave/survey/activity/main/BTActivity.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package com.astoev.cave.survey.activity.main;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.Pair;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;

Expand Down Expand Up @@ -39,7 +36,8 @@
*/
public class BTActivity extends MainMenuActivity implements Refresheable {

Set<Pair<String, String>> devices = new HashSet<>();
private AbstractBluetoothDevice deviceFilter;
private Set<Pair<String, String>> devices = new HashSet<>();

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand All @@ -59,11 +57,14 @@ private void prepareUI() {
return;
}

displaySupportedDevices();

Spinner devicesChooser = findViewById(R.id.bt_devices);
devicesChooser.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectDevice();
refreshDevicesList();
}

@Override
Expand All @@ -74,8 +75,6 @@ public void onNothingSelected(AdapterView<?> parent) {

refreshDevicesList();

displaySupportedDevices();

} catch (Exception e) {
Log.e(LOG_TAG_UI, "Failed during create", e);
UIUtilities.showNotification(R.string.error);
Expand All @@ -91,20 +90,41 @@ public void showDevicesHelp(View aView) {
}

private void displaySupportedDevices() {
LinearLayout devicesList = findViewById(R.id.bt_container);

if (devicesList.getChildCount() <= 3) { // don't duplicate
List<SupportedDevice> supportedDevices = new ArrayList<>();
supportedDevices.add(new SupportedDevice(null));
for (AbstractBluetoothDevice device : BluetoothService.getSupportedDevices()) {
supportedDevices.add(new SupportedDevice(device));
}

TextView preparing = findViewById(R.id.bt_preparing);
preparing.setVisibility(View.INVISIBLE);
ArrayAdapter<SupportedDevice> spinnerArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, supportedDevices);
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Spinner devicesChooser = findViewById(R.id.bt_supportd_devices);
devicesChooser.setAdapter(spinnerArrayAdapter);

devicesChooser.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

// mark selection
SupportedDevice device = (SupportedDevice) devicesChooser.getSelectedItem();
deviceFilter = device.device;

for (AbstractBluetoothDevice device : BluetoothService.getSupportedDevices()) {
TextView deviceLabel = new TextView(getApplicationContext());
deviceLabel.setText("\t\u2022 " + device.getDescription());
deviceLabel.setTextColor(Color.WHITE);
devicesList.addView(deviceLabel);
// need new LE discovery
BluetoothService.stop();
BluetoothService.discoverBluetoothLEDevices(deviceFilter);

// filter the active devices
refreshDevicesList();
}
}

@Override
public void onNothingSelected(AdapterView<?> parent) {

}
});

deviceFilter = null;
}

@Override
Expand All @@ -113,9 +133,8 @@ protected void onResume() {

BluetoothService.registerListeners(this);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
BluetoothService.discoverBluetoothLEDevices();
}
BluetoothService.stop();
BluetoothService.discoverBluetoothLEDevices(deviceFilter);

prepareUI();
}
Expand All @@ -138,7 +157,7 @@ protected String getScreenTitle() {

private void refreshDevicesList() {

devices = BluetoothService.getPairedCompatibleDevices();
devices = BluetoothService.getPairedCompatibleDevices(deviceFilter);

String selectedDeviceName = null;
String selectedBtDeviceAddress = ConfigUtil.getStringProperty(ConfigUtil.PROP_CURR_BT_DEVICE_ADDRESS);
Expand Down Expand Up @@ -198,7 +217,7 @@ public void selectDevice() {
// store & propagate
ConfigUtil.setStringProperty(ConfigUtil.PROP_CURR_BT_DEVICE_NAME, device.first);
ConfigUtil.setStringProperty(ConfigUtil.PROP_CURR_BT_DEVICE_ADDRESS, device.second);
BluetoothService.selectDevice(device.second);
BluetoothService.selectDevice(device.second, deviceFilter);
}

/**
Expand Down Expand Up @@ -240,4 +259,18 @@ protected void onPause() {
public void refresh() {
runOnUiThread(() -> updateDeviceStatus());
}

public static class SupportedDevice {
public static final String NO_DEVICE_SELECTED = " --- ";
AbstractBluetoothDevice device;

public SupportedDevice(AbstractBluetoothDevice aDevice) {
device = aDevice;
}

@Override
public String toString() {
return device != null ? device.getDescription() : NO_DEVICE_SELECTED;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public class BluetoothService {

private static final Set<AbstractBluetoothRFCOMMDevice> SUPPORTED_BLUETOOTH_COM_DEVICES = new HashSet<>();
private static final Set<AbstractBluetoothLEDevice> SUPPORTED_BLUETOOTH_LE_DEVICES = new HashSet<>();
private static final Set<AbstractBluetoothDevice> SUPPORTED_BLUETOOTH_DEVICES = new HashSet<>();

static {

Expand All @@ -114,6 +115,8 @@ public class BluetoothService {
SUPPORTED_BLUETOOTH_LE_DEVICES.add(new HerschLEM50BluetoothLeDevice());
SUPPORTED_BLUETOOTH_LE_DEVICES.add(new Bric4BluetoothLEDevice());

SUPPORTED_BLUETOOTH_DEVICES.addAll(SUPPORTED_BLUETOOTH_COM_DEVICES);
SUPPORTED_BLUETOOTH_DEVICES.addAll(SUPPORTED_BLUETOOTH_LE_DEVICES);
}

// generic
Expand Down Expand Up @@ -281,13 +284,13 @@ private static void stopLE() {
}
}

public static synchronized void selectDevice(final String aDeviceAddress) {
public static synchronized void selectDevice(final String aDeviceAddress, AbstractBluetoothDevice aFilter) {
if (StringUtils.isEmpty(aDeviceAddress)) {
Log.i(LOG_TAG_BT, "No device selected");
return;
}
mSelectedDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(aDeviceAddress);
mSelectedDeviceSpec = getSupportedDevice(mSelectedDevice);
mSelectedDeviceSpec = getSupportedDevice(mSelectedDevice, aFilter);
if (mSelectedDeviceSpec == null) {
Log.i(LOG_TAG_BT, "No spec found");
return;
Expand All @@ -306,6 +309,7 @@ public static synchronized void selectDevice(final String aDeviceAddress) {
}

mCommunicationThread = new CommDeviceCommunicationThread(mSelectedDevice, (AbstractBluetoothRFCOMMDevice) mSelectedDeviceSpec);
mCommunicationThread.setDeviceFilter(aFilter);
mCommunicationThread.start();
} else {
// require newer android to work with LE devices
Expand Down Expand Up @@ -342,15 +346,10 @@ public static boolean isPaired() {
return mCommunicationThread != null && mCommunicationThread.ismPaired();
}

public static AbstractBluetoothDevice getSupportedDevice(BluetoothDevice aDevice) {
public static AbstractBluetoothDevice getSupportedDevice(BluetoothDevice aDevice, AbstractBluetoothDevice filter) {
Log.d(LOG_TAG_BT, "Search supported device for " + aDevice.getName());
for (AbstractBluetoothRFCOMMDevice device : SUPPORTED_BLUETOOTH_COM_DEVICES) {
if (device.isTypeCompatible(aDevice) && device.isNameSupported(aDevice.getName())) {
return device;
}
}
for (AbstractBluetoothLEDevice device : SUPPORTED_BLUETOOTH_LE_DEVICES) {
if (device.isTypeCompatible(aDevice) && device.isNameSupported(aDevice.getName())) {
for (AbstractBluetoothDevice device : SUPPORTED_BLUETOOTH_DEVICES) {
if (device.matchesDeviceFilter(filter) && device.isTypeCompatible(aDevice) && device.isNameSupported(aDevice.getName())) {
return device;
}
}
Expand All @@ -364,21 +363,21 @@ public static List<AbstractBluetoothDevice> getSupportedDevices() {
return devicesByDescription;
}

public static boolean isSupported(BluetoothDevice aDevice) {
return aDevice != null && getSupportedDevice(aDevice) != null;
public static boolean isSupported(BluetoothDevice aDevice, AbstractBluetoothDevice filter) {
return aDevice != null && getSupportedDevice(aDevice, filter) != null;
}

public static Set<Pair<String, String>> getPairedCompatibleDevices() {
public static Set<Pair<String, String>> getPairedCompatibleDevices(AbstractBluetoothDevice filter) {
Set<Pair<String, String>> result = new HashSet<>();
Set<BluetoothDevice> devices = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
for (BluetoothDevice d : devices) {
if (isSupported(d)) {
if (isSupported(d, filter)) {
result.add(new Pair<>(d.getName(), d.getAddress()));
}
}
if (mLastLEDevice != null) {
Pair<String, String> lastLeDevice = new Pair<>(mLastLEDevice.getName(), mLastLEDevice.getAddress());
if (!devices.contains(lastLeDevice)) {
if (getSupportedDevice(mLastLEDevice, filter) != null && !devices.contains(lastLeDevice)) {
result.add(lastLeDevice);
}
}
Expand Down Expand Up @@ -456,12 +455,17 @@ public static void unregisterListeners(BTActivity btActivity) {


@TargetApi(18)
public static void discoverBluetoothLEDevices() {
public static void discoverBluetoothLEDevices(AbstractBluetoothDevice aDeviceFilter) {

if (SDK_INT >= LOLLIPOP) {
leCallbackLollipop = startLEScanCallbackLollipop();
} else {
leCallback = startLEScanCallback();
// only if supported by the required device
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (aDeviceFilter == null || aDeviceFilter.getClass().isAssignableFrom(AbstractBluetoothLEDevice.class)) {
if (SDK_INT >= LOLLIPOP) {
leCallbackLollipop = startLEScanCallbackLollipop(aDeviceFilter);
} else {
leCallback = startLEScanCallback(aDeviceFilter);
}
}
}
}

Expand All @@ -481,28 +485,28 @@ public static void stopDiscoverBluetoothLEDevices() {
}

@TargetApi(JELLY_BEAN_MR2)
public static BluetoothAdapter.LeScanCallback startLEScanCallback() {
public static BluetoothAdapter.LeScanCallback startLEScanCallback(AbstractBluetoothDevice aDeviceFilter) {

Log.i(LOG_TAG_BT, "Start discovery for Bluetooth LE devices");
BluetoothAdapter.LeScanCallback callback = (device, rssi, scanRecord) -> handleDeviceDiscovered(device, rssi);
BluetoothAdapter.LeScanCallback callback = (device, rssi, scanRecord) -> handleDeviceDiscovered(device, aDeviceFilter, rssi);
BluetoothAdapter.getDefaultAdapter().startLeScan(leCallback);
return callback;
}

@TargetApi(LOLLIPOP)
private static ScanCallback startLEScanCallbackLollipop() {
private static ScanCallback startLEScanCallbackLollipop(AbstractBluetoothDevice aDeviceFilter) {
Log.i(LOG_TAG_BT, "Start discovery for Lollipop+ Bluetooth LE devices");

ScanCallback callback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
handleDeviceDiscovered(result.getDevice(), result.getRssi());
handleDeviceDiscovered(result.getDevice(), aDeviceFilter, result.getRssi());
}

@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult result : results) {
handleDeviceDiscovered(result.getDevice(), result.getRssi());
handleDeviceDiscovered(result.getDevice(), aDeviceFilter, result.getRssi());
}
}

Expand All @@ -522,9 +526,9 @@ public void onScanFailed(int errorCode) {
return callback;
}

private static void handleDeviceDiscovered(BluetoothDevice device, int rssi) {
private static void handleDeviceDiscovered(BluetoothDevice device, AbstractBluetoothDevice aDeviceFilter, int rssi) {
Log.d(LOG_TAG_BT, "Discovered: " + device.getName());
AbstractBluetoothDevice deviceParent = BluetoothService.getSupportedDevice(device);
AbstractBluetoothDevice deviceParent = BluetoothService.getSupportedDevice(device, aDeviceFilter);

if (deviceParent != null && deviceParent instanceof AbstractBluetoothLEDevice) {
Log.i(LOG_TAG_BT, "Discovered LE device " + rssi + " : " + device.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.astoev.cave.survey.R;
import com.astoev.cave.survey.activity.UIUtilities;
import com.astoev.cave.survey.exception.DataException;
import com.astoev.cave.survey.service.bluetooth.device.AbstractBluetoothDevice;
import com.astoev.cave.survey.service.bluetooth.device.comm.AbstractBluetoothRFCOMMDevice;
import com.astoev.cave.survey.util.ByteUtils;
import com.astoev.cave.survey.util.ConfigUtil;
Expand All @@ -42,6 +43,7 @@ public class CommDeviceCommunicationThread extends Thread {
private static final int KEEP_ALIVE_INTERVAL = 1000 * 60; // 1 minute

private BluetoothDevice mDevice;
private AbstractBluetoothDevice mDeviceFilter;
private AbstractBluetoothRFCOMMDevice mDeviceSpec;
private List<Constants.MeasureTypes> mMeasureTypes = null;
private List<Constants.Measures> mTargets = null;
Expand Down Expand Up @@ -73,7 +75,7 @@ private BluetoothSocket createSocketApi10Plus() throws IOException {
public void onReceive(Context context, Intent intent) {
try {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (!BluetoothService.isSupported(device)) {
if (!BluetoothService.isSupported(device, mDeviceFilter)) {
// ignore other devices
Log.i(Constants.LOG_TAG_BT, "Bonded unsupported device");
return;
Expand All @@ -89,7 +91,7 @@ public void onReceive(Context context, Intent intent) {
Log.i(Constants.LOG_TAG_BT, "Paired with " + device.getName());
mPaired = true;
mDevice = device;
mDeviceSpec = (AbstractBluetoothRFCOMMDevice) BluetoothService.getSupportedDevice(device);
mDeviceSpec = (AbstractBluetoothRFCOMMDevice) BluetoothService.getSupportedDevice(device, mDeviceFilter);

TextView status = ConfigUtil.getContext().findViewById(R.id.bt_status);
status.setText(BluetoothService.getCurrDeviceStatusLabel(ConfigUtil.getContext()));
Expand All @@ -111,7 +113,7 @@ public void onReceive(Context context, Intent intent) {
}

BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (!BluetoothService.isSupported(device)) {
if (!BluetoothService.isSupported(device, mDeviceFilter)) {
// ignore other devices
Log.i(Constants.LOG_TAG_BT, "Ignore disconnect, device not supported");
return;
Expand Down Expand Up @@ -390,4 +392,8 @@ public void awaitMeasures(List<Constants.MeasureTypes> aMeasureTypes, List<Const
public boolean ismPaired() {
return mPaired;
}

public void setDeviceFilter(AbstractBluetoothDevice aDeviceFilter) {
mDeviceFilter = aDeviceFilter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ public boolean isTypeCompatible(BluetoothDevice device) {
public int compareTo(Object another) {
return getDescription().compareTo(((AbstractBluetoothDevice) another).getDescription());
}

public boolean matchesDeviceFilter(AbstractBluetoothDevice filter) {
return filter == null || filter.getClass().equals(getClass());
}
}
Loading

0 comments on commit 4ed7a38

Please sign in to comment.