Some fixes regarding device initialization, should avoid disconnects

Avoid repeated initializations and device info requests. Fix unsetting
of dynamic state (e.g. battery info) when initialized.
This commit is contained in:
cpfeiffer 2015-05-28 00:26:41 +02:00
parent f60903699e
commit 7f89f4bb57
8 changed files with 105 additions and 6 deletions

View File

@ -20,6 +20,9 @@ import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -30,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst;
public class ControlCenter extends Activity { public class ControlCenter extends Activity {
private static final Logger LOG = LoggerFactory.getLogger(ControlCenter.class);
public static final String ACTION_QUIT public static final String ACTION_QUIT
= "nodomain.freeyourgadget.gadgetbride.controlcenter.action.quit"; = "nodomain.freeyourgadget.gadgetbride.controlcenter.action.quit";
@ -57,7 +61,7 @@ public class ControlCenter extends Activity {
refreshPairedDevices(); refreshPairedDevices();
break; break;
case GBDevice.ACTION_DEVICE_CHANGED: case GBDevice.ACTION_DEVICE_CHANGED:
GBDevice dev = intent.getParcelableExtra("device"); GBDevice dev = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
if (dev.getAddress() != null) { if (dev.getAddress() != null) {
int index = deviceList.indexOf(dev); // search by address int index = deviceList.indexOf(dev); // search by address
if (index >= 0) { if (index >= 0) {
@ -68,7 +72,8 @@ public class ControlCenter extends Activity {
} }
refreshPairedDevices(); refreshPairedDevices();
if (dev.isConnected() && dev.getFirmwareVersion() == null) { if (dev.isConnected() && dev.getFirmwareVersion() == null && !dev.isInitializing()) {
LOG.info("device connected, requesting more info");
requestDeviceInfo(); requestDeviceInfo();
} }
break; break;

View File

@ -104,6 +104,10 @@ public class GBDevice implements Parcelable {
return mState.ordinal() >= State.CONNECTED.ordinal(); return mState.ordinal() >= State.CONNECTED.ordinal();
} }
public boolean isInitializing() {
return mState == State.INITIALIZING;
}
public boolean isInitialized() { public boolean isInitialized() {
return mState.ordinal() >= State.INITIALIZED.ordinal(); return mState.ordinal() >= State.INITIALIZED.ordinal();
} }
@ -118,7 +122,9 @@ public class GBDevice implements Parcelable {
public void setState(State state) { public void setState(State state) {
mState = state; mState = state;
unsetDynamicState(); if (state.ordinal() <= State.CONNECTED.ordinal()) {
unsetDynamicState();
}
} }
private void unsetDynamicState() { private void unsetDynamicState() {
@ -136,6 +142,8 @@ public class GBDevice implements Parcelable {
return GBApplication.getContext().getString(R.string.connecting); return GBApplication.getContext().getString(R.string.connecting);
case CONNECTED: case CONNECTED:
return GBApplication.getContext().getString(R.string.connected); return GBApplication.getContext().getString(R.string.connected);
case INITIALIZING:
return GBApplication.getContext().getString(R.string.initializing);
case INITIALIZED: case INITIALIZED:
return GBApplication.getContext().getString(R.string.initialized); return GBApplication.getContext().getString(R.string.initialized);
} }
@ -238,6 +246,7 @@ public class GBDevice implements Parcelable {
NOT_CONNECTED, NOT_CONNECTED,
CONNECTING, CONNECTING,
CONNECTED, CONNECTED,
INITIALIZING,
INITIALIZED INITIALIZED
} }

View File

@ -77,6 +77,7 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
if (!isInitialized()) { if (!isInitialized()) {
// first, add a transaction that performs device initialization // first, add a transaction that performs device initialization
TransactionBuilder builder = createTransactionBuilder("Initialize device"); TransactionBuilder builder = createTransactionBuilder("Initialize device");
builder.add(new CheckInitializedAction(gbDevice));
initializeDevice(builder).queue(getQueue()); initializeDevice(builder).queue(getQueue());
} }
return createTransactionBuilder(taskName); return createTransactionBuilder(taskName);

View File

@ -87,15 +87,14 @@ public final class BtLEQueue {
} }
} }
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
mWaitForActionResultLatch = null;
mConnectionLatch = null; mConnectionLatch = null;
LOG.debug("Thread interrupted"); LOG.debug("Thread interrupted");
} catch (Throwable ex) { } catch (Throwable ex) {
LOG.error("Queue Dispatch Thread died: " + ex.getMessage()); LOG.error("Queue Dispatch Thread died: " + ex.getMessage());
mCrashed = true; mCrashed = true;
mWaitForActionResultLatch = null;
mConnectionLatch = null; mConnectionLatch = null;
} finally { } finally {
mWaitForActionResultLatch = null;
mWaitCharacteristic = null; mWaitCharacteristic = null;
} }
} }

View File

@ -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;
}
}

View File

@ -55,15 +55,27 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
@Override @Override
protected TransactionBuilder initializeDevice(TransactionBuilder builder) { protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
builder.add(new SetDeviceStateAction(getDevice(), State.INITIALIZING, getContext()));
pair(builder) pair(builder)
.sendUserInfo(builder) .sendUserInfo(builder)
.enableNotifications(builder, true) .enableNotifications(builder, true)
.setCurrentTime(builder) .setCurrentTime(builder)
.requestBatteryInfo(builder); .requestBatteryInfo(builder)
.setInitialized(builder);
return 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 // TODO: tear down the notifications on quit
private MiBandSupport enableNotifications(TransactionBuilder builder, boolean enable) { private MiBandSupport enableNotifications(TransactionBuilder builder, boolean enable) {
builder.notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_NOTIFICATION), enable) builder.notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_NOTIFICATION), enable)

View File

@ -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;
}
}

View File

@ -104,5 +104,6 @@
<string name="title_activity_sleepmonitor">Sleep Monitor</string> <string name="title_activity_sleepmonitor">Sleep Monitor</string>
<string name="pref_log_to_file">LogToFile</string> <string name="pref_log_to_file">LogToFile</string>
<string name="pref_write_logfiles">Write Log Files (needs restart)</string> <string name="pref_write_logfiles">Write Log Files (needs restart)</string>
<string name="initializing">initializing</string>
</resources> </resources>