diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
index cfa192d2..d7bde89f 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/ControlCenter.java
@@ -20,6 +20,9 @@ import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -30,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst;
public class ControlCenter extends Activity {
+ private static final Logger LOG = LoggerFactory.getLogger(ControlCenter.class);
public static final String ACTION_QUIT
= "nodomain.freeyourgadget.gadgetbride.controlcenter.action.quit";
@@ -57,7 +61,7 @@ public class ControlCenter extends Activity {
refreshPairedDevices();
break;
case GBDevice.ACTION_DEVICE_CHANGED:
- GBDevice dev = intent.getParcelableExtra("device");
+ GBDevice dev = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
if (dev.getAddress() != null) {
int index = deviceList.indexOf(dev); // search by address
if (index >= 0) {
@@ -68,7 +72,8 @@ public class ControlCenter extends Activity {
}
refreshPairedDevices();
- if (dev.isConnected() && dev.getFirmwareVersion() == null) {
+ if (dev.isConnected() && dev.getFirmwareVersion() == null && !dev.isInitializing()) {
+ LOG.info("device connected, requesting more info");
requestDeviceInfo();
}
break;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java
index 42cafaa8..9ddbdb28 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBDevice.java
@@ -104,6 +104,10 @@ public class GBDevice implements Parcelable {
return mState.ordinal() >= State.CONNECTED.ordinal();
}
+ public boolean isInitializing() {
+ return mState == State.INITIALIZING;
+ }
+
public boolean isInitialized() {
return mState.ordinal() >= State.INITIALIZED.ordinal();
}
@@ -118,7 +122,9 @@ public class GBDevice implements Parcelable {
public void setState(State state) {
mState = state;
- unsetDynamicState();
+ if (state.ordinal() <= State.CONNECTED.ordinal()) {
+ unsetDynamicState();
+ }
}
private void unsetDynamicState() {
@@ -136,6 +142,8 @@ public class GBDevice implements Parcelable {
return GBApplication.getContext().getString(R.string.connecting);
case CONNECTED:
return GBApplication.getContext().getString(R.string.connected);
+ case INITIALIZING:
+ return GBApplication.getContext().getString(R.string.initializing);
case INITIALIZED:
return GBApplication.getContext().getString(R.string.initialized);
}
@@ -238,6 +246,7 @@ public class GBDevice implements Parcelable {
NOT_CONNECTED,
CONNECTING,
CONNECTED,
+ INITIALIZING,
INITIALIZED
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java
index 9764dfe7..5ad8b139 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java
@@ -77,6 +77,7 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
if (!isInitialized()) {
// first, add a transaction that performs device initialization
TransactionBuilder builder = createTransactionBuilder("Initialize device");
+ builder.add(new CheckInitializedAction(gbDevice));
initializeDevice(builder).queue(getQueue());
}
return createTransactionBuilder(taskName);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java
index 5de3cffd..c5126024 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java
@@ -87,15 +87,14 @@ public final class BtLEQueue {
}
}
} catch (InterruptedException ignored) {
- mWaitForActionResultLatch = null;
mConnectionLatch = null;
LOG.debug("Thread interrupted");
} catch (Throwable ex) {
LOG.error("Queue Dispatch Thread died: " + ex.getMessage());
mCrashed = true;
- mWaitForActionResultLatch = null;
mConnectionLatch = null;
} finally {
+ mWaitForActionResultLatch = null;
mWaitCharacteristic = null;
}
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/CheckInitializedAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/CheckInitializedAction.java
new file mode 100644
index 00000000..eafdf750
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/CheckInitializedAction.java
@@ -0,0 +1,37 @@
+package nodomain.freeyourgadget.gadgetbridge.btle;
+
+import android.bluetooth.BluetoothGatt;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import nodomain.freeyourgadget.gadgetbridge.GBDevice;
+
+/**
+ * A special action that is executed at the very front of the initialization
+ * sequence (transaction). It will abort the entire initialization sequence
+ * by returning false, when the device is already initialized.
+ */
+public class CheckInitializedAction extends BtLEAction {
+ private static final Logger LOG = LoggerFactory.getLogger(CheckInitializedAction.class);
+
+ private final GBDevice device;
+
+ public CheckInitializedAction(GBDevice gbDevice) {
+ device = gbDevice;
+ }
+
+ @Override
+ public boolean run(BluetoothGatt gatt) {
+ boolean continueWithOtherInitActions = !device.isInitialized();
+ if (!continueWithOtherInitActions) {
+ LOG.info("Aborting device initialization, because already initialized: " + device);
+ }
+ return continueWithOtherInitActions;
+ }
+
+ @Override
+ public boolean expectsResult() {
+ return false;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
index cb2f3bea..8847225e 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java
@@ -55,15 +55,27 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
@Override
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
+ builder.add(new SetDeviceStateAction(getDevice(), State.INITIALIZING, getContext()));
pair(builder)
.sendUserInfo(builder)
.enableNotifications(builder, true)
.setCurrentTime(builder)
- .requestBatteryInfo(builder);
+ .requestBatteryInfo(builder)
+ .setInitialized(builder);
return builder;
}
+ /**
+ * Last action of initialization sequence. Sets the device to initialized.
+ * It is only invoked if all other actions were successfully run, so the device
+ * must be initialized, then.
+ * @param builder
+ */
+ private void setInitialized(TransactionBuilder builder) {
+ builder.add(new SetDeviceStateAction(getDevice(), State.INITIALIZED, getContext()));
+ }
+
// TODO: tear down the notifications on quit
private MiBandSupport enableNotifications(TransactionBuilder builder, boolean enable) {
builder.notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_NOTIFICATION), enable)
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/SetDeviceStateAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/SetDeviceStateAction.java
new file mode 100644
index 00000000..673e2a46
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/SetDeviceStateAction.java
@@ -0,0 +1,35 @@
+package nodomain.freeyourgadget.gadgetbridge.miband;
+
+import android.bluetooth.BluetoothGatt;
+import android.content.Context;
+
+import nodomain.freeyourgadget.gadgetbridge.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.btle.BtLEAction;
+
+public class SetDeviceStateAction extends BtLEAction {
+ private final GBDevice device;
+ private final GBDevice.State deviceState;
+ private final Context context;
+
+ public SetDeviceStateAction(GBDevice device, GBDevice.State deviceState, Context context) {
+ this.device = device;
+ this.deviceState = deviceState;
+ this.context = context;
+ }
+
+ @Override
+ public boolean run(BluetoothGatt gatt) {
+ device.setState(deviceState);
+ device.sendDeviceUpdateIntent(getContext());
+ return true;
+ }
+
+ @Override
+ public boolean expectsResult() {
+ return false;
+ }
+
+ public Context getContext() {
+ return context;
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d297f632..52d30e88 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -104,5 +104,6 @@
Sleep Monitor
LogToFile
Write Log Files (needs restart)
+ initializing