Huawei: Collect and process more workout data: HRZones, RunPaceZones

This commit is contained in:
Me7c7 2024-11-26 17:37:19 +02:00 committed by José Rebelo
parent 48a6e1aa95
commit 7b8f02ec29
11 changed files with 344 additions and 51 deletions

View File

@ -54,7 +54,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
final Schema schema = new Schema(88, MAIN_PACKAGE + ".entities");
final Schema schema = new Schema(89, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@ -1411,6 +1411,26 @@ public class GBDaoGenerator {
workoutSummary.addByteProperty("swimType").notNull();
workoutSummary.addIntProperty("maxMET").notNull();
workoutSummary.addByteProperty("hrZoneType").notNull();
workoutSummary.addShortProperty("runPaceZone1Min").notNull();
workoutSummary.addShortProperty("runPaceZone2Min").notNull();
workoutSummary.addShortProperty("runPaceZone3Min").notNull();
workoutSummary.addShortProperty("runPaceZone4Min").notNull();
workoutSummary.addShortProperty("runPaceZone5Min").notNull();
workoutSummary.addShortProperty("runPaceZone5Max").notNull();
workoutSummary.addShortProperty("runPaceZone1Time").notNull();
workoutSummary.addShortProperty("runPaceZone2Time").notNull();
workoutSummary.addShortProperty("runPaceZone3Time").notNull();
workoutSummary.addShortProperty("runPaceZone4Time").notNull();
workoutSummary.addShortProperty("runPaceZone5Time").notNull();
workoutSummary.addByteProperty("algType").notNull();
workoutSummary.addIntProperty("trainingPoints").notNull();
return workoutSummary;
}

View File

@ -0,0 +1,93 @@
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_89 implements DBUpdateScript {
@Override
public void upgradeSchema(final SQLiteDatabase db) {
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.MaxMET.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.MaxMET.columnName + "\" INTEGER NOT NULL DEFAULT 0;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.HrZoneType.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.HrZoneType.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone1Min.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone1Min.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone2Min.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone2Min.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone3Min.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone3Min.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone4Min.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone4Min.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone5Min.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone5Min.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone5Max.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone5Max.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone1Time.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone1Time.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone2Time.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone2Time.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone3Time.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone3Time.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone4Time.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone4Time.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone5Time.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.RunPaceZone5Time.columnName + "\" INTEGER NOT NULL DEFAULT -1;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.AlgType.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.AlgType.columnName + "\" INTEGER NOT NULL DEFAULT 0;";
db.execSQL(statement);
}
if (!DBHelper.existsColumn(HuaweiWorkoutSummarySampleDao.TABLENAME, HuaweiWorkoutSummarySampleDao.Properties.TrainingPoints.columnName, db)) {
final String statement = "ALTER TABLE " + HuaweiWorkoutSummarySampleDao.TABLENAME + " ADD COLUMN \""
+ HuaweiWorkoutSummarySampleDao.Properties.TrainingPoints.columnName + "\" INTEGER NOT NULL DEFAULT 0;";
db.execSQL(statement);
}
}
@Override
public void downgradeSchema(final SQLiteDatabase db) {
}
}

View File

@ -11,12 +11,16 @@ public class HeartRateZonesConfig {
public static final int TYPE_SWIMMING = 3;
public static final int TYPE_OTHER = 4;
public static final int CALCULATE_METHOD_MHR = 0;
public static final int CALCULATE_METHOD_HRR = 1;
public static final int CALCULATE_METHOD_LTHR = 3;
private static final int DEFAULT_REST_HEART_RATE = 60;
public static final int MAXIMUM_HEART_RATE = 220;
private final int configType;
private int calculateMethod = 0; // 0 - MHR, 1 - HRR, 3 - LTHR
private int calculateMethod = CALCULATE_METHOD_MHR; // 0 - MHR, 1 - HRR, 3 - LTHR
private int maxHRThreshold;
private int restHeartRate = DEFAULT_REST_HEART_RATE;
@ -262,4 +266,22 @@ public class HeartRateZonesConfig {
return getZoneForHR(heartRate, LTHRAnaerobic, LTHRLactate, LTHRAdvancedAerobic, LTHRBasicAerobic, LTHRWarmUp);
}
public int getZoneByMethod(int heartRate, int method) {
if(method == CALCULATE_METHOD_LTHR) {
return getLTHRZone(heartRate);
} else if(method == CALCULATE_METHOD_MHR) {
return getMHRZone(heartRate);
}
return getHHRZone(heartRate);
}
public static boolean isCalculateMethodValidFroType(int type, int method) {
if(method == CALCULATE_METHOD_LTHR && type == TYPE_UPRIGHT) {
return true;
}
return (method == CALCULATE_METHOD_MHR) || (method == CALCULATE_METHOD_HRR);
}
}

