mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-24 17:45:50 +01:00
Xiaomi: Outdoor Cycling and GPX fix for Smart Band 8 Active
This commit is contained in:
parent
32109507d9
commit
c01607dc06
@ -198,7 +198,7 @@ public class XiaomiActivityFileId implements Comparable<XiaomiActivityFileId> {
|
|||||||
SPORTS_OUTDOOR_RUNNING(Type.SPORTS, 0x01),
|
SPORTS_OUTDOOR_RUNNING(Type.SPORTS, 0x01),
|
||||||
SPORTS_OUTDOOR_WALKING_V1(Type.SPORTS, 0x02),
|
SPORTS_OUTDOOR_WALKING_V1(Type.SPORTS, 0x02),
|
||||||
SPORTS_TREADMILL(Type.SPORTS, 0x03),
|
SPORTS_TREADMILL(Type.SPORTS, 0x03),
|
||||||
SPORTS_OUTDOOR_CYCLING_V2(Type.SPORTS, 0x06), // TODO
|
SPORTS_OUTDOOR_CYCLING_V2(Type.SPORTS, 0x06),
|
||||||
SPORTS_INDOOR_CYCLING(Type.SPORTS, 0x07),
|
SPORTS_INDOOR_CYCLING(Type.SPORTS, 0x07),
|
||||||
SPORTS_FREESTYLE(Type.SPORTS, 0x08),
|
SPORTS_FREESTYLE(Type.SPORTS, 0x08),
|
||||||
SPORTS_POOL_SWIMMING(Type.SPORTS, 0x09),
|
SPORTS_POOL_SWIMMING(Type.SPORTS, 0x09),
|
||||||
|
@ -58,6 +58,9 @@ public class WorkoutGpsParser extends XiaomiActivityParser {
|
|||||||
final int sampleSize;
|
final int sampleSize;
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case 1:
|
case 1:
|
||||||
|
headerSize = 1;
|
||||||
|
sampleSize = 12;
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
headerSize = 1;
|
headerSize = 1;
|
||||||
sampleSize = 18;
|
sampleSize = 18;
|
||||||
@ -85,21 +88,34 @@ public class WorkoutGpsParser extends XiaomiActivityParser {
|
|||||||
|
|
||||||
final ActivityTrack activityTrack = new ActivityTrack();
|
final ActivityTrack activityTrack = new ActivityTrack();
|
||||||
|
|
||||||
while (buf.position() < buf.limit()) {
|
// GPS V1 contains no speed data, therefore second while loop to avoid too many ifs within the loop
|
||||||
final int ts = buf.getInt();
|
if (version == 1) {
|
||||||
final float longitude = buf.getFloat();
|
while (buf.position() < buf.limit()) {
|
||||||
final float latitude = buf.getFloat();
|
final int ts = buf.getInt();
|
||||||
final int unk1 = buf.getInt(); // 0
|
final float longitude = buf.getFloat();
|
||||||
final float speed = (buf.getShort() >> 2) / 10.0f;
|
final float latitude = buf.getFloat();
|
||||||
|
|
||||||
final ActivityPoint ap = new ActivityPoint(new Date(ts * 1000L));
|
final ActivityPoint ap = new ActivityPoint(new Date(ts * 1000L));
|
||||||
ap.setLocation(new GPSCoordinate(longitude, latitude, 0));
|
ap.setLocation(new GPSCoordinate(longitude, latitude, 0));
|
||||||
activityTrack.addTrackPoint(ap);
|
activityTrack.addTrackPoint(ap);
|
||||||
|
LOG.trace("ActivityPoint V1: ts={} lon={} lat={}", ts, longitude, latitude);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (buf.position() < buf.limit()) {
|
||||||
|
final int ts = buf.getInt();
|
||||||
|
final float longitude = buf.getFloat();
|
||||||
|
final float latitude = buf.getFloat();
|
||||||
|
final int unk1 = buf.getInt(); // 0
|
||||||
|
final float speed = (buf.getShort() >> 2) / 10.0f;
|
||||||
|
|
||||||
LOG.trace("ActivityPoint: ts={} lon={} lat={} unk1={} speed={}", ts, longitude, latitude, unk1, speed);
|
final ActivityPoint ap = new ActivityPoint(new Date(ts * 1000L));
|
||||||
|
ap.setLocation(new GPSCoordinate(longitude, latitude, 0));
|
||||||
|
activityTrack.addTrackPoint(ap);
|
||||||
|
LOG.trace("ActivityPoint: ts={} lon={} lat={} unk1={} speed={}", ts, longitude, latitude, unk1, speed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
final DaoSession session = dbHandler.getDaoSession();
|
final DaoSession session = dbHandler.getDaoSession();
|
||||||
final Device device = DBHelper.getDevice(support.getDevice(), session);
|
final Device device = DBHelper.getDevice(support.getDevice(), session);
|
||||||
final User user = DBHelper.getUser(session);
|
final User user = DBHelper.getUser(session);
|
||||||
|
@ -210,6 +210,10 @@ public class WorkoutSummaryParser extends XiaomiActivityParser implements Activi
|
|||||||
case SPORTS_OUTDOOR_WALKING_V2:
|
case SPORTS_OUTDOOR_WALKING_V2:
|
||||||
parser = getOutdoorWalkingV2Parser(fileId);
|
parser = getOutdoorWalkingV2Parser(fileId);
|
||||||
break;
|
break;
|
||||||
|
case SPORTS_OUTDOOR_CYCLING_V2:
|
||||||
|
summary.setActivityKind(ActivityKind.OUTDOOR_CYCLING.getCode());
|
||||||
|
parser = getOutdoorCyclingV2Parser(fileId);
|
||||||
|
break;
|
||||||
case SPORTS_OUTDOOR_CYCLING:
|
case SPORTS_OUTDOOR_CYCLING:
|
||||||
parser = getOutdoorCyclingParser(fileId);
|
parser = getOutdoorCyclingParser(fileId);
|
||||||
break;
|
break;
|
||||||
@ -277,7 +281,10 @@ public class WorkoutSummaryParser extends XiaomiActivityParser implements Activi
|
|||||||
if (version == 5) {
|
if (version == 5) {
|
||||||
builder.addUnknown(10);
|
builder.addUnknown(10);
|
||||||
builder.addShort(XIAOMI_WORKOUT_TYPE, UNIT_NONE);
|
builder.addShort(XIAOMI_WORKOUT_TYPE, UNIT_NONE);
|
||||||
builder.addUnknown(8);
|
builder.addUnknown(2);
|
||||||
|
builder.addUnknown(2); // configuredTimeGoal, UNIT_SECONDS
|
||||||
|
builder.addUnknown(2);
|
||||||
|
builder.addUnknown(2); // configuredCaloriesGoal, UNIT_KCAL
|
||||||
} else {
|
} else {
|
||||||
builder.addUnknown(2);
|
builder.addUnknown(2);
|
||||||
builder.addUnknown(4);
|
builder.addUnknown(4);
|
||||||
@ -749,4 +756,42 @@ public class WorkoutSummaryParser extends XiaomiActivityParser implements Activi
|
|||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private XiaomiSimpleActivityParser getOutdoorCyclingV2Parser(final XiaomiActivityFileId fileId) {
|
||||||
|
final int version = fileId.getVersion();
|
||||||
|
final int headerSize;
|
||||||
|
switch (version) {
|
||||||
|
case 4:
|
||||||
|
headerSize = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG.warn("Unable to parse workout summary version {}", fileId.getVersion());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final XiaomiSimpleActivityParser.Builder builder = new XiaomiSimpleActivityParser.Builder();
|
||||||
|
builder.setHeaderSize(headerSize);
|
||||||
|
builder.addInt(TIME_START, UNIT_UNIX_EPOCH_SECONDS);
|
||||||
|
builder.addInt(TIME_END, UNIT_UNIX_EPOCH_SECONDS);
|
||||||
|
builder.addInt(ACTIVE_SECONDS, UNIT_SECONDS);
|
||||||
|
builder.addInt(DISTANCE_METERS, UNIT_METERS);
|
||||||
|
builder.addShort(CALORIES_BURNT, UNIT_KCAL);
|
||||||
|
builder.addUnknown(8);
|
||||||
|
builder.addFloat(SPEED_MAX, UNIT_KMPH);
|
||||||
|
builder.addByte(HR_AVG, UNIT_BPM);
|
||||||
|
builder.addByte(HR_MAX, UNIT_BPM);
|
||||||
|
builder.addByte(HR_MIN, UNIT_BPM);
|
||||||
|
builder.addUnknown(28);
|
||||||
|
builder.addInt(HR_ZONE_EXTREME, UNIT_SECONDS);
|
||||||
|
builder.addInt(HR_ZONE_ANAEROBIC, UNIT_SECONDS);
|
||||||
|
builder.addInt(HR_ZONE_AEROBIC, UNIT_SECONDS);
|
||||||
|
builder.addInt(HR_ZONE_FAT_BURN, UNIT_SECONDS);
|
||||||
|
builder.addInt(HR_ZONE_WARM_UP, UNIT_SECONDS);
|
||||||
|
builder.addUnknown(18);
|
||||||
|
builder.addUnknown(2); // configuredTimeGoal, UNIT_SECONDS
|
||||||
|
builder.addUnknown(6);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user