mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-10 17:11:56 +01:00
Huawei: Collect and process more workout data: HRZones, RunPaceZones
This commit is contained in:
parent
48a6e1aa95
commit
7b8f02ec29
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user