Merge remote-tracking branch 'origin/master' into new_GUI

This commit is contained in:
cpfeiffer 2016-10-24 11:32:39 +02:00
commit 84f36b528a
6 changed files with 58 additions and 45 deletions

View File

@ -1,5 +1,9 @@
###Changelog ###Changelog
####Version 0.13.6
* Mi Band 2: Support for multiple alarms (3 at the moment)
* Mi Band 2: Fix for alarms not working when just one is enabled
####Version 0.13.5 ####Version 0.13.5
* Mi Band 2: Support setting one alarm * Mi Band 2: Support setting one alarm
* Pebble: Health compatibility for Firmware 4.2 * Pebble: Health compatibility for Firmware 4.2

View File

@ -26,8 +26,8 @@ android {
targetSdkVersion 23 targetSdkVersion 23
// note: always bump BOTH versionCode and versionName! // note: always bump BOTH versionCode and versionName!
versionName "0.13.5" versionName "0.13.6"
versionCode 67 versionCode 68
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }

View File

@ -16,8 +16,8 @@ public class MiBand2Service {
public static final UUID UUID_UNKNOWN_CHARACTERISTIC0 = UUID.fromString("00000000-0000-3512-2118-0009af100700"); public static final UUID UUID_UNKNOWN_CHARACTERISTIC0 = UUID.fromString("00000000-0000-3512-2118-0009af100700");
public static final UUID UUID_UNKNOWN_CHARACTERISTIC1 = UUID.fromString("00000001-0000-3512-2118-0009af100700"); public static final UUID UUID_UNKNOWN_CHARACTERISTIC1 = UUID.fromString("00000001-0000-3512-2118-0009af100700");
public static final UUID UUID_UNKNOWN_CHARACTERISTIC2 = UUID.fromString("00000002-0000-3512-2118-0009af100700"); public static final UUID UUID_UNKNOWN_CHARACTERISTIC2 = UUID.fromString("00000002-0000-3512-2118-0009af100700");
public static final UUID UUID_UNKNOWN_CHARACTERISTIC3 = UUID.fromString("00000003-0000-3512-2118-0009af100700"); public static final UUID UUID_UNKNOWN_CHARACTERISTIC3 = UUID.fromString("00000003-0000-3512-2118-0009af100700"); // Alarm related
public static final UUID UUID_UNKNOWN_CHARACTERISTIC4 = UUID.fromString("00000004-0000-3512-2118-0009af100700"); // Alarm related public static final UUID UUID_UNKNOWN_CHARACTERISTIC4 = UUID.fromString("00000004-0000-3512-2118-0009af100700");
public static final UUID UUID_UNKNOWN_CHARACTERISTIC5 = UUID.fromString("00000005-0000-3512-2118-0009af100700"); public static final UUID UUID_UNKNOWN_CHARACTERISTIC5 = UUID.fromString("00000005-0000-3512-2118-0009af100700");
public static final UUID UUID_UNKNOWN_CHARACTERISTIC6 = UUID.fromString("00000006-0000-3512-2118-0009af100700"); public static final UUID UUID_UNKNOWN_CHARACTERISTIC6 = UUID.fromString("00000006-0000-3512-2118-0009af100700");
public static final UUID UUID_UNKNOWN_CHARACTERISTIC7 = UUID.fromString("00000007-0000-3512-2118-0009af100700"); public static final UUID UUID_UNKNOWN_CHARACTERISTIC7 = UUID.fromString("00000007-0000-3512-2118-0009af100700");

View File

@ -2,16 +2,23 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.heartrate;
import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattCharacteristic;
import android.widget.Toast;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic; import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
/** /**
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml
*/ */
public class HeartRateProfile<T extends AbstractBTLEDeviceSupport> extends AbstractBleProfile<T> { public class HeartRateProfile<T extends AbstractBTLEDeviceSupport> extends AbstractBleProfile<T> {
private static final Logger LOG = LoggerFactory.getLogger(HeartRateProfile.class);
/** /**
* Returned when a request to the heart rate control point is not supported by the device * Returned when a request to the heart rate control point is not supported by the device
*/ */
@ -26,29 +33,36 @@ public class HeartRateProfile<T extends AbstractBTLEDeviceSupport> extends Abstr
} }
protected void writeToControlPoint(byte value, TransactionBuilder builder) { protected void writeToControlPoint(byte value, TransactionBuilder builder) {
builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), new byte[] { value }); writeToControlPoint(new byte[] { value }, builder);
}
protected void writeToControlPoint(byte[] value, TransactionBuilder builder) {
builder.write(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), value);
} }
public void requestBodySensorLocation(TransactionBuilder builder) { public void requestBodySensorLocation(TransactionBuilder builder) {
} }
// TODO: I didn't find anything in the spec to request heart rate readings, so probably this
// should be done in a device specific way.
public void requestHeartRateMeasurement(TransactionBuilder builder) { public void requestHeartRateMeasurement(TransactionBuilder builder) {
writeToControlPoint(new byte[] { 0x15, 0x02, 0x01}, builder);
} }
@Override @Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
// if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { if (GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
// int flag = characteristic.getProperties(); int flag = characteristic.getProperties();
// int format = -1; int format = -1;
// if ((flag & 0x01) != 0) { if ((flag & 0x01) != 0) {
// format = BluetoothGattCharacteristic.FORMAT_UINT16; format = BluetoothGattCharacteristic.FORMAT_UINT16;
// } else { } else {
// format = BluetoothGattCharacteristic.FORMAT_UINT8; format = BluetoothGattCharacteristic.FORMAT_UINT8;
// } }
// final int heartRate = characteristic.getIntValue(format, 1); final int heartRate = characteristic.getIntValue(format, 1);
// } GB.toast(getContext(), "Heart rate: " + heartRate, Toast.LENGTH_LONG, GB.INFO);
}
return false; return false;
} }
} }

