aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/io/trygvis/android
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2015-01-12 22:47:57 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2015-01-16 22:48:11 +0100
commit5f880d3816526157c5d411896707b971af48212b (patch)
treea9315b7853c2bfc55944537d5890515ce0618746 /app/src/main/java/io/trygvis/android
parent17a1f7227c8c3872fce7bbcc2f5cd46540f9ac52 (diff)
downloadio.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.
Diffstat (limited to 'app/src/main/java/io/trygvis/android')
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtCallback.java8
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtDevice.java150
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtPromise.java116
-rw-r--r--app/src/main/java/io/trygvis/android/bt/DefaultBtService.java5
-rw-r--r--app/src/main/java/io/trygvis/android/bt/WrappingBluetoothGattCallback.java60
5 files changed, 210 insertions, 129 deletions
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);
- }
-}