mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-02-13 19:05:39 +01:00
Huawei: Parse more workout information. No UI.
This commit is contained in:
parent
02aa267e8f
commit
fdea3b7955
@ -54,7 +54,7 @@ public class GBDaoGenerator {
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
final Schema schema = new Schema(95, MAIN_PACKAGE + ".entities");
|
||||
final Schema schema = new Schema(96, MAIN_PACKAGE + ".entities");
|
||||
|
||||
Entity userAttributes = addUserAttributes(schema);
|
||||
Entity user = addUserInfo(schema, userAttributes);
|
||||
@ -161,6 +161,7 @@ public class GBDaoGenerator {
|
||||
addHuaweiWorkoutPaceSample(schema, huaweiWorkoutSummary);
|
||||
addHuaweiWorkoutSwimSegmentsSample(schema, huaweiWorkoutSummary);
|
||||
addHuaweiWorkoutSpO2Sample(schema, huaweiWorkoutSummary);
|
||||
addHuaweiWorkoutSectionsSample(schema, huaweiWorkoutSummary);
|
||||
|
||||
Entity huaweiDictData = addHuaweiDictData(schema, user, device);
|
||||
addHuaweiDictDataValues(schema, huaweiDictData);
|
||||
@ -1502,6 +1503,18 @@ public class GBDaoGenerator {
|
||||
workoutDataSample.addShortProperty("frequency").notNull();
|
||||
workoutDataSample.addIntProperty("altitude");
|
||||
|
||||
workoutDataSample.addShortProperty("hangTime").notNull();
|
||||
workoutDataSample.addShortProperty("impactHangRate").notNull();
|
||||
workoutDataSample.addByteProperty("rideCadence").notNull();
|
||||
workoutDataSample.addFloatProperty("ap").notNull();
|
||||
workoutDataSample.addFloatProperty("vo").notNull();
|
||||
workoutDataSample.addFloatProperty("gtb").notNull();
|
||||
workoutDataSample.addFloatProperty("vr").notNull();
|
||||
workoutDataSample.addByteProperty("ceiling").notNull();
|
||||
workoutDataSample.addByteProperty("temp").notNull();
|
||||
workoutDataSample.addByteProperty("spo2").notNull();
|
||||
workoutDataSample.addShortProperty("cns").notNull();
|
||||
|
||||
return workoutDataSample;
|
||||
}
|
||||
|
||||
@ -1559,6 +1572,39 @@ public class GBDaoGenerator {
|
||||
return workoutSwimSegmentsSample;
|
||||
}
|
||||
|
||||
private static Entity addHuaweiWorkoutSectionsSample(Schema schema, Entity summaryEntity) {
|
||||
Entity workoutSectionsSample = addEntity(schema, "HuaweiWorkoutSectionsSample");
|
||||
|
||||
workoutSectionsSample.setJavaDoc("Contains Huawei Workout Section data samples");
|
||||
|
||||
Property id = workoutSectionsSample.addLongProperty("workoutId").primaryKey().notNull().getProperty();
|
||||
workoutSectionsSample.addToOne(summaryEntity, id);
|
||||
|
||||
workoutSectionsSample.addIntProperty("dataIdx").notNull().primaryKey();
|
||||
workoutSectionsSample.addIntProperty("rowIdx").notNull().primaryKey();
|
||||
|
||||
workoutSectionsSample.addIntProperty("num").notNull();
|
||||
workoutSectionsSample.addLongProperty("time").notNull();
|
||||
workoutSectionsSample.addLongProperty("distance").notNull();
|
||||
workoutSectionsSample.addIntProperty("pace").notNull();
|
||||
workoutSectionsSample.addIntProperty("heartRate").notNull();
|
||||
workoutSectionsSample.addIntProperty("cadence").notNull();
|
||||
workoutSectionsSample.addIntProperty("stepLength").notNull();
|
||||
workoutSectionsSample.addLongProperty("totalRise").notNull();
|
||||
workoutSectionsSample.addLongProperty("totalDescend").notNull();
|
||||
workoutSectionsSample.addIntProperty("groundContactTime").notNull();
|
||||
workoutSectionsSample.addIntProperty("groundImpact").notNull();
|
||||
workoutSectionsSample.addIntProperty("swingAngle").notNull();
|
||||
workoutSectionsSample.addIntProperty("eversion").notNull();
|
||||
workoutSectionsSample.addIntProperty("avgCadence").notNull();
|
||||
workoutSectionsSample.addIntProperty("intervalTrainingType").notNull();
|
||||
workoutSectionsSample.addIntProperty("divingMaxDepth").notNull();
|
||||
workoutSectionsSample.addIntProperty("divingUnderwaterTime").notNull();
|
||||
workoutSectionsSample.addIntProperty("divingBreakTime").notNull();
|
||||
|
||||
return workoutSectionsSample;
|
||||
}
|
||||
|
||||
private static Entity addHuaweiDictData(Schema schema, Entity user, Entity device) {
|
||||
Entity dictData = addEntity(schema, "HuaweiDictData");
|
||||
|
||||
|
@ -0,0 +1,74 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.database.schema;
|
||||
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
|
||||
|
||||
public class GadgetbridgeUpdate_96 implements DBUpdateScript {
|
||||
@Override
|
||||
public void upgradeSchema(final SQLiteDatabase db) {
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.HangTime.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.HangTime.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.ImpactHangRate.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.ImpactHangRate.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.RideCadence.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.RideCadence.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Ap.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Ap.columnName + "\" FLOAT NOT NULL DEFAULT 0;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Vo.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Vo.columnName + "\" FLOAT NOT NULL DEFAULT 0;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Gtb.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Gtb.columnName + "\" FLOAT NOT NULL DEFAULT 0;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Vr.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Vr.columnName + "\" FLOAT NOT NULL DEFAULT 0;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Ceiling.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Ceiling.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Temp.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Temp.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Spo2.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Spo2.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
if (!DBHelper.existsColumn(HuaweiWorkoutDataSampleDao.TABLENAME, HuaweiWorkoutDataSampleDao.Properties.Cns.columnName, db)) {
|
||||
final String statement = "ALTER TABLE " + HuaweiWorkoutDataSampleDao.TABLENAME + " ADD COLUMN \""
|
||||
+ HuaweiWorkoutDataSampleDao.Properties.Cns.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
|
||||
db.execSQL(statement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downgradeSchema(final SQLiteDatabase db) {
|
||||
}
|
||||
}
|
@ -75,6 +75,8 @@ public class HuaweiCoordinator {
|
||||
private boolean supportsTruSleepNewSync = false;
|
||||
private boolean supportsGpsNewSync = false;
|
||||
|
||||
private boolean supportsWorkoutNewSteps = false;
|
||||
|
||||
private Watchface.WatchfaceDeviceParams watchfaceDeviceParams;
|
||||
|
||||
private App.AppDeviceParams appDeviceParams;
|
||||
@ -585,6 +587,10 @@ public class HuaweiCoordinator {
|
||||
return supportsCommandForService(0x17, 0x01);
|
||||
}
|
||||
|
||||
public boolean supportsWorkoutCapability() {
|
||||
return supportsCommandForService(0x17, 0x15);
|
||||
}
|
||||
|
||||
public boolean supportsWorkoutsTrustHeartRate() {
|
||||
return supportsCommandForService(0x17, 0x17);
|
||||
}
|
||||
@ -966,6 +972,14 @@ public class HuaweiCoordinator {
|
||||
this.supportsGpsNewSync = supportsGpsNewSync;
|
||||
}
|
||||
|
||||
public boolean isSupportsWorkoutNewSteps() {
|
||||
return supportsWorkoutNewSteps;
|
||||
}
|
||||
|
||||
public void setSupportsWorkoutNewSteps(boolean supportsWorkoutNewSteps) {
|
||||
this.supportsWorkoutNewSteps = supportsWorkoutNewSteps;
|
||||
}
|
||||
|
||||
public String getOtaSoftwareVersion() {
|
||||
return otaSoftwareVersion;
|
||||
}
|
||||
|
@ -582,6 +582,10 @@ public class HuaweiPacket {
|
||||
return new Workout.WorkoutSwimSegments.Response(paramsProvider).fromPacket(this);
|
||||
case Workout.WorkoutSpO2.id:
|
||||
return new Workout.WorkoutSpO2.Response(paramsProvider).fromPacket(this);
|
||||
case Workout.WorkoutCapability.id:
|
||||
return new Workout.WorkoutCapability.Response(paramsProvider).fromPacket(this);
|
||||
case Workout.WorkoutSections.id:
|
||||
return new Workout.WorkoutSections.Response(paramsProvider).fromPacket(this);
|
||||
default:
|
||||
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
|
||||
return this;
|
||||
|
@ -28,6 +28,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
|
||||
|
||||
public class Workout {
|
||||
|
||||
public static final byte id = 0x17;
|
||||
|
||||
public static class WorkoutCount {
|
||||
@ -63,6 +64,7 @@ public class Workout {
|
||||
public short paceCount;
|
||||
public short segmentsCount = 0;
|
||||
public short spO2Count = 0;
|
||||
public short sectionsCount = 0;
|
||||
|
||||
}
|
||||
|
||||
@ -90,12 +92,15 @@ public class Workout {
|
||||
workoutNumber.workoutNumber = subContainerTlv.getShort(0x06);
|
||||
workoutNumber.dataCount = subContainerTlv.getShort(0x07);
|
||||
workoutNumber.paceCount = subContainerTlv.getShort(0x08);
|
||||
if(subContainerTlv.contains(0x09)) {
|
||||
if (subContainerTlv.contains(0x09)) {
|
||||
workoutNumber.segmentsCount = subContainerTlv.getShort(0x09);
|
||||
}
|
||||
if(subContainerTlv.contains(0x0c)) {
|
||||
if (subContainerTlv.contains(0x0c)) {
|
||||
workoutNumber.spO2Count = subContainerTlv.getShort(0x0c);
|
||||
}
|
||||
if (subContainerTlv.contains(0x0d)) {
|
||||
workoutNumber.sectionsCount = subContainerTlv.getShort(0x0d);
|
||||
}
|
||||
this.workoutNumbers.add(workoutNumber);
|
||||
}
|
||||
|
||||
@ -285,17 +290,23 @@ public class Workout {
|
||||
public Request(
|
||||
ParamsProvider paramsProvider,
|
||||
short workoutNumber,
|
||||
short dataNumber
|
||||
short dataNumber,
|
||||
boolean newSteps
|
||||
) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = Workout.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV().put(0x81, new HuaweiTLV()
|
||||
HuaweiTLV data = new HuaweiTLV()
|
||||
.put(0x02, workoutNumber)
|
||||
.put(0x03, dataNumber)
|
||||
);
|
||||
.put(0x03, dataNumber);
|
||||
if (newSteps) {
|
||||
data.put(0x06, (byte) 1);
|
||||
}
|
||||
data.put(0x07);
|
||||
|
||||
this.tlv = new HuaweiTLV().put(0x81, data);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
@ -311,6 +322,7 @@ public class Workout {
|
||||
public byte dataLength;
|
||||
public short bitmap; // TODO: can this be enum-like?
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Header{" +
|
||||
@ -342,6 +354,17 @@ public class Workout {
|
||||
public byte midFootLanding = -1;
|
||||
public byte backFootLanding = -1;
|
||||
public byte eversionAngle = -1;
|
||||
public short hangTime = -1;
|
||||
public short impactHangRate = -1;
|
||||
public byte rideCadence = -1;
|
||||
public float ap = 0.0F;
|
||||
public float vo = 0.0F;
|
||||
public float gtb = 0.0F;
|
||||
public float vr = 0.0F;
|
||||
public byte ceiling = -1;
|
||||
public byte temp = -1;
|
||||
public byte spo2 = -1;
|
||||
public short cns = -1;
|
||||
|
||||
public short swolf = -1;
|
||||
public short strokeRate = -1;
|
||||
@ -353,6 +376,7 @@ public class Workout {
|
||||
|
||||
public int timestamp = -1; // Calculated timestamp for this data point
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Data{" +
|
||||
@ -369,6 +393,17 @@ public class Workout {
|
||||
", midFootLanding=" + midFootLanding +
|
||||
", backFootLanding=" + backFootLanding +
|
||||
", eversionAngle=" + eversionAngle +
|
||||
", hangTime=" + hangTime +
|
||||
", impactHangRate=" + impactHangRate +
|
||||
", rideCadence=" + rideCadence +
|
||||
", ap=" + ap +
|
||||
", vo=" + vo +
|
||||
", gtb=" + gtb +
|
||||
", vr=" + vr +
|
||||
", ceiling=" + ceiling +
|
||||
", temp=" + temp +
|
||||
", spo2=" + spo2 +
|
||||
", cns=" + cns +
|
||||
", swolf=" + swolf +
|
||||
", strokeRate=" + strokeRate +
|
||||
", calories=" + calories +
|
||||
@ -387,7 +422,8 @@ public class Workout {
|
||||
public short dataNumber;
|
||||
public byte[] rawHeader;
|
||||
public byte[] rawData;
|
||||
public short innerBitmap;
|
||||
public int innerBitmap = 0;
|
||||
public int extraDataLength = 0;
|
||||
|
||||
public Header header;
|
||||
public List<Data> dataList;
|
||||
@ -416,11 +452,19 @@ public class Workout {
|
||||
this.rawHeader = container.getBytes(0x04);
|
||||
this.rawData = container.getBytes(0x05); // TODO: not sure if 5 can also be omitted
|
||||
|
||||
if (container.contains(0x09))
|
||||
innerBitmap = container.getShort(0x09);
|
||||
else
|
||||
innerBitmap = 0x01FF; // This seems to be the default
|
||||
if (container.contains(0x08))
|
||||
this.extraDataLength = container.getAsInteger(0x08);
|
||||
|
||||
if (container.contains(0x09))
|
||||
this.innerBitmap = container.getAsInteger(0x09);
|
||||
else
|
||||
this.innerBitmap = 0x01FF; // This seems to be the default
|
||||
|
||||
|
||||
if (this.rawHeader.length != 14)
|
||||
throw new LengthMismatchException("Workout data header length mismatch.");
|
||||
|
||||
// Calculate inner data length
|
||||
int innerDataLength = 0;
|
||||
for (byte i = 0; i < innerBitmapLengths.length; i++) {
|
||||
if ((innerBitmap & (1 << i)) != 0) {
|
||||
@ -428,8 +472,9 @@ public class Workout {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.rawHeader.length != 14)
|
||||
throw new LengthMismatchException("Workout data header length mismatch.");
|
||||
//TODO: innerDataLength should be equal to this.extraDataLength. Should correlate to innerBitmap default value.
|
||||
//TODO: I suppose innerBitmap should be 0 by default but not sure and don't have devices for testing. So I do not add this check.
|
||||
//TODO: is is possible that innerBitmap = 0x01FF only true for AW70 devices. in this case extraDataLength should be properly calculated.
|
||||
|
||||
this.header = new Header();
|
||||
ByteBuffer buf = ByteBuffer.wrap(this.rawHeader);
|
||||
@ -517,7 +562,40 @@ public class Workout {
|
||||
data.backFootLanding = buf.get();
|
||||
break;
|
||||
case 8:
|
||||
data.eversionAngle = buf.get();
|
||||
data.eversionAngle = buf.get(); // buf.get() - 100;
|
||||
break;
|
||||
case 9:
|
||||
data.hangTime = buf.getShort();
|
||||
break;
|
||||
case 10:
|
||||
data.impactHangRate = buf.getShort();
|
||||
break;
|
||||
case 11:
|
||||
data.rideCadence = buf.get();
|
||||
break;
|
||||
case 12:
|
||||
data.ap = (float) buf.getShort() / 10.0f;
|
||||
break;
|
||||
case 13:
|
||||
data.vo = (float) buf.getShort() / 10.0f;
|
||||
break;
|
||||
case 14:
|
||||
data.gtb = (float) buf.getShort() / 100.0f;
|
||||
break;
|
||||
case 15:
|
||||
data.vr = (float) buf.getShort() / 10.0f;
|
||||
break;
|
||||
case 16:
|
||||
data.ceiling = buf.get();
|
||||
break;
|
||||
case 17:
|
||||
data.temp = buf.get();
|
||||
break;
|
||||
case 18:
|
||||
data.spo2 = buf.get();
|
||||
break;
|
||||
case 19:
|
||||
data.cns = buf.getShort();
|
||||
break;
|
||||
default:
|
||||
data.unknownData = this.tlv.serialize();
|
||||
@ -586,6 +664,7 @@ public class Workout {
|
||||
public short correction = 0;
|
||||
public boolean hasCorrection = false;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Block{" +
|
||||
@ -663,25 +742,24 @@ public class Workout {
|
||||
public int pace = -1;
|
||||
public short pointIndex = 0;
|
||||
public short segment = -1;
|
||||
public byte swimType= -1;
|
||||
public byte swimType = -1;
|
||||
public short strokes = -1;
|
||||
public short avgSwolf = -1;
|
||||
public int time= -1;
|
||||
public int time = -1;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("Block{");
|
||||
sb.append("distance=").append(distance);
|
||||
sb.append(", type=").append(type);
|
||||
sb.append(", pace=").append(pace);
|
||||
sb.append(", pointIndex=").append(pointIndex);
|
||||
sb.append(", segment=").append(segment);
|
||||
sb.append(", swimType=").append(swimType);
|
||||
sb.append(", strokes=").append(strokes);
|
||||
sb.append(", awgSwolf=").append(avgSwolf);
|
||||
sb.append(", time=").append(time);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
return "Block{" + "distance=" + distance +
|
||||
", type=" + type +
|
||||
", pace=" + pace +
|
||||
", pointIndex=" + pointIndex +
|
||||
", segment=" + segment +
|
||||
", swimType=" + swimType +
|
||||
", strokes=" + strokes +
|
||||
", awgSwolf=" + avgSwolf +
|
||||
", time=" + time +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -712,13 +790,13 @@ public class Workout {
|
||||
if (blockTlv.contains(0x09))
|
||||
block.segment = blockTlv.getShort(0x09);
|
||||
if (blockTlv.contains(0x0a))
|
||||
block.swimType= blockTlv.getByte(0x0a);
|
||||
block.swimType = blockTlv.getByte(0x0a);
|
||||
if (blockTlv.contains(0x0b))
|
||||
block.strokes = blockTlv.getShort(0x0b);
|
||||
if (blockTlv.contains(0x0c))
|
||||
block.avgSwolf = blockTlv.getShort(0x0c);
|
||||
if (blockTlv.contains(0x0d))
|
||||
block.time= blockTlv.getInteger(0x0d);
|
||||
block.time = blockTlv.getInteger(0x0d);
|
||||
|
||||
blocks.add(block);
|
||||
}
|
||||
@ -758,11 +836,9 @@ public class Workout {
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuffer sb = new StringBuffer("Block{");
|
||||
sb.append("interval=").append(interval);
|
||||
sb.append(", value=").append(value);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
return "Block{" + "interval=" + interval +
|
||||
", value=" + value +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -797,6 +873,179 @@ public class Workout {
|
||||
}
|
||||
}
|
||||
|
||||
public static class WorkoutCapability {
|
||||
public static final int id = 0x15;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
|
||||
public Request(
|
||||
ParamsProvider paramsProvider
|
||||
) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = Workout.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public boolean supportNewStep = false;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
if (this.tlv.contains(0x01)) {
|
||||
int flags = this.tlv.getAsInteger(0x01);
|
||||
supportNewStep = (flags & 2) == 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class WorkoutSections {
|
||||
public static final int id = 0x16;
|
||||
|
||||
public static class Request extends HuaweiPacket {
|
||||
|
||||
public Request(
|
||||
ParamsProvider paramsProvider,
|
||||
short workoutNumber,
|
||||
short additionalDataNumber
|
||||
) {
|
||||
super(paramsProvider);
|
||||
|
||||
this.serviceId = Workout.id;
|
||||
this.commandId = id;
|
||||
|
||||
this.tlv = new HuaweiTLV()
|
||||
.put(0x01, workoutNumber)
|
||||
.put(0x02, additionalDataNumber)
|
||||
.put(0x03);
|
||||
|
||||
this.complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response extends HuaweiPacket {
|
||||
public static class Block {
|
||||
public int num = -1;
|
||||
public long time = -1;
|
||||
public long distance = -1;
|
||||
public int pace = -1;
|
||||
public int heartRate = -1;
|
||||
public int cadence = -1;
|
||||
public int stepLength = -1;
|
||||
public long totalRise = -1;
|
||||
public long totalDescend = -1;
|
||||
public int groundContactTime = -1;
|
||||
public int groundImpact = -1;
|
||||
public int swingAngle = -1;
|
||||
public int eversion = -1;
|
||||
|
||||
public int avgCadence = -1;
|
||||
public int intervalTrainingType = -1;
|
||||
public int divingMaxDepth = -1;
|
||||
public int divingUnderwaterTime = -1;
|
||||
public int divingBreakTime = -1;
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Block{" + "num=" + num +
|
||||
", time=" + time +
|
||||
", distance=" + distance +
|
||||
", pace=" + pace +
|
||||
", heartRate=" + heartRate +
|
||||
", cadence=" + cadence +
|
||||
", stepLength=" + stepLength +
|
||||
", totalRise=" + totalRise +
|
||||
", totalDescend=" + totalDescend +
|
||||
", groundContactTime=" + groundContactTime +
|
||||
", groundImpact=" + groundImpact +
|
||||
", swingAngle=" + swingAngle +
|
||||
", eversion=" + eversion +
|
||||
", avgCadence=" + avgCadence +
|
||||
", intervalTrainingType=" + intervalTrainingType +
|
||||
", divingMaxDepth=" + divingMaxDepth +
|
||||
", divingUnderwaterTime=" + divingUnderwaterTime +
|
||||
", divingBreakTime=" + divingBreakTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public short workoutId;
|
||||
public short number; //TODO: meaning of this field
|
||||
public List<Block> blocks;
|
||||
|
||||
public Response(ParamsProvider paramsProvider) {
|
||||
super(paramsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseTlv() throws ParseException {
|
||||
|
||||
this.workoutId = this.tlv.getShort(0x01);
|
||||
this.number = this.tlv.getShort(0x02);
|
||||
|
||||
HuaweiTLV container = this.tlv.getObject(0x83);
|
||||
|
||||
this.blocks = new ArrayList<>();
|
||||
for (HuaweiTLV blockTlv : container.getObjects(0x84)) {
|
||||
Block block = new Block();
|
||||
|
||||
if (blockTlv.contains(0x05))
|
||||
block.num = blockTlv.getAsInteger(0x05);
|
||||
if (blockTlv.contains(0x06))
|
||||
block.time = blockTlv.getAsLong(0x06);
|
||||
if (blockTlv.contains(0x07))
|
||||
block.distance = blockTlv.getAsLong(0x07);
|
||||
if (blockTlv.contains(0x08))
|
||||
block.pace = blockTlv.getAsInteger(0x08);
|
||||
if (blockTlv.contains(0x09))
|
||||
block.heartRate = blockTlv.getAsInteger(0x09);
|
||||
if (blockTlv.contains(0xa))
|
||||
block.cadence = blockTlv.getAsInteger(0xa);
|
||||
if (blockTlv.contains(0xb))
|
||||
block.stepLength = blockTlv.getAsInteger(0xb);
|
||||
if (blockTlv.contains(0xc))
|
||||
block.totalRise = blockTlv.getAsLong(0xc);
|
||||
if (blockTlv.contains(0xd))
|
||||
block.totalDescend = blockTlv.getAsLong(0xd);
|
||||
if (blockTlv.contains(0xe))
|
||||
block.groundContactTime = blockTlv.getAsInteger(0xe);
|
||||
if (blockTlv.contains(0xf))
|
||||
block.groundImpact = blockTlv.getAsInteger(0xf);
|
||||
if (blockTlv.contains(0x10))
|
||||
block.swingAngle = blockTlv.getAsInteger(0x10);
|
||||
if (blockTlv.contains(0x11))
|
||||
block.eversion = blockTlv.getAsInteger(0x11);
|
||||
|
||||
if (blockTlv.contains(0x22))
|
||||
block.avgCadence = blockTlv.getAsInteger(0x22);
|
||||
if (blockTlv.contains(0x23))
|
||||
block.intervalTrainingType = blockTlv.getAsInteger(0x23);
|
||||
if (blockTlv.contains(0x28))
|
||||
block.divingMaxDepth = blockTlv.getAsInteger(0x28);
|
||||
if (blockTlv.contains(0x29))
|
||||
block.divingUnderwaterTime = blockTlv.getAsInteger(0x29);
|
||||
if (blockTlv.contains(0x2a))
|
||||
block.divingBreakTime = blockTlv.getAsInteger(0x2a);
|
||||
|
||||
blocks.add(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class NotifyHeartRate {
|
||||
public static final int id = 0x17;
|
||||
|
||||
|
@ -80,6 +80,8 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSectionsSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSectionsSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSpO2Sample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSpO2SampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
|
||||
@ -128,6 +130,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetN
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetOTAChangeLog;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetSmartAlarmList;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWatchfaceParams;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.GetWorkoutCapability;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendCameraRemoteSetupEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendDeviceReportThreshold;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendExtendedAccountRequest;
|
||||
@ -856,6 +859,7 @@ public class HuaweiSupportProvider {
|
||||
initRequestQueue.add(new GetContactsCount(this));
|
||||
initRequestQueue.add(new SendOTASetAutoUpdate(this));
|
||||
initRequestQueue.add(new GetOTAChangeLog(this));
|
||||
//initRequestQueue.add(new GetWorkoutCapability(this)); // TODO: in current stage I don't understand how to parse new steps.
|
||||
initRequestQueue.add(new GetEventAlarmList(this));
|
||||
initRequestQueue.add(new GetSmartAlarmList(this));
|
||||
|
||||
@ -1821,7 +1825,18 @@ public class HuaweiSupportProvider {
|
||||
data.calories,
|
||||
data.cyclingPower,
|
||||
data.frequency,
|
||||
data.altitude
|
||||
data.altitude,
|
||||
data.hangTime,
|
||||
data.impactHangRate,
|
||||
data.rideCadence,
|
||||
data.ap,
|
||||
data.vo,
|
||||
data.gtb,
|
||||
data.vr,
|
||||
data.ceiling,
|
||||
data.temp,
|
||||
data.spo2,
|
||||
data.cns
|
||||
);
|
||||
dao.insertOrReplace(dataSample);
|
||||
}
|
||||
@ -1928,6 +1943,54 @@ public class HuaweiSupportProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public void addWorkoutSectionsData(Long workoutId, List<Workout.WorkoutSections.Response.Block> spO2List, short number) {
|
||||
if (workoutId == null)
|
||||
return;
|
||||
|
||||
// NOTE: All fields of this data is optional. At this point I don't all workouts that this data used.
|
||||
// I decided to add two additional fields dataIdx and rowIdx as primary keys that should identify each row
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
HuaweiWorkoutSectionsSampleDao dao = db.getDaoSession().getHuaweiWorkoutSectionsSampleDao();
|
||||
|
||||
if (number == 0) {
|
||||
final DeleteQuery<HuaweiWorkoutSectionsSample> tableDeleteQuery = dao.queryBuilder()
|
||||
.where(HuaweiWorkoutSectionsSampleDao.Properties.WorkoutId.eq(workoutId))
|
||||
.buildDelete();
|
||||
tableDeleteQuery.executeDeleteWithoutDetachingEntities();
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (Workout.WorkoutSections.Response.Block block : spO2List) {
|
||||
HuaweiWorkoutSectionsSample huaweiWorkoutSectionsSample = new HuaweiWorkoutSectionsSample(
|
||||
workoutId,
|
||||
number,
|
||||
i++,
|
||||
block.num,
|
||||
block.time,
|
||||
block.distance,
|
||||
block.pace,
|
||||
block.heartRate,
|
||||
block.cadence,
|
||||
block.stepLength,
|
||||
block.totalRise,
|
||||
block.totalDescend,
|
||||
block.groundContactTime,
|
||||
block.groundImpact,
|
||||
block.swingAngle,
|
||||
block.eversion,
|
||||
block.avgCadence,
|
||||
block.divingUnderwaterTime,
|
||||
block.divingMaxDepth,
|
||||
block.divingUnderwaterTime,
|
||||
block.divingBreakTime
|
||||
);
|
||||
dao.insertOrReplace(huaweiWorkoutSectionsSample);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to add workout sections data to database", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDictData(List<HuaweiP2PDataDictionarySyncService.DictData> dictData) {
|
||||
try (DBHandler db = GBApplication.acquireDB()) {
|
||||
Long userId = DBHelper.getUser(db.getDaoSession()).getId();
|
||||
|
@ -301,7 +301,18 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
|
||||
responseData.calories,
|
||||
responseData.cyclingPower,
|
||||
responseData.frequency,
|
||||
responseData.altitude
|
||||
responseData.altitude,
|
||||
responseData.hangTime,
|
||||
responseData.impactHangRate,
|
||||
responseData.rideCadence,
|
||||
responseData.ap,
|
||||
responseData.vo,
|
||||
responseData.gtb,
|
||||
responseData.vr,
|
||||
responseData.ceiling,
|
||||
responseData.temp,
|
||||
responseData.spo2,
|
||||
responseData.cns
|
||||
);
|
||||
|
||||
dbHandler.getDaoSession().getHuaweiWorkoutDataSampleDao().insertOrReplace(dataSample);
|
||||
|
@ -0,0 +1,45 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Workout;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
|
||||
public class GetWorkoutCapability extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GetWorkoutCapability.class);
|
||||
|
||||
public GetWorkoutCapability(HuaweiSupportProvider support) {
|
||||
super(support);
|
||||
this.serviceId = Workout.id;
|
||||
this.commandId = Workout.WorkoutCapability.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requestSupported() {
|
||||
return supportProvider.getHuaweiCoordinator().supportsWorkoutCapability();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new Workout.WorkoutCapability.Request(paramsProvider).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws ResponseParseException {
|
||||
LOG.debug("handle WorkoutCapability");
|
||||
if (!(receivedPacket instanceof Workout.WorkoutCapability.Response))
|
||||
throw new ResponseTypeMismatchException(receivedPacket, Workout.WorkoutCapability.Response.class);
|
||||
|
||||
LOG.info("Workout capability: NewSteps: {}", ((Workout.WorkoutCapability.Response) receivedPacket).supportNewStep);
|
||||
|
||||
supportProvider.getHuaweiCoordinator().setSupportsWorkoutNewSteps(((Workout.WorkoutCapability.Response) receivedPacket).supportNewStep);
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ public class GetWorkoutDataRequest extends Request {
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new Workout.WorkoutData.Request(paramsProvider, workoutNumbers.workoutNumber, this.number).serialize();
|
||||
return new Workout.WorkoutData.Request(paramsProvider, workoutNumbers.workoutNumber, this.number, supportProvider.getHuaweiCoordinator().isSupportsWorkoutNewSteps()).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
@ -133,6 +133,16 @@ public class GetWorkoutDataRequest extends Request {
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else if (this.workoutNumbers.sectionsCount > 0) {
|
||||
GetWorkoutSectionsRequest nextRequest = new GetWorkoutSectionsRequest(
|
||||
this.supportProvider,
|
||||
this.workoutNumbers,
|
||||
this.remainder,
|
||||
(short) 0,
|
||||
this.databaseId
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(this.databaseId);
|
||||
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {
|
||||
|
@ -109,6 +109,16 @@ public class GetWorkoutPaceRequest extends Request {
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else if (this.workoutNumbers.sectionsCount > 0) {
|
||||
GetWorkoutSectionsRequest nextRequest = new GetWorkoutSectionsRequest(
|
||||
this.supportProvider,
|
||||
this.workoutNumbers,
|
||||
this.remainder,
|
||||
(short) 0,
|
||||
this.databaseId
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(this.databaseId);
|
||||
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {
|
||||
|
@ -0,0 +1,96 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Workout;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWorkoutGbParser;
|
||||
|
||||
public class GetWorkoutSectionsRequest extends Request {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GetWorkoutSectionsRequest.class);
|
||||
|
||||
Workout.WorkoutCount.Response.WorkoutNumbers workoutNumbers;
|
||||
List<Workout.WorkoutCount.Response.WorkoutNumbers> remainder;
|
||||
short number;
|
||||
Long databaseId;
|
||||
|
||||
public GetWorkoutSectionsRequest(HuaweiSupportProvider support, Workout.WorkoutCount.Response.WorkoutNumbers workoutNumbers, List<Workout.WorkoutCount.Response.WorkoutNumbers> remainder, short number, Long databaseId) {
|
||||
super(support);
|
||||
|
||||
this.serviceId = Workout.id;
|
||||
this.commandId = Workout.WorkoutSections.id;
|
||||
|
||||
this.workoutNumbers = workoutNumbers;
|
||||
this.remainder = remainder;
|
||||
this.number = number;
|
||||
|
||||
this.databaseId = databaseId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<byte[]> createRequest() throws RequestCreationException {
|
||||
try {
|
||||
return new Workout.WorkoutSections.Request(paramsProvider, this.workoutNumbers.workoutNumber, this.number).serialize();
|
||||
} catch (HuaweiPacket.CryptoException e) {
|
||||
throw new RequestCreationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processResponse() throws ResponseParseException {
|
||||
if (!(receivedPacket instanceof Workout.WorkoutSections.Response))
|
||||
throw new ResponseTypeMismatchException(receivedPacket, Workout.WorkoutSections.Response.class);
|
||||
|
||||
Workout.WorkoutSections.Response packet = (Workout.WorkoutSections.Response) receivedPacket;
|
||||
|
||||
|
||||
LOG.info("Workout {} section {}:", this.workoutNumbers.workoutNumber, this.number);
|
||||
LOG.info("workoutId : {}", packet.workoutId);
|
||||
LOG.info("number : {}", packet.number);
|
||||
LOG.info("Block num : {}", packet.blocks.size());
|
||||
LOG.info("Blocks : {}", Arrays.toString(packet.blocks.toArray()));
|
||||
|
||||
supportProvider.addWorkoutSectionsData(this.databaseId, packet.blocks, this.number);
|
||||
|
||||
if (this.workoutNumbers.sectionsCount > this.number + 1) {
|
||||
GetWorkoutSectionsRequest nextRequest = new GetWorkoutSectionsRequest(
|
||||
this.supportProvider,
|
||||
this.workoutNumbers,
|
||||
this.remainder,
|
||||
(short) (this.number + 1),
|
||||
this.databaseId
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(this.databaseId);
|
||||
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!remainder.isEmpty()) {
|
||||
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
|
||||
GetWorkoutSectionsRequest.this.supportProvider,
|
||||
remainder.remove(0),
|
||||
remainder
|
||||
);
|
||||
nextRequest.setFinalizeReq(GetWorkoutSectionsRequest.this.finalizeReq);
|
||||
// Cannot do this with nextRequest because it's in a callback
|
||||
try {
|
||||
nextRequest.doPerform();
|
||||
} catch (IOException e) {
|
||||
finalizeReq.handleException(new ResponseParseException("Cannot send next request", e));
|
||||
}
|
||||
} else {
|
||||
supportProvider.endOfWorkoutSync();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -45,7 +45,7 @@ public class GetWorkoutSpO2Request extends Request {
|
||||
@Override
|
||||
protected void processResponse() throws ResponseParseException {
|
||||
if (!(receivedPacket instanceof Workout.WorkoutSpO2.Response))
|
||||
throw new ResponseTypeMismatchException(receivedPacket, Workout.WorkoutSwimSegments.Response.class);
|
||||
throw new ResponseTypeMismatchException(receivedPacket, Workout.WorkoutSections.Response.class);
|
||||
|
||||
Workout.WorkoutSpO2.Response packet = (Workout.WorkoutSpO2.Response) receivedPacket;
|
||||
|
||||
@ -68,6 +68,16 @@ public class GetWorkoutSpO2Request extends Request {
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else if (this.workoutNumbers.sectionsCount > 0) {
|
||||
GetWorkoutSectionsRequest nextRequest = new GetWorkoutSectionsRequest(
|
||||
this.supportProvider,
|
||||
this.workoutNumbers,
|
||||
this.remainder,
|
||||
(short) 0,
|
||||
this.databaseId
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(this.databaseId);
|
||||
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {
|
||||
|
@ -83,6 +83,16 @@ public class GetWorkoutSwimSegmentsRequest extends Request {
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else if (this.workoutNumbers.sectionsCount > 0) {
|
||||
GetWorkoutSectionsRequest nextRequest = new GetWorkoutSectionsRequest(
|
||||
this.supportProvider,
|
||||
this.workoutNumbers,
|
||||
this.remainder,
|
||||
(short) 0,
|
||||
this.databaseId
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(this.databaseId);
|
||||
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {
|
||||
|
@ -124,6 +124,16 @@ public class GetWorkoutTotalsRequest extends Request {
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else if (this.workoutNumbers.sectionsCount > 0) {
|
||||
GetWorkoutSectionsRequest nextRequest = new GetWorkoutSectionsRequest(
|
||||
this.supportProvider,
|
||||
this.workoutNumbers,
|
||||
this.remainder,
|
||||
(short) 0,
|
||||
databaseId
|
||||
);
|
||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||
this.nextRequest(nextRequest);
|
||||
} else {
|
||||
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(databaseId);
|
||||
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, databaseId, new Runnable() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user