View File

@ -57,6 +57,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.ConditionalWrit
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WriteAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WriteAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.heartrate.HeartRateProfile;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2NotificationStrategy; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2NotificationStrategy;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.InitOperation; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.InitOperation;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
@ -86,6 +87,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
private static final Logger LOG = LoggerFactory.getLogger(MiBand2Support.class); private static final Logger LOG = LoggerFactory.getLogger(MiBand2Support.class);
private final DeviceInfoProfile<MiBand2Support> deviceInfoProfile; private final DeviceInfoProfile<MiBand2Support> deviceInfoProfile;
private final HeartRateProfile<MiBand2Support> heartRateProfile;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
@ -119,6 +121,8 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
deviceInfoProfile = new DeviceInfoProfile<>(this); deviceInfoProfile = new DeviceInfoProfile<>(this);
addSupportedProfile(deviceInfoProfile); addSupportedProfile(deviceInfoProfile);
heartRateProfile = new HeartRateProfile<MiBand2Support>(this);
addSupportedProfile(heartRateProfile);
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getContext()); LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getContext());
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
@ -230,6 +234,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
builder.notify(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_AUTH), enable); builder.notify(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_AUTH), enable);
builder.notify(getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC3), enable); builder.notify(getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC3), enable);
builder.notify(getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC4), enable); builder.notify(getCharacteristic(MiBand2Service.UUID_UNKNOWN_CHARACTERISTIC4), enable);
builder.notify(getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT), enable);
return this; return this;
} }
@ -673,12 +678,14 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
if (supportsHeartRate()) { if (supportsHeartRate()) {
try { try {
TransactionBuilder builder = performInitialized("HeartRateTest"); TransactionBuilder builder = performInitialized("HeartRateTest");
builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), stopHeartMeasurementContinuous); heartRateProfile.requestHeartRateMeasurement(builder);
builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), stopHeartMeasurementManual); // profile.resetEnergyExpended(builder);
builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), startHeartMeasurementManual); // builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), stopHeartMeasurementContinuous);
// builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), stopHeartMeasurementManual);
// builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), startHeartMeasurementManual);
builder.queue(getQueue()); builder.queue(getQueue());
} catch (IOException ex) { } catch (IOException ex) {
LOG.error("Unable to read HearRate in MI1S", ex); LOG.error("Unable to read HearRate with MI2", ex);
} }
} else { } else {
GB.toast(getContext(), "Heart rate is not supported on this device", Toast.LENGTH_LONG, GB.ERROR); GB.toast(getContext(), "Heart rate is not supported on this device", Toast.LENGTH_LONG, GB.ERROR);
@ -1056,43 +1063,27 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
Calendar calendar = alarm.getAlarmCal(); Calendar calendar = alarm.getAlarmCal();
int daysMask = 0; int daysMask = 0;
if (alarm.getIndex() != 0 && alarm.isEnabled()) { int maxAlarms = 5; // arbitrary at the moment...
GB.toast(getContext(), "Only the first alarm is currently supported.", Toast.LENGTH_LONG, GB.WARN); if (alarm.getIndex() >= maxAlarms) {
if (alarm.isEnabled()) {
GB.toast(getContext(), "Only 5 alarms are currently supported.", Toast.LENGTH_LONG, GB.WARN);
}
return; return;
} }
if (alarm.isEnabled()) { if (alarm.isEnabled()) {
if (alarm.getRepetition(Alarm.ALARM_MON)) { daysMask = alarm.getRepetitionMask();
daysMask |= 1;
}
if (alarm.getRepetition(Alarm.ALARM_TUE)) {
daysMask |= 2;
}
if (alarm.getRepetition(Alarm.ALARM_WED)) {
daysMask |= 4;
}
if (alarm.getRepetition(Alarm.ALARM_THU)) {
daysMask |= 8;
}
if (alarm.getRepetition(Alarm.ALARM_FRI)) {
daysMask |= 16;
}
if (alarm.getRepetition(Alarm.ALARM_SAT)) {
daysMask |= 32;
}
if (alarm.getRepetition(Alarm.ALARM_SUN)) {
daysMask |= 64;
}
} }
byte[] alarmMessage = new byte[] { byte[] alarmMessage = new byte[] {
(byte) 0x2, // TODO what is this? 0x1 does not work (byte) 0x2, // TODO what is this?
(byte) 128, // TODO: what is this? (byte) (128 + alarm.getIndex()), // 128 is the base, alarm slot is added
(byte) calendar.get(Calendar.HOUR_OF_DAY), (byte) calendar.get(Calendar.HOUR_OF_DAY),
(byte) calendar.get(Calendar.MINUTE), (byte) calendar.get(Calendar.MINUTE),
(byte) daysMask, (byte) daysMask,
}; };
builder.write(characteristic, alarmMessage); builder.write(characteristic, alarmMessage);
// TODO: react on 0x10, 0x02, 0x01 on notification (success)
} }
private void handleControlPointResult(byte[] value, int status) { private void handleControlPointResult(byte[] value, int status) {

View File

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<changelog> <changelog>
<release version="0.13.6" versioncode="68">
<change>Mi Band 2: Support multiple alarms (3 at the moment)</change>
<change>Mi Band 2: Fix for alarms not working when just one is enabled</change>
</release>
<release version="0.13.5" versioncode="67"> <release version="0.13.5" versioncode="67">
<change>Mi Band 2: Support setting one alarm</change> <change>Mi Band 2: Support setting one alarm</change>
<change>Pebble: Health compatibility for Firmware 4.2</change> <change>Pebble: Health compatibility for Firmware 4.2</change>