diff options
author | Trygve Laugstøl <trygvis@inamo.no> | 2015-01-12 22:47:57 +0100 |
---|---|---|
committer | Trygve Laugstøl <trygvis@inamo.no> | 2015-01-16 22:48:11 +0100 |
commit | 5f880d3816526157c5d411896707b971af48212b (patch) | |
tree | a9315b7853c2bfc55944537d5890515ce0618746 | |
parent | 17a1f7227c8c3872fce7bbcc2f5cd46540f9ac52 (diff) | |
download | io.trygvis.soilmoisture-android-5f880d3816526157c5d411896707b971af48212b.tar.gz io.trygvis.soilmoisture-android-5f880d3816526157c5d411896707b971af48212b.tar.bz2 io.trygvis.soilmoisture-android-5f880d3816526157c5d411896707b971af48212b.tar.xz io.trygvis.soilmoisture-android-5f880d3816526157c5d411896707b971af48212b.zip |
o Major refactoring of the BT promise.
7 files changed, 214 insertions, 279 deletions
diff --git a/app/app.iml b/app/app.iml deleted file mode 100644 index 7d4711d..0000000 --- a/app/app.iml +++ /dev/null @@ -1,117 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4"> - <component name="FacetManager"> - <facet type="android-gradle" name="Android-Gradle"> - <configuration> - <option name="GRADLE_PROJECT_PATH" value=":app" /> - </configuration> - </facet> - <facet type="android" name="Android"> - <configuration> - <option name="SELECTED_BUILD_VARIANT" value="level18Debug" /> - <option name="ASSEMBLE_TASK_NAME" value="assembleLevel18Debug" /> - <option name="COMPILE_JAVA_TASK_NAME" value="compileLevel18DebugSources" /> - <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleLevel18DebugTest" /> - <option name="SOURCE_GEN_TASK_NAME" value="generateLevel18DebugSources" /> - <option name="TEST_SOURCE_GEN_TASK_NAME" value="generateLevel18DebugTestSources" /> - <option name="ALLOW_USER_CONFIGURATION" value="false" /> - <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> - <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> - <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" /> - <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" /> - </configuration> - </facet> - </component> - <component name="NewModuleRootManager" inherit-compiler-output="false"> - <output url="file://$MODULE_DIR$/build/intermediates/classes/level18/debug" /> - <exclude-output /> - <content url="file://$MODULE_DIR$"> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/level18/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/level18/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/level18/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/level18/debug" isTestSource="false" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/level18/debug" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/level18/debug" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18Debug/res" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18Debug/resources" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18Debug/assets" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18Debug/aidl" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18Debug/java" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18Debug/jni" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18Debug/rs" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/test/level18/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/test/level18/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/test/level18/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/test/level18/debug" isTestSource="true" generated="true" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/level18/debug" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/test/level18/debug" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18/res" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18/resources" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18/assets" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18/aidl" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18/java" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18/jni" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/level18/rs" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTestLevel18/res" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTestLevel18/resources" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTestLevel18/assets" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTestLevel18/aidl" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTestLevel18/java" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTestLevel18/jni" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTestLevel18/rs" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" /> - <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" /> - <excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> - <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> - <excludeFolder url="file://$MODULE_DIR$/build/outputs" /> - <excludeFolder url="file://$MODULE_DIR$/build/retrolambda" /> - <excludeFolder url="file://$MODULE_DIR$/build/tmp" /> - </content> - <orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" /> - <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="library" exported="" name="answers-1.0.2" level="project" /> - <orderEntry type="library" exported="" name="flyway-core-3.1" level="project" /> - <orderEntry type="library" exported="" name="fabric-1.0.2" level="project" /> - <orderEntry type="library" exported="" name="sqldroid-1.0.3" level="project" /> - <orderEntry type="library" exported="" name="crashlytics-2.1.0" level="project" /> - <orderEntry type="library" exported="" name="beta-1.0.2" level="project" /> - </component> -</module> - diff --git a/app/src/main/java/io/trygvis/android/bt/BtCallback.java b/app/src/main/java/io/trygvis/android/bt/BtCallback.java index 71f7d56..7ff8733 100644 --- a/app/src/main/java/io/trygvis/android/bt/BtCallback.java +++ b/app/src/main/java/io/trygvis/android/bt/BtCallback.java @@ -62,4 +62,12 @@ public class BtCallback { public void onFinally() { throw new NotOverriddenException(); } + + @Override + public String toString() { + return "BtCallback{" + + "name='" + name + '\'' + + ", stopOnFailure=" + stopOnFailure + + '}'; + } } diff --git a/app/src/main/java/io/trygvis/android/bt/BtDevice.java b/app/src/main/java/io/trygvis/android/bt/BtDevice.java index d8dfefc..2a4a5d8 100644 --- a/app/src/main/java/io/trygvis/android/bt/BtDevice.java +++ b/app/src/main/java/io/trygvis/android/bt/BtDevice.java @@ -3,11 +3,16 @@ package io.trygvis.android.bt; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; import android.database.sqlite.SQLiteDatabase; import android.util.Log; import java.util.Date; +import static io.trygvis.android.bt.BtPromise.PromiseResult.detour; +import static io.trygvis.android.bt.BtPromise.PromiseResult.stop; + public class BtDevice<A extends BtDevice.BtDeviceWrapper<A>> { private final static String TAG = BtDevice.class.getSimpleName(); @@ -23,6 +28,7 @@ public class BtDevice<A extends BtDevice.BtDeviceWrapper<A>> { private final Date firstSeen; private Date lastSeen; private boolean connected; + private final WrappingBluetoothGattCallback wrappingCallback = new WrappingBluetoothGattCallback(); public static interface BtDeviceWrapper<A extends BtDevice.BtDeviceWrapper<A>> { BtDevice<A> getBtDevice(); @@ -83,27 +89,69 @@ public class BtDevice<A extends BtDevice.BtDeviceWrapper<A>> { this.lastSeen = lastSeen; } - public synchronized boolean connect(BtPromise executor) { - Log.i(TAG, "connect(), address=" + bluetoothDevice.getAddress()); - BluetoothGattCallback callback = executor.asCallback(bluetoothDevice.getAddress()); - gatt = bluetoothDevice.connectGatt(btService, false, new WrappingBluetoothGattCallback(callback) { - @Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - BtDevice.this.connected = newState == BluetoothGatt.STATE_CONNECTED; - - super.onConnectionStateChange(gatt, status, newState); - } - }); - return true; - } +// public synchronized boolean connect(BtPromise executor) { +// Log.i(TAG, "connect(), address=" + bluetoothDevice.getAddress()); +// BluetoothGattCallback callback = executor.asCallback(bluetoothDevice.getAddress()); +// gatt = bluetoothDevice.connectGatt(btService, false, new WrappingBluetoothGattCallback(callback) { +// @Override +// public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { +// BtDevice.this.connected = newState == BluetoothGatt.STATE_CONNECTED; +// +// super.onConnectionStateChange(gatt, status, newState); +// } +// }); +// return true; +// } + + private BluetoothGattCallback callback; + + public synchronized void withConnection(BtPromise promise) { + if (callback != null) { + throw new RuntimeException("The current callback is not done."); + } - public synchronized void disconnect() { - if (gatt != null) { - gatt.disconnect(); - gatt = null; + Log.i(TAG, "withConnection(), address=" + bluetoothDevice.getAddress() + ", connected: " + (gatt != null)); + + if (gatt == null) { + callback = new BtPromise(). + ignoreFailureForNext(). + onConnectionStateChange((gatt, status, newState) -> { + Log.i(TAG, "defaultConnectCallback: status=" + status + ", newState=" + newState); + String address = gatt.getDevice().getAddress(); + //noinspection SimplifiableIfStatement + if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) { + Log.i(TAG, "Connected to " + address); + return detour(promise); + } else { + Log.i(TAG, "Could not connect to " + address + ", trying again"); + + return detour(new BtPromise().onConnectionStateChange((gatt2, status2, newState2) -> { + if (status2 == BluetoothGatt.GATT_SUCCESS && newState2 == BluetoothGatt.STATE_CONNECTED) { + Log.i(TAG, "Connected to " + address); + return detour(promise); + } + + Log.i(TAG, "Could still not connect to " + address + ", failing."); + + return stop(); + })); + } + }). + asCallback(bluetoothDevice.getAddress()); + } else { + callback = promise.asCallback(bluetoothDevice.getAddress()); } + + gatt = bluetoothDevice.connectGatt(btService, false, wrappingCallback); } +// public synchronized void disconnect() { +// if (gatt != null) { +// gatt.disconnect(); +// gatt = null; +// } +// } + public boolean connected() { return connected; } @@ -131,4 +179,72 @@ public class BtDevice<A extends BtDevice.BtDeviceWrapper<A>> { public int hashCode() { return getAddress().hashCode(); } + + private class WrappingBluetoothGattCallback extends BluetoothGattCallback { + + @Override + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + BtDevice.this.connected = newState == BluetoothGatt.STATE_CONNECTED; + + if (callback != null) { + callback.onConnectionStateChange(gatt, status, newState); + } + } + + @Override + public void onServicesDiscovered(BluetoothGatt gatt, int status) { + if (callback != null) { + callback.onServicesDiscovered(gatt, status); + } + } + + @Override + public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + if (callback != null) { + callback.onCharacteristicRead(gatt, characteristic, status); + } + } + + @Override + public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + if (callback != null) { + callback.onCharacteristicWrite(gatt, characteristic, status); + } + } + + @Override + public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + if (callback != null) { + callback.onCharacteristicChanged(gatt, characteristic); + } + } + + @Override + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + if (callback != null) { + callback.onDescriptorRead(gatt, descriptor, status); + } + } + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + if (callback != null) { + callback.onDescriptorWrite(gatt, descriptor, status); + } + } + + @Override + public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { + if (callback != null) { + callback.onReliableWriteCompleted(gatt, status); + } + } + + @Override + public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { + if (callback != null) { + callback.onReadRemoteRssi(gatt, rssi, status); + } + } + } } diff --git a/app/src/main/java/io/trygvis/android/bt/BtPromise.java b/app/src/main/java/io/trygvis/android/bt/BtPromise.java index 6af62c0..d4b3b67 100644 --- a/app/src/main/java/io/trygvis/android/bt/BtPromise.java +++ b/app/src/main/java/io/trygvis/android/bt/BtPromise.java @@ -6,12 +6,9 @@ import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.util.Log; -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.ListIterator; -import java.util.Queue; import io.trygvis.android.F2; import io.trygvis.android.F3; @@ -32,8 +29,8 @@ import static io.trygvis.android.bt.BtPromise.EventType.onServicesDiscovered; public class BtPromise { private final static String TAG = BtPromise.class.getSimpleName(); private final List<BtCallback> actionQ = new ArrayList<>(); - private final Queue<BtCallback> failureQ = new ArrayDeque<>(); - private final Queue<BtCallback> finallyQ = new ArrayDeque<>(); + private final List<BtCallback> failureQ = new ArrayList<>(); + private final List<BtCallback> finallyQ = new ArrayList<>(); private static final PromiseResult waitForNextEvent = new WaitForNextEvent(); private static final PromiseResult stop = new Stop(); @@ -84,7 +81,7 @@ public class BtPromise { } private boolean stopOnFailure() { - if(stopOnFailure != null) { + if (stopOnFailure != null) { boolean b = stopOnFailure; stopOnFailure = null; return b; @@ -96,12 +93,12 @@ public class BtPromise { stopOnFailure = true; return this; } - + public synchronized BtPromise onConnectionStateChange(F3<BluetoothGatt, Integer, Integer, PromiseResult> callback) { actionQ.add(new BtCallback(stopOnFailure(), "onConnectionStateChange") { @Override public PromiseResult onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - return callback.apply(gatt, status,newState); + return callback.apply(gatt, status, newState); } }); return this; @@ -296,17 +293,17 @@ public class BtPromise { private final String address; private List<BtCallback> actionQ; - private ListIterator<BtCallback> it; - private ArrayDeque<BtCallback> failureQ; - ArrayDeque<BtCallback> finallyQ; + private int currentAction = 0; + private List<BtCallback> failureQ; + private List<BtCallback> finallyQ; private List<String> events = new ArrayList<>(); - private BtBluetoothGattCallback(String address, List<BtCallback> actionQ, Queue<BtCallback> failureQ, Queue<BtCallback> finallyQ) { + private BtBluetoothGattCallback(String address, List<BtCallback> actionQ, + List<BtCallback> failureQ, List<BtCallback> finallyQ) { this.address = address; this.actionQ = new ArrayList<>(actionQ); - this.failureQ = new ArrayDeque<>(failureQ); - this.finallyQ = new ArrayDeque<>(finallyQ); - this.it = actionQ.listIterator(); + this.failureQ = new ArrayList<>(failureQ); + this.finallyQ = new ArrayList<>(finallyQ); } void onEvent(EventType key, String values, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, @@ -316,22 +313,28 @@ public class BtPromise { Log.i(TAG, "event: " + key + "(" + values + "), success=" + success); - if (!success) { - doFailure(); - return; - } - BtCallback btCallback; synchronized (this) { - if (!it.hasNext()) { - Log.d(TAG, "All Bluetooth actions are done"); + if (!hasNext()) { + Log.d(TAG, "All Bluetooth actions are done, no handler for last event."); + showEvents(); doFinally(); return; } - btCallback = it.next(); - Log.i(TAG, "Executing bt action: " + btCallback.name); + btCallback = actionQ.get(currentAction++); + + if (!success) { + if (btCallback.stopOnFailure) { + doFailure(); + return; + } else { + Log.i(TAG, "Last status was a failure, but the callback still want it."); + } + } + + Log.i(TAG, "Graceful sleep" + btCallback.name); try { Thread.sleep(1000); } catch (InterruptedException e) { @@ -340,6 +343,7 @@ public class BtPromise { } try { + Log.i(TAG, "Executing bt action: " + btCallback.name); PromiseResult result = callCallback(key, gatt, characteristic, descriptor, status, newState, btCallback, value); @@ -347,20 +351,23 @@ public class BtPromise { Log.i(TAG, "The chain want to stop."); doFinally(); } else if (result instanceof Detour) { - Log.i(TAG, "Adding detour"); - BtPromise promise = ((Detour) result).promise; - events.add("detour " + promise.actionQ.size()); - if (!promise.failureQ.isEmpty()) { - Log.i(TAG, "Ignoring " + promise.failureQ.size() + " items from the failure Q"); - } - if (!promise.finallyQ.isEmpty()) { - Log.i(TAG, "Ignoring " + promise.finallyQ.size() + " items from the finally Q"); + BtPromise detour = ((Detour) result).promise; + Log.i(TAG, "Adding detour with " + detour.actionQ.size() + " actions."); + events.add("detour, action size=" + detour.actionQ.size() + ", failure size=" + + detour.failureQ.size() + ", finally size=" + detour.finallyQ.size()); + + Log.i(TAG, "hasNext(): " + hasNext()); + Log.i(TAG, "currentAction: " + currentAction); + if (hasNext()) { + Log.i(TAG, "next action: " + actionQ.get(currentAction).name); } - synchronized (this) { - for (BtCallback cb : promise.actionQ) { - it.add(cb); - } + actionQ.addAll(currentAction, detour.actionQ); + failureQ.addAll(detour.failureQ); + finallyQ.addAll(detour.finallyQ); + Log.i(TAG, "hasNext(): " + hasNext()); + if (hasNext()) { + Log.i(TAG, "next action: " + actionQ.get(currentAction).name); } } else if (result instanceof ContinueDirectly) { value = ((ContinueDirectly) result).value; @@ -369,8 +376,9 @@ public class BtPromise { return; } - if (!it.hasNext()) { + if (!hasNext()) { Log.i(TAG, "The queue is empty"); + showEvents(); } } catch (NotOverriddenException e) { Log.w(TAG, "Unexpected callback by listener: " + key); @@ -378,33 +386,37 @@ public class BtPromise { } } + private boolean hasNext() { + return currentAction < actionQ.size(); + } + private void doFailure() { + showEvents(); + + Log.w(TAG, "Executing " + failureQ.size() + " failure handlers"); + + for (BtCallback callback : failureQ) { + callCallback(onFailure, null, null, null, 0, 0, callback, null); + } + + doFinally(); + } + + private void showEvents() { StringBuilder msg = new StringBuilder(); msg.append("Address: ").append(address).append("\n"); - msg.append("Expected events: \n"); + msg.append("Event handlers: \n"); for (BtCallback cb : actionQ) { msg.append("- ").append(cb.name).append("\n"); } - msg.append("Actual events: \n"); + msg.append("Events received: \n"); for (String event : events) { msg.append("- ").append(event).append("\n"); } Log.w(TAG, msg.toString()); - - Log.w(TAG, "Executing " + failureQ.size() + " failure handlers"); - - for (BtCallback callback = failureQ.poll(); callback != null; callback = failureQ.poll()) { - try { - callCallback(onFailure, null, null, null, 0, 0, callback, null); - } catch (NotOverriddenException e) { - return; - } - } - - doFinally(); } private void doFinally() { @@ -412,7 +424,7 @@ public class BtPromise { Log.w(TAG, "Executing " + finallyQ.size() + " finally handlers"); - for (BtCallback callback = finallyQ.poll(); callback != null; callback = finallyQ.poll()) { + for (BtCallback callback : finallyQ) { try { callCallback(onFinally, null, null, null, 0, 0, callback, null); } catch (NotOverriddenException e) { diff --git a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java index cc7d484..718a1cd 100644 --- a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java +++ b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java @@ -185,6 +185,11 @@ public class DefaultBtService<A extends BtDevice.BtDeviceWrapper<A>> extends Ser private BluetoothAdapter.LeScanCallback leScanCallback = (device, rssi, scanRecord) -> { BtScanResult scanResult = new BtScanResult(scanRecord); + if (!device.getAddress().startsWith("FB:")) { + Log.w(TAG, "filtering out device: " + device.getAddress()); + return; + } + register(device, rssi, scanResult); }; diff --git a/app/src/main/java/io/trygvis/android/bt/WrappingBluetoothGattCallback.java b/app/src/main/java/io/trygvis/android/bt/WrappingBluetoothGattCallback.java deleted file mode 100644 index 8d790d1..0000000 --- a/app/src/main/java/io/trygvis/android/bt/WrappingBluetoothGattCallback.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.trygvis.android.bt; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; - -class WrappingBluetoothGattCallback extends BluetoothGattCallback { - - private final BluetoothGattCallback wrapped; - - public WrappingBluetoothGattCallback(BluetoothGattCallback wrapped) { - this.wrapped = wrapped; - } - - @Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - wrapped.onConnectionStateChange(gatt, status, newState); - } - - @Override - public void onServicesDiscovered(BluetoothGatt gatt, int status) { - wrapped.onServicesDiscovered(gatt, status); - } - - @Override - public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { - wrapped.onCharacteristicRead(gatt, characteristic, status); - } - - @Override - public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { - wrapped.onCharacteristicWrite(gatt, characteristic, status); - } - - @Override - public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - wrapped.onCharacteristicChanged(gatt, characteristic); - } - - @Override - public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - wrapped.onDescriptorRead(gatt, descriptor, status); - } - - @Override - public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { - wrapped.onDescriptorWrite(gatt, descriptor, status); - } - - @Override - public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { - wrapped.onReliableWriteCompleted(gatt, status); - } - - @Override - public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { - wrapped.onReadRemoteRssi(gatt, rssi, status); - } -} diff --git a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java index 3ff6e66..174c245 100644 --- a/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java +++ b/app/src/main/java/io/trygvis/soilmoisture/DefaultSoilMoistureService.java @@ -30,8 +30,6 @@ import io.trygvis.android.bt.BtService; import io.trygvis.android.bt.DefaultBtService; import io.trygvis.bluetooth.TrygvisIoUuids; -import static io.trygvis.android.bt.BtPromise.PromiseResult.continueDirectly; -import static io.trygvis.android.bt.BtPromise.PromiseResult.detour; import static io.trygvis.android.bt.BtPromise.PromiseResult.stop; import static io.trygvis.android.bt.BtPromise.PromiseResult.waitForNextEvent; import static io.trygvis.android.bt.BtService.BtServiceListenerBroadcastReceiver; @@ -117,8 +115,6 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS if (!smDevice.isProbed()) { Log.i(TAG, "Probing " + address + ", name=" + btDevice.getName()); BtPromise executor = new BtPromise(). - ignoreFailureForNext(). - onConnectionStateChange(DefaultSoilMoistureService::defaultConnectCallback). onDirect(v -> { BluetoothGatt gatt = (BluetoothGatt) v; return gatt.discoverServices() ? waitForNextEvent() : stop(); @@ -162,15 +158,14 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS return stop(); }). onFinally(() -> { - btDevice.disconnect(); +// btDevice.disconnect(); if (smDevice.getIsUseful() == null) { smDevice.setIsUseful(false); } - }); - btDevice.connect(executor); + btDevice.withConnection(executor); } } }; @@ -208,29 +203,6 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS }); } - public static BtPromise.PromiseResult defaultConnectCallback(BluetoothGatt gatt, int status, Integer newState) { - Log.i(TAG, "defaultConnectCallback: status=" + status + ", newState=" + newState); - String address = gatt.getDevice().getAddress(); - //noinspection SimplifiableIfStatement - if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) { - Log.i(TAG, "Connected to " + address); - return continueDirectly(gatt); - } else { - Log.i(TAG, "Disconnected from " + address + ", trying again"); - - return detour(new BtPromise().onConnectionStateChange((gatt2, status2, newState2) -> { - if (newState2 == BluetoothGatt.STATE_CONNECTED) { - Log.i(TAG, "Connected to " + address); - return continueDirectly(gatt); - } - - Log.i(TAG, "Could still not connect to " + address + ", failing."); - - return stop(); - })); - } - } - // ----------------------------------------------------------------------- // SmDevicesManager Implementation // ----------------------------------------------------------------------- @@ -300,7 +272,6 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS void readCurrentValue(SmSensor sensor) { BtPromise promise = new BtPromise(). - onConnectionStateChange(DefaultSoilMoistureService::defaultConnectCallback). onDirect(v -> { BluetoothGatt gatt = (BluetoothGatt) v; return gatt.discoverServices() ? waitForNextEvent() : stop(); @@ -327,14 +298,14 @@ public class DefaultSoilMoistureService extends Service implements SoilMoistureS handleNewSensorValueReady(sensor, getSensorCountRes.value); - gatt.disconnect(); +// gatt.disconnect(); return stop(); }). onFinally(() -> { }); - sensor.getDevice().getBtDevice().connect(promise); + sensor.getDevice().getBtDevice().withConnection(promise); } // ----------------------------------------------------------------------- |