View File

@ -0,0 +1,62 @@
package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
// TODO: make this configurable
// NOTE: algorithms used in this class are generic. So this data can be used with other devices.
// We can move this class to global scope.
public class HuaweiRunPaceConfig {
private int zone5HIITRunMax = 300;
private int zone5HIITRunMin = 330;
private int zone4AnaerobicMin = 360;
private int zone3LactateThresholdMin = 390;
private int zone2MarathonMin = 420;
private int zone1JogMin = 450;
public int getZone5HIITRunMax() {
return zone5HIITRunMax;
}
public void setZone5HIITRunMax(int zone5HIITRunMax) {
this.zone5HIITRunMax = zone5HIITRunMax;
}
public int getZone5HIITRunMin() {
return zone5HIITRunMin;
}
public void setZone5HIITRunMin(int zone5HIITRunMin) {
this.zone5HIITRunMin = zone5HIITRunMin;
}
public int getZone4AnaerobicMin() {
return zone4AnaerobicMin;
}
public void setZone4AnaerobicMin(int zone4AnaerobicMin) {
this.zone4AnaerobicMin = zone4AnaerobicMin;
}
public int getZone3LactateThresholdMin() {
return zone3LactateThresholdMin;
}
public void setZone3LactateThresholdMin(int zone3LactateThresholdMin) {
this.zone3LactateThresholdMin = zone3LactateThresholdMin;
}
public int getZone2MarathonMin() {
return zone2MarathonMin;
}
public void setZone2MarathonMin(int zone2MarathonMin) {
this.zone2MarathonMin = zone2MarathonMin;
}
public int getZone1JogMin() {
return zone1JogMin;
}
public void setZone1JogMin(int zone1JogMin) {
this.zone1JogMin = zone1JogMin;
}
}

View File

