1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-27 19:15:50 +01:00

Huawei: more details for swim workout

This commit is contained in:
Me7c7 2024-10-26 08:14:23 +03:00 committed by José Rebelo
parent 3294e20242
commit a46e970f84
11 changed files with 440 additions and 16 deletions

View File

@ -54,7 +54,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
final Schema schema = new Schema(84, MAIN_PACKAGE + ".entities");
final Schema schema = new Schema(85, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@ -151,6 +151,7 @@ public class GBDaoGenerator {
Entity huaweiWorkoutSummary = addHuaweiWorkoutSummarySample(schema, user, device);
addHuaweiWorkoutDataSample(schema, huaweiWorkoutSummary);
addHuaweiWorkoutPaceSample(schema, huaweiWorkoutSummary);
addHuaweiWorkoutSwimSegmentsSample(schema, huaweiWorkoutSummary);
addCalendarSyncState(schema, device);
addAlarms(schema, user, device);
@ -1387,6 +1388,8 @@ public class GBDaoGenerator {
workoutSummary.addByteArrayProperty("recoveryHeartRates");
workoutSummary.addByteProperty("swimType").notNull();
return workoutSummary;
}
@ -1443,6 +1446,28 @@ public class GBDaoGenerator {
return workoutPaceSample;
}
private static Entity addHuaweiWorkoutSwimSegmentsSample(Schema schema, Entity summaryEntity) {
Entity workoutSwimSegmentsSample = addEntity(schema, "HuaweiWorkoutSwimSegmentsSample");
workoutSwimSegmentsSample.setJavaDoc("Contains Huawei Workout swim segments data samples");
Property id = workoutSwimSegmentsSample.addLongProperty("workoutId").primaryKey().notNull().getProperty();
workoutSwimSegmentsSample.addToOne(summaryEntity, id);
workoutSwimSegmentsSample.addIntProperty("segmentIndex").notNull().primaryKey();
workoutSwimSegmentsSample.addIntProperty("distance").notNull().primaryKey();
workoutSwimSegmentsSample.addByteProperty("type").notNull().primaryKey();
workoutSwimSegmentsSample.addIntProperty("pace").notNull();
workoutSwimSegmentsSample.addIntProperty("pointIndex").notNull();
workoutSwimSegmentsSample.addIntProperty("segment").notNull();
workoutSwimSegmentsSample.addByteProperty("swimType").notNull();
workoutSwimSegmentsSample.addIntProperty("strokes").notNull();
workoutSwimSegmentsSample.addIntProperty("avgSwolf").notNull();
workoutSwimSegmentsSample.addIntProperty("time").notNull();
return workoutSwimSegmentsSample;
}
private static void addTemperatureProperties(Entity activitySample) {
activitySample.addFloatProperty(SAMPLE_TEMPERATURE).notNull().codeBeforeGetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_TEMPERATURE_TYPE).notNull().codeBeforeGetter(OVERRIDE);

View File

@ -0,0 +1,22 @@
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.HuaweiWorkoutSummarySampleDao;
public class GadgetbridgeUpdate_85 implements DBUpdateScript {
@Override
public void upgradeSchema(final SQLiteDatabase db) {
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.SwimType.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.SwimType.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
}
@Override
public void downgradeSchema(final SQLiteDatabase db) {
}
}

View File

@ -50,6 +50,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSwimSegmentsSampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -124,6 +125,10 @@ public class HuaweiCoordinator {
session.getHuaweiWorkoutPaceSampleDao().queryBuilder().where(
HuaweiWorkoutPaceSampleDao.Properties.WorkoutId.eq(sample.getWorkoutId())
).buildDelete().executeDeleteWithoutDetachingEntities();
session.getHuaweiWorkoutSwimSegmentsSampleDao().queryBuilder().where(
HuaweiWorkoutSwimSegmentsSampleDao.Properties.WorkoutId.eq(sample.getWorkoutId())
).buildDelete().executeDeleteWithoutDetachingEntities();
}
session.getHuaweiWorkoutSummarySampleDao().queryBuilder().where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();

View File

@ -570,6 +570,8 @@ public class HuaweiPacket {
return new Workout.WorkoutData.Response(paramsProvider).fromPacket(this);
case Workout.WorkoutPace.id:
return new Workout.WorkoutPace.Response(paramsProvider).fromPacket(this);
case Workout.WorkoutSwimSegments.id:
return new Workout.WorkoutSwimSegments.Response(paramsProvider).fromPacket(this);
default:
this.isEncrypted = this.attemptDecrypt(); // Helps with debugging
return this;

View File

@ -58,6 +58,8 @@ public class Workout {
public short workoutNumber;
public short dataCount;
public short paceCount;
public short segmentsCount = 0;
}
public short count;
@ -84,6 +86,9 @@ public class Workout {
workoutNumber.workoutNumber = subContainerTlv.getShort(0x06);
workoutNumber.dataCount = subContainerTlv.getShort(0x07);
workoutNumber.paceCount = subContainerTlv.getShort(0x08);
if(subContainerTlv.contains(0x09)) {
workoutNumber.segmentsCount = subContainerTlv.getShort(0x09);
}
this.workoutNumbers.add(workoutNumber);
}
}
@ -143,6 +148,8 @@ public class Workout {
public byte[] recoveryHeartRates = null;
public byte swimType = -1;
public Response(ParamsProvider paramsProvider) {
super(paramsProvider);
@ -184,7 +191,8 @@ public class Workout {
this.duration = container.getInteger(0x12);
if (container.contains(0x14))
this.type = container.getByte(0x14);
// TODO: I'm guessing 0x15 is Main style for swimming, but cannot confirm.
if (container.contains(0x15))
this.swimType = container.getByte(0x15);
if (container.contains(0x16))
this.strokes = container.getShort(0x16);
if (container.contains(0x17))
@ -565,6 +573,100 @@ public class Workout {
}
}
public static class WorkoutSwimSegments {
public static final int id = 0x0e;
public static class Request extends HuaweiPacket {
public Request(
ParamsProvider paramsProvider,
short workoutNumber,
short segmentNumber
) {
super(paramsProvider);
this.serviceId = Workout.id;
this.commandId = id;
this.tlv = new HuaweiTLV().put(0x81, new HuaweiTLV()
.put(0x02, workoutNumber)
.put(0x08, segmentNumber)
);
this.complete = true;
}
}
public static class Response extends HuaweiPacket {
public static class Block {
public short distance = -1;
public byte type = -1;
public int pace = -1;
public short pointIndex = 0;
public short segment = -1;
public byte swimType= -1;
public short strokes = -1;
public short avgSwolf = -1;
public int time= -1;
@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();
}
}
public short workoutNumber;
public short segmentNumber;
public List<Block> blocks;
public Response(ParamsProvider paramsProvider) {
super(paramsProvider);
}
@Override
public void parseTlv() throws ParseException {
HuaweiTLV container = this.tlv.getObject(0x81);
this.workoutNumber = container.getShort(0x02);
this.segmentNumber = container.getShort(0x08);
this.blocks = new ArrayList<>();
for (HuaweiTLV blockTlv : container.getObjects(0x83)) {
Block block = new Block();
block.distance = blockTlv.getShort(0x04);
block.type = blockTlv.getByte(0x05);
block.pace = blockTlv.getInteger(0x06);
if (blockTlv.contains(0x07))
block.pointIndex = blockTlv.getShort(0x07);
if (blockTlv.contains(0x09))
block.segment = blockTlv.getShort(0x09);
if (blockTlv.contains(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);
blocks.add(block);
}
}
}
}
public static class NotifyHeartRate {
public static final int id = 0x17;

View File

@ -74,6 +74,8 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSwimSegmentsSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSwimSegmentsSampleDao;
import nodomain.freeyourgadget.gadgetbridge.export.ActivityTrackExporter;
import nodomain.freeyourgadget.gadgetbridge.export.GPXExporter;
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationProviderType;
@ -1646,7 +1648,8 @@ public class HuaweiSupportProvider {
packet.recoveryTime,
packet.minHeartRatePeak,
packet.maxHeartRatePeak,
recoveryHeartRates
recoveryHeartRates,
packet.swimType
);
db.getDaoSession().getHuaweiWorkoutSummarySampleDao().insertOrReplace(summarySample);
@ -1735,6 +1738,44 @@ public class HuaweiSupportProvider {
}
}
public void addWorkoutSwimSegmentsData(Long workoutId, List<Workout.WorkoutSwimSegments.Response.Block> paceList, short number) {
if (workoutId == null)
return;
try (DBHandler db = GBApplication.acquireDB()) {
HuaweiWorkoutSwimSegmentsSampleDao dao = db.getDaoSession().getHuaweiWorkoutSwimSegmentsSampleDao();
if(number == 0) {
final DeleteQuery<HuaweiWorkoutSwimSegmentsSample> tableDeleteQuery = dao.queryBuilder()
.where(HuaweiWorkoutSwimSegmentsSampleDao.Properties.WorkoutId.eq(workoutId))
.buildDelete();
tableDeleteQuery.executeDeleteWithoutDetachingEntities();
}
int paceIndex = (int) dao.queryBuilder().where(HuaweiWorkoutSwimSegmentsSampleDao.Properties.WorkoutId.eq(workoutId)).count();
for (Workout.WorkoutSwimSegments.Response.Block block : paceList) {
HuaweiWorkoutSwimSegmentsSample swimSectionSample = new HuaweiWorkoutSwimSegmentsSample(
workoutId,
paceIndex++,
block.distance,
block.type,
block.pace,
block.pointIndex,
block.segment,
block.swimType,
block.strokes,
block.avgSwolf,
block.time
);
dao.insertOrReplace(swimSectionSample);
}
} catch (Exception e) {
LOG.error("Failed to add workout swim section data to database", e);
}
}
public void setWearLocation() {
try {
SetWearLocationRequest setWearLocationReq = new SetWearLocationRequest(this);

View File

@ -22,9 +22,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@ -50,6 +50,8 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSwimSegmentsSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSwimSegmentsSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
@ -310,6 +312,20 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
return ActivityKind.UNKNOWN;
}
private String getSwimStyle(byte swimType) {
switch (swimType) {
case 1:
return "breaststroke";
case 3:
return "butterfly";
case 4:
return "backstroke";
case 5:
return "medley";
}
return "freestyle";
}
public void parseWorkout(Long workoutId) {
LOG.debug("Parsing workout ID {}", workoutId);
if (workoutId == null)
@ -361,6 +377,10 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
HuaweiWorkoutPaceSampleDao.Properties.WorkoutId.eq(summary.getWorkoutId())
);
QueryBuilder<HuaweiWorkoutSwimSegmentsSample> qbSegments = session.getHuaweiWorkoutSwimSegmentsSampleDao().queryBuilder().orderAsc(HuaweiWorkoutSwimSegmentsSampleDao.Properties.SegmentIndex).where(
HuaweiWorkoutSwimSegmentsSampleDao.Properties.WorkoutId.eq(summary.getWorkoutId())
);
ActivityKind type = huaweiTypeToGbType(summary.getType());
ActivitySummaryData summaryData = new ActivitySummaryData();
@ -376,11 +396,6 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
summaryData.add(ActivitySummaryEntries.STROKES, summary.getStrokes(), ActivitySummaryEntries.UNIT_STROKES);
}
if (summary.getAvgStrokeRate() != -1) {
// TODO: find out unit
summaryData.add(ActivitySummaryEntries.STROKE_RATE_AVG, summary.getAvgStrokeRate(), ActivitySummaryEntries.UNIT_NONE);
}
if (summary.getPoolLength() != -1) {
summaryData.add(ActivitySummaryEntries.LANE_LENGTH, summary.getPoolLength(), ActivitySummaryEntries.UNIT_CM);
}
@ -389,10 +404,6 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
summaryData.add(ActivitySummaryEntries.LAPS, summary.getLaps(), ActivitySummaryEntries.UNIT_LAPS);
}
if (summary.getAvgSwolf() != -1) {
summaryData.add(ActivitySummaryEntries.SWOLF_AVG, summary.getAvgSwolf(), ActivitySummaryEntries.UNIT_NONE);
}
if(summary.getWorkoutLoad() > 0) {
summaryData.add(ActivitySummaryEntries.WORKOUT_LOAD, summary.getWorkoutLoad(), ActivitySummaryEntries.UNIT_NONE);
}
@ -409,6 +420,10 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
summaryData.add(ActivitySummaryEntries.RECOVERY_TIME, summary.getRecoveryTime() / 60.0, ActivitySummaryEntries.UNIT_HOURS);
}
if(summary.getSwimType() != -1) {
summaryData.add(ActivitySummaryEntries.SWIM_STYLE, getSwimStyle(summary.getSwimType()));
}
Integer summaryMinAltitude = summary.getMinAltitude();
Integer summaryMaxAltitude = summary.getMaxAltitude();
Integer elevationGain = summary.getElevationGain();
@ -417,6 +432,10 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
int minHeartRatePeak = summary.getMinHeartRatePeak() & 0xff;
int maxHeartRatePeak = summary.getMaxHeartRatePeak() & 0xff;
int avgStrokeRate = summary.getAvgStrokeRate();
int avgSwolf = summary.getAvgSwolf();
boolean unknownData = false;
if (!dataSamples.isEmpty()) {
int speed = 0;
@ -640,12 +659,17 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
}
if (swolfCount > 0) {
summaryData.add(ActivitySummaryEntries.SWOLF_AVG, swolf, ActivitySummaryEntries.UNIT_NONE);
if(avgSwolf == -1) {
avgSwolf = swolf;
}
summaryData.add(ActivitySummaryEntries.SWOLF_MAX, maxSwolf, ActivitySummaryEntries.UNIT_NONE);
summaryData.add(ActivitySummaryEntries.SWOLF_MIN, minSwolf, ActivitySummaryEntries.UNIT_NONE);
}
if (strokeRateCount > 0) {
if(avgStrokeRate == -1) {
avgStrokeRate = strokeRate;
}
// TODO: find out unit?
summaryData.add(ActivitySummaryEntries.STROKE_RATE_AVG, strokeRate, ActivitySummaryEntries.UNIT_NONE);
@ -695,6 +719,14 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
}
}
if(avgSwolf > 0) {
summaryData.add(ActivitySummaryEntries.SWOLF_AVG, avgSwolf, ActivitySummaryEntries.UNIT_NONE);
}
if (avgStrokeRate > 0) {
summaryData.add(ActivitySummaryEntries.STROKE_RATE_AVG, avgStrokeRate, ActivitySummaryEntries.UNIT_STROKES_PER_MINUTE);
}
if (minHeartRatePeak > 0) {
summaryData.add(ActivitySummaryEntries.HR_MIN, minHeartRatePeak, ActivitySummaryEntries.UNIT_BPM);
}
@ -816,6 +848,69 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
}
}
final LinkedHashMap<String, ActivitySummaryTableRowEntry> segmentsTable = new LinkedHashMap<>();
try (CloseableListIterator<HuaweiWorkoutSwimSegmentsSample> it = qbSegments.build().listIterator()) {
int currentIndex = 1;
int tableIndex = 1;
while (it.hasNext()) {
HuaweiWorkoutSwimSegmentsSample sample = it.next();
if (sample.getType() != unitType)
continue;
final List<ActivitySummaryValue> columns = new LinkedList<>();
// TODO: add proper units for type == 1. MILES
columns.add(new ActivitySummaryValue(currentIndex++, ActivitySummaryEntries.UNIT_NONE));
columns.add(new ActivitySummaryValue(getSwimStyle(sample.getSwimType()), ActivitySummaryEntries.UNIT_NONE));
columns.add(new ActivitySummaryValue(sample.getDistance(), ActivitySummaryEntries.UNIT_METERS));
columns.add(new ActivitySummaryValue(sample.getTime(), ActivitySummaryEntries.UNIT_SECONDS));
segmentsTable.put("segments_table_" + tableIndex++,
new ActivitySummaryTableRowEntry(
ActivitySummaryEntries.GROUP_PACE,
columns,
true,
true
)
);
final List<ActivitySummaryValue> columns2 = new LinkedList<>();
// TODO: add proper units for type == 1. MILES and SECONDS PER MILE
columns2.add(new ActivitySummaryValue("", ActivitySummaryEntries.UNIT_NONE));
columns2.add(new ActivitySummaryValue(sample.getStrokes(), ActivitySummaryEntries.UNIT_STROKES));
columns2.add(new ActivitySummaryValue(sample.getAvgSwolf(), ActivitySummaryEntries.UNIT_NONE));
columns2.add(new ActivitySummaryValue(sample.getPace(), ActivitySummaryEntries.UNIT_NONE)); //TODO: seconds / 100 meters
segmentsTable.put("segments_table_" + tableIndex++,
new ActivitySummaryTableRowEntry(
ActivitySummaryEntries.GROUP_PACE,
columns2,
false,
false
)
);
segmentsTable.put("segments_table_" + tableIndex++,
new ActivitySummaryTableRowEntry(
ActivitySummaryEntries.GROUP_PACE,
new ArrayList<>(),
false,
false
)
);
}
if (!segmentsTable.isEmpty()) {
for (final Map.Entry<String, ActivitySummaryTableRowEntry> e : segmentsTable.entrySet()) {
summaryData.add(e.getKey(), e.getValue());
}
}
}
if (unknownData) {
summaryData.add(
GBApplication.getContext().getString(R.string.unknownDataEncountered),

View File

@ -112,6 +112,16 @@ public class GetWorkoutDataRequest extends Request {
);
nextRequest.setFinalizeReq(this.finalizeReq);
this.nextRequest(nextRequest);
} else if (this.workoutNumbers.segmentsCount > 0) {
GetWorkoutSwimSegmentsRequest nextRequest = new GetWorkoutSwimSegmentsRequest(
this.supportProvider,
this.workoutNumbers,
this.remainder,
(short) 0,
this.databaseId
);
nextRequest.setFinalizeReq(this.finalizeReq);
this.nextRequest(nextRequest);
} else {
new HuaweiWorkoutGbParser(getDevice()).parseWorkout(this.databaseId);
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {

View File

@ -89,7 +89,17 @@ public class GetWorkoutPaceRequest extends Request {
);
nextRequest.setFinalizeReq(this.finalizeReq);
this.nextRequest(nextRequest);
} else {
} else if (this.workoutNumbers.segmentsCount > 0) {
GetWorkoutSwimSegmentsRequest nextRequest = new GetWorkoutSwimSegmentsRequest(
this.supportProvider,
this.workoutNumbers,
this.remainder,
(short) 0,
this.databaseId
);
nextRequest.setFinalizeReq(this.finalizeReq);
this.nextRequest(nextRequest);
} else {
new HuaweiWorkoutGbParser(getDevice()).parseWorkout(this.databaseId);
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {
@Override

View File

@ -0,0 +1,102 @@
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 GetWorkoutSwimSegmentsRequest extends Request {
private static final Logger LOG = LoggerFactory.getLogger(GetWorkoutSwimSegmentsRequest.class);
Workout.WorkoutCount.Response.WorkoutNumbers workoutNumbers;
List<Workout.WorkoutCount.Response.WorkoutNumbers> remainder;
short number;
Long databaseId;
public GetWorkoutSwimSegmentsRequest(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.WorkoutSwimSegments.id;
this.workoutNumbers = workoutNumbers;
this.remainder = remainder;
this.number = number;
this.databaseId = databaseId;
}
@Override
protected List<byte[]> createRequest() throws RequestCreationException {
try {
return new Workout.WorkoutSwimSegments.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.WorkoutSwimSegments.Response))
throw new ResponseTypeMismatchException(receivedPacket, Workout.WorkoutSwimSegments.Response.class);
Workout.WorkoutSwimSegments.Response packet = (Workout.WorkoutSwimSegments.Response) receivedPacket;
if (packet.workoutNumber != this.workoutNumbers.workoutNumber)
throw new WorkoutParseException("Incorrect workout number!");
if (packet.segmentNumber != this.number)
throw new WorkoutParseException("Incorrect pace number!");
LOG.info("Workout {} segment {}:", this.workoutNumbers.workoutNumber, this.number);
LOG.info("Workout : " + packet.workoutNumber);
LOG.info("Segments : " + packet.segmentNumber);
LOG.info("Block num: " + packet.blocks.size());
LOG.info("Blocks : " + Arrays.toString(packet.blocks.toArray()));
supportProvider.addWorkoutSwimSegmentsData(this.databaseId, packet.blocks, packet.segmentNumber);
if (this.workoutNumbers.segmentsCount > this.number + 1) {
GetWorkoutSwimSegmentsRequest nextRequest = new GetWorkoutSwimSegmentsRequest(
this.supportProvider,
this.workoutNumbers,
this.remainder,
(short) (this.number + 1),
this.databaseId
);
nextRequest.setFinalizeReq(this.finalizeReq);
this.nextRequest(nextRequest);
} else {
new HuaweiWorkoutGbParser(getDevice()).parseWorkout(this.databaseId);
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, this.databaseId, new Runnable() {
@Override
public void run() {
if (!remainder.isEmpty()) {
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
GetWorkoutSwimSegmentsRequest.this.supportProvider,
remainder.remove(0),
remainder
);
nextRequest.setFinalizeReq(GetWorkoutSwimSegmentsRequest.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();
}
}
});
}
}
}

View File

@ -103,7 +103,17 @@ public class GetWorkoutTotalsRequest extends Request {
);
nextRequest.setFinalizeReq(this.finalizeReq);
this.nextRequest(nextRequest);
} else {
} else if (this.workoutNumbers.segmentsCount > 0) {
GetWorkoutSwimSegmentsRequest nextRequest = new GetWorkoutSwimSegmentsRequest(
this.supportProvider,
this.workoutNumbers,
this.remainder,
(short) 0,
databaseId
);
nextRequest.setFinalizeReq(this.finalizeReq);
this.nextRequest(nextRequest);
} else {
new HuaweiWorkoutGbParser(getDevice()).parseWorkout(databaseId);
supportProvider.downloadWorkoutGpsFiles(this.workoutNumbers.workoutNumber, databaseId, new Runnable() {
@Override