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.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;

View File

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

View File

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

View File

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

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
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)

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="pref_log_to_file">LogToFile</string>
<string name="pref_write_logfiles">Write Log Files (needs restart)</string>
<string name="initializing">initializing</string>
</resources>