@ -2,26 +2,26 @@ package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
public class HuaweiSportHRZones {
private final HeartRateZonesConfig otherHRZonesConfig;
private final HeartRateZonesConfig SittingHRZonesConfig;
private final HeartRateZonesConfig UprightHRZonesConfig;
private final HeartRateZonesConfig SwimmingHRZonesConfig;
private final HeartRateZonesConfig sittingHRZonesConfig;
private final HeartRateZonesConfig uprightHRZonesConfig;
private final HeartRateZonesConfig swimmingHRZonesConfig;
public HuaweiSportHRZones(int age) {
this.UprightHRZonesConfig = new HeartRateZonesConfig(HeartRateZonesConfig.TYPE_UPRIGHT, age);
this.SittingHRZonesConfig = new HeartRateZonesConfig(HeartRateZonesConfig.TYPE_SITTING, age);
this.SwimmingHRZonesConfig = new HeartRateZonesConfig(HeartRateZonesConfig.TYPE_SWIMMING, age);
this.uprightHRZonesConfig = new HeartRateZonesConfig(HeartRateZonesConfig.TYPE_UPRIGHT, age);
this.sittingHRZonesConfig = new HeartRateZonesConfig(HeartRateZonesConfig.TYPE_SITTING, age);
this.swimmingHRZonesConfig = new HeartRateZonesConfig(HeartRateZonesConfig.TYPE_SWIMMING, age);
this.otherHRZonesConfig = new HeartRateZonesConfig(HeartRateZonesConfig.TYPE_OTHER, age);
}
public HeartRateZonesConfig getHRZonesConfigByType(int type) {
if (type == HeartRateZonesConfig.TYPE_SITTING) {
return this.SittingHRZonesConfig;
return this.sittingHRZonesConfig;
} else if (type == HeartRateZonesConfig.TYPE_SWIMMING) {
return this.SwimmingHRZonesConfig;
return this.swimmingHRZonesConfig;
} else if (type == HeartRateZonesConfig.TYPE_OTHER) {
return this.otherHRZonesConfig;
}
return this.UprightHRZonesConfig;
return this.uprightHRZonesConfig;
}
public byte[] getHRZonesData() {

View File

@ -23,6 +23,7 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HeartRateZonesConfig;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiReportThreshold;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiRunPaceConfig;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV;
public class FitnessData {
@ -741,25 +742,19 @@ public class FitnessData {
public static final byte id = 0x28;
public static class Request extends HuaweiPacket {
public Request(ParamsProvider paramsProvider,
int easyPaceZoneMinValue,
int marathonPaceZoneMinValue,
int lactatePaceZoneMinValue,
int anaerobicPaceZoneMinValue,
int maxOxygenPaceZoneMinValue,
int maxOxygenPaceZoneMaxValue) {
public Request(ParamsProvider paramsProvider, final HuaweiRunPaceConfig runPaceConfig) {
super(paramsProvider);
this.serviceId = FitnessData.id;
this.commandId = id;
this.tlv = new HuaweiTLV()
.put(0x01, (short) easyPaceZoneMinValue)
.put(0x02, (short) marathonPaceZoneMinValue)
.put(0x03, (short) lactatePaceZoneMinValue)
.put(0x04, (short) anaerobicPaceZoneMinValue)
.put(0x05, (short) maxOxygenPaceZoneMinValue)
.put(0x06, (short) maxOxygenPaceZoneMaxValue);
.put(0x01, (short) runPaceConfig.getZone1JogMin())
.put(0x02, (short) runPaceConfig.getZone2MarathonMin())
.put(0x03, (short) runPaceConfig.getZone3LactateThresholdMin())
.put(0x04, (short) runPaceConfig.getZone4AnaerobicMin())
.put(0x05, (short) runPaceConfig.getZone5HIITRunMin())
.put(0x06, (short) runPaceConfig.getZone5HIITRunMax());
this.complete = true;
}
}

View File

@ -154,6 +154,26 @@ public class Workout {
public byte swimType = -1;
public int maxMET = 0;
public byte hrZoneType = -1;
public short runPaceZone1Min = -1;
public short runPaceZone2Min = -1;
public short runPaceZone3Min = -1;
public short runPaceZone4Min = -1;
public short runPaceZone5Min = -1;
public short runPaceZone5Max = -1;
public short runPaceZone1Time = -1;
public short runPaceZone2Time = -1;
public short runPaceZone3Time = -1;
public short runPaceZone4Time = -1;
public short runPaceZone5Time = -1;
public byte algType = 0;
public int trainingPoints = -1;
public Response(ParamsProvider paramsProvider) {
super(paramsProvider);
@ -189,6 +209,8 @@ public class Workout {
this.workoutLoad = container.getInteger(0x0d);
if (container.contains(0x0e))
this.workoutAerobicEffect = container.getInteger(0x0e);
if (container.contains(0x10))
this.maxMET = container.getInteger(0x10);
if (container.contains(0x11))
this.recoveryTime = container.getShort(0x11);
if (container.contains(0x12))
@ -215,9 +237,36 @@ public class Workout {
this.minAltitude = container.getInteger(0x1d);
if (container.contains(0x20))
this.workoutAnaerobicEffect = container.getByte(0x20);
if (container.contains(0x24))
this.hrZoneType = container.getByte(0x24);
if (container.contains(0x50))
this.runPaceZone1Min = container.getShort(0x50);
if (container.contains(0x51))
this.runPaceZone2Min = container.getShort(0x51);
if (container.contains(0x52))
this.runPaceZone3Min = container.getShort(0x52);
if (container.contains(0x53))
this.runPaceZone4Min = container.getShort(0x53);
if (container.contains(0x54))
this.runPaceZone5Min = container.getShort(0x54);
if (container.contains(0x55))
this.runPaceZone5Max = container.getShort(0x55);
if (container.contains(0x56))
this.runPaceZone1Time = container.getShort(0x56);
if (container.contains(0x57))
this.runPaceZone2Time = container.getShort(0x57);
if (container.contains(0x58))
this.runPaceZone3Time = container.getShort(0x58);
if (container.contains(0x59))
this.runPaceZone4Time = container.getShort(0x59);
if (container.contains(0x5a))
this.runPaceZone5Time = container.getShort(0x5a);
if (container.contains(0x5d))
this.algType = container.getByte(0x5d);
if (container.contains(0x63))
this.trainingPoints = container.getShort(0x63);
if (container.contains(0x66))
this.recoveryHeartRates = container.getBytes(0x66);
}
}
}

View File

@ -1649,8 +1649,25 @@ public class HuaweiSupportProvider {
packet.minHeartRatePeak,
packet.maxHeartRatePeak,
recoveryHeartRates,
packet.swimType
packet.swimType,
packet.maxMET,
packet.hrZoneType,
packet.runPaceZone1Min,
packet.runPaceZone2Min,
packet.runPaceZone3Min,
packet.runPaceZone4Min,
packet.runPaceZone5Min,
packet.runPaceZone5Max,
packet.runPaceZone1Time,
packet.runPaceZone2Time,
packet.runPaceZone3Time,
packet.runPaceZone4Time,
packet.runPaceZone5Time,
packet.algType,
packet.trainingPoints
);
db.getDaoSession().getHuaweiWorkoutSummarySampleDao().insertOrReplace(summarySample);
return summarySample.getWorkoutId();

View File

@ -395,7 +395,7 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
summaryData.add(ActivitySummaryEntries.DISTANCE_METERS, summary.getDistance(), ActivitySummaryEntries.UNIT_METERS);
summaryData.add(ActivitySummaryEntries.STEPS, summary.getStepCount(), ActivitySummaryEntries.UNIT_STEPS);
summaryData.add(ActivitySummaryEntries.ACTIVE_SECONDS, summary.getDuration(), ActivitySummaryEntries.UNIT_SECONDS);
summaryData.add(ActivitySummaryEntries.STATUS, summary.getStatus() & 0xFF, ActivitySummaryEntries.UNIT_NONE);
//summaryData.add(ActivitySummaryEntries.STATUS, summary.getStatus() & 0xFF, ActivitySummaryEntries.UNIT_NONE);
summaryData.add(ActivitySummaryEntries.TYPE, summary.getType() & 0xFF, ActivitySummaryEntries.UNIT_NONE);
if (summary.getStrokes() != -1) {
@ -492,15 +492,15 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
int sumAltitudeDown = 0;
//NOTE: The method of retrieving HR zones from the Huawei watch is not discovered. It may not return zones.
// So they are calculated based on config. Enabled only for running and walking activities for testing.
// Currently only calculated zones based on MHR.
// TODO: Use other methods after the configuration will be implemented. Use calculateMethod on HeartRateZonesConfig class.
// TODO: Enable for other workout types
// So they are calculated based on config.
HeartRateZonesConfig HRZonesCfg = null;
if( type == ActivityKind.WALKING || type == ActivityKind.RUNNING) {
Integer zoneType = HuaweiWorkoutUtils.getHRZoneTypeByActivity(type);
int zoneCalculateMethod = summary.getHrZoneType();
LOG.info("Workout HR Zone Calculate Type: {}", zoneCalculateMethod);
if(zoneType != null && HeartRateZonesConfig.isCalculateMethodValidFroType(zoneType, zoneCalculateMethod)) {
ActivityUser activityUser = new ActivityUser();
HuaweiSportHRZones hrSportZones = new HuaweiSportHRZones(activityUser.getAge());
HRZonesCfg = hrSportZones.getHRZonesConfigByType(HeartRateZonesConfig.TYPE_UPRIGHT);
HRZonesCfg = hrSportZones.getHRZonesConfigByType(zoneType);
}
int dataDelta = 5;
@ -514,7 +514,7 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
for (HuaweiWorkoutDataSample dataSample : dataSamples) {
if(HRZonesCfg != null) {
int zoneIdx = HRZonesCfg.getMHRZone(dataSample.getHeartRate() & 0xFF);
int zoneIdx = HRZonesCfg.getZoneByMethod(dataSample.getHeartRate() & 0xFF, zoneCalculateMethod);
if (zoneIdx != -1 && dataIdx < (dataSamples.size() - 1)) {
HRZones[zoneIdx] += dataDelta;
}
@ -627,7 +627,7 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
if(HRZonesCfg != null) {
final double totalTime = Arrays.stream(HRZones).sum();
final List<String> zoneOrder = Arrays.asList(ActivitySummaryEntries.HR_ZONE_WARM_UP, ActivitySummaryEntries.HR_ZONE_FAT_BURN, ActivitySummaryEntries.HR_ZONE_AEROBIC, ActivitySummaryEntries.HR_ZONE_ANAEROBIC, ActivitySummaryEntries.HR_ZONE_EXTREME);
for (int i = 0; i < zoneOrder.size(); i++) {
for (int i = zoneOrder.size() - 1; i >= 0; i--) {
double timeInZone = HRZones[i];
LOG.info("Zone: {} {}", zoneOrder.get(i), timeInZone);
summaryData.add(
@ -675,8 +675,6 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
}
if (stepRatePresent) {
summaryData.add(ActivitySummaryEntries.STEP_RATE_SUM, stepRate, ActivitySummaryEntries.UNIT_SPM);
summaryData.add(ActivitySummaryEntries.STEP_RATE_AVG, avgStepRate, ActivitySummaryEntries.UNIT_SPM);
}
@ -724,11 +722,7 @@ public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
if(avgStrokeRate == -1) {
avgStrokeRate = strokeRate;
}
// TODO: find out unit?
summaryData.add(ActivitySummaryEntries.STROKE_RATE_AVG, strokeRate, ActivitySummaryEntries.UNIT_NONE);
// TODO: find out unit?
summaryData.add(ActivitySummaryEntries.STROKE_RATE_MAX, maxStrokeRate, ActivitySummaryEntries.UNIT_NONE);
summaryData.add(ActivitySummaryEntries.STROKE_RATE_MAX, maxStrokeRate, ActivitySummaryEntries.UNIT_STROKES_PER_MINUTE);
}
if (heartRateCount > 0) {

View File

@ -0,0 +1,48 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HeartRateZonesConfig;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
public class HuaweiWorkoutUtils {
private static final Map<ActivityKind, Integer> activityHRZoneType = createActivityHRZoneType();
//TODO: discover and add more activity types. Should be same as in the watch.
private static Map<ActivityKind, Integer> createActivityHRZoneType() {
Map<ActivityKind, Integer> result = new HashMap<>();
result.put(ActivityKind.RUNNING, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.WALKING, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.CYCLING, HeartRateZonesConfig.TYPE_SITTING);
result.put(ActivityKind.MOUNTAIN_HIKE, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.INDOOR_RUNNING, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.POOL_SWIM, HeartRateZonesConfig.TYPE_SWIMMING);
result.put(ActivityKind.INDOOR_CYCLING, HeartRateZonesConfig.TYPE_SITTING);
result.put(ActivityKind.SWIMMING_OPENWATER, HeartRateZonesConfig.TYPE_SWIMMING);
result.put(ActivityKind.INDOOR_WALKING, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.HIKING, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.JUMP_ROPING, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.PINGPONG, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.BADMINTON, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.TENNIS, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.SOCCER, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.BASKETBALL, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.VOLLEYBALL, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.ELLIPTICAL_TRAINER, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.ROWING_MACHINE, HeartRateZonesConfig.TYPE_SITTING);
result.put(ActivityKind.STEPPER, HeartRateZonesConfig.TYPE_UPRIGHT);
result.put(ActivityKind.YOGA, HeartRateZonesConfig.TYPE_OTHER);
return Collections.unmodifiableMap(result);
}
public static Integer getHRZoneTypeByActivity(ActivityKind type) {
if(activityHRZoneType.containsKey(type)) {
return activityHRZoneType.get(type);
}
return null;
}
}

View File

@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiRunPaceConfig;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FitnessData;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider;
@ -26,15 +27,7 @@ public class SendRunPaceConfigRequest extends Request {
@Override
protected List<byte[]> createRequest() throws Request.RequestCreationException {
try {
//Hardcoded value till interface enable threshold values
return new FitnessData.RunPaceConfig.Request(paramsProvider,
0x1C2,
0x1A4,
0x186,
0x168,
0x14A,
0x12C
).serialize();
return new FitnessData.RunPaceConfig.Request(paramsProvider, new HuaweiRunPaceConfig()).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new Request.RequestCreationException(e);
}