1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-28 11:35:48 +01:00

Huawei: send more user info. Fix issue with weight

This commit is contained in:
Me7c7 2024-10-25 13:51:27 +03:00 committed by José Rebelo
parent e124ac4974
commit b18fb901e6
3 changed files with 174 additions and 38 deletions

View File

@ -584,6 +584,19 @@ public class HuaweiCoordinator {
return false;
}
public boolean supportsUnknownGender() {
if (supportsExpandCapability())
return supportsExpandCapability(0x57);
return false;
}
public boolean supportsPrecisionWeight() {
if (supportsExpandCapability())
return supportsExpandCapability(0xb3);
return false;
}
public boolean supportsPromptPushMessage () {
// do not ask for capabilities under specific condition
// if (deviceType == 10 && deviceVersion == 73617766697368 && deviceSoftVersion == 372E312E31) -> leo device

View File

@ -49,7 +49,7 @@ public class FitnessData {
.put(0x04, frameType);
stepGoal = ((Type.data & 0x01) != 0x00) ? stepGoal : 0xffffffff;
if (stepGoal != 0xffffffff)
subTlv.put(0x05, stepGoal);
subTlv.put(0x05, stepGoal);
int calorieGoalFinal = ((Type.data & 0x02) != 0x00) ? calorieGoal : 0xffffffff;
if (calorieGoalFinal != 0xffffffff) {
subTlv.put(0x06, calorieGoalFinal);
@ -75,31 +75,139 @@ public class FitnessData {
public static class UserInfo {
public static final byte id = 0x02;
public static class UserInfoData {
public static final int GENDER_MALE = 1;
public static final int GENDER_FEMALE = 2;
public static final int GENDER_UNKNOWN = 3;
private static final float RUN_CF = 0.83f;
private static final float WALK_CF = 0.42f;
public static final int DEFAULT_HEIGHT = 175;
public static final int DEFAULT_WEIGHT = 65;
private final int height;
private final float weight;
private final int age;
private final int birthday;
private final byte gender;
private final boolean unknownGenderSupported;
private final boolean vo2Supported;
private final int vo2Max;
private final int vo2Time;
private final boolean precisionWeightSupported;
public UserInfoData(int height, float weight, int age, int birthday, byte gender, boolean unknownGenderSupported, boolean vo2Supported, int vo2Max, int vo2Time, boolean precisionWeightSupported) {
this.height = height;
this.weight = weight;
this.age = age;
this.birthday = birthday;
this.gender = gender;
this.unknownGenderSupported = unknownGenderSupported;
this.vo2Supported = vo2Supported;
this.vo2Max = vo2Max;
this.vo2Time = vo2Time;
this.precisionWeightSupported = precisionWeightSupported;
}
public int getHeight() {
if (this.height > 0)
return this.height;
return DEFAULT_HEIGHT;
}
public float getWeight() {
if (this.weight > 0)
return this.weight;
return DEFAULT_WEIGHT;
}
public int getAge() {
return age;
}
public int getBirthday() {
return birthday;
}
public byte getGender() {
return gender;
}
public boolean isUnknownGenderSupported() {
return unknownGenderSupported;
}
public boolean isVo2Supported() {
return vo2Supported;
}
public int getVo2Max() {
return vo2Max;
}
public int getVo2Time() {
return vo2Time;
}
public boolean isPrecisionWeightSupported() {
return precisionWeightSupported;
}
public boolean isGenderValid() {
return this.gender == GENDER_MALE || this.gender == GENDER_FEMALE || this.gender == GENDER_UNKNOWN;
}
public boolean isBirthdayValid() {
return this.birthday > 0;
}
}
public static class Request extends HuaweiPacket {
public Request(ParamsProvider paramsProvider,
int height,
int weight,
int age,
int birthdayEncoded,
byte gender) {
public Request(ParamsProvider paramsProvider, UserInfoData info) {
super(paramsProvider);
this.serviceId = FitnessData.id;
this.commandId = id;
byte bmi1 = (byte)Math.round(0.42f * height);
byte bmi2 = (byte)Math.round(0.83f * height);
int height = info.getHeight();
float weight = info.getWeight();
byte bmiWalk = (byte) Math.round(UserInfoData.WALK_CF * height);
byte bmiRun = (byte) Math.round(UserInfoData.RUN_CF * height);
this.tlv = new HuaweiTLV()
.put(0x01, (byte)height)
.put(0x02, (byte)weight)
.put(0x03, (byte)age)
.put(0x04, birthdayEncoded)
.put(0x05, gender)
.put(0x06, bmi1)
.put(0x07, bmi2);
.put(0x01, (byte) height)
.put(0x02, (byte) weight)
.put(0x03, (byte) info.getAge());
if (info.isBirthdayValid())
this.tlv.put(0x04, info.getBirthday());
if (info.isGenderValid()) {
if (info.unknownGenderSupported || info.gender != UserInfoData.GENDER_UNKNOWN)
this.tlv.put(0x05, info.gender);
}
this.tlv.put(0x06, bmiWalk);
this.tlv.put(0x07, bmiRun);
if (info.vo2Supported) {
this.tlv.put(0x08, info.getVo2Max());
this.tlv.put(0x09, info.getVo2Time());
}
if (info.precisionWeightSupported) {
int precisionWeight = Math.round(weight * 100f);
this.tlv.put(0x0b, precisionWeight);
}
}
}
}
public static class MessageCount {
public static final byte sleepId = 0x0C;
public static final byte stepId = 0x0A;
@ -268,6 +376,7 @@ public class FitnessData {
public List<SubContainer> containers;
private static final List<Byte> singleByteTagListBitmap1 = new ArrayList<>();
static {
singleByteTagListBitmap1.add((byte) 0x20);
singleByteTagListBitmap1.add((byte) 0x40);
@ -479,7 +588,7 @@ public class FitnessData {
HuaweiTLV subTlv = new HuaweiTLV();
for(HuaweiReportThreshold th: thresholds) {
for (HuaweiReportThreshold th : thresholds) {
subTlv.put(0x02, th.getBytes());
}
this.tlv = new HuaweiTLV().put(0x81, subTlv);
@ -561,6 +670,7 @@ public class FitnessData {
}
}
}
public static class RunPaceConfig {
public static final byte id = 0x28;
@ -578,12 +688,12 @@ public class FitnessData {
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) easyPaceZoneMinValue)
.put(0x02, (short) marathonPaceZoneMinValue)
.put(0x03, (short) lactatePaceZoneMinValue)
.put(0x04, (short) anaerobicPaceZoneMinValue)
.put(0x05, (short) maxOxygenPaceZoneMinValue)
.put(0x06, (short) maxOxygenPaceZoneMaxValue);
this.complete = true;
}
}
@ -625,7 +735,7 @@ public class FitnessData {
this.commandId = id;
if (walkRun < 0x00 || walkRun > 0xc8) walkRun = 0x6E;
if (climb < 0x0 || climb > 0xc8) climb = 0x3c;
if (climb < 0x0 || climb > 0xc8) climb = 0x3c;
if (heartRate < 0x0 || heartRate > 0x64) heartRate = 0x40;
if (cycleSpeed < 0x0 || cycleSpeed > 0xff) cycleSpeed = 0x50;
if (sample < 0x1 || sample > 0xa) sample = 0x3;
@ -639,11 +749,11 @@ public class FitnessData {
.put(0x04, cycleSpeed)
.put(0x05, sample)
.put(0x06, countLength);
if(walkRunSpeed != -1) {
this.tlv.put(0x07, (byte)walkRunSpeed);
if (walkRunSpeed != -1) {
this.tlv.put(0x07, (byte) walkRunSpeed);
}
if(walkRunWithHeartRate != -1) {
this.tlv.put(0x08, (byte)walkRunWithHeartRate);
if (walkRunWithHeartRate != -1) {
this.tlv.put(0x08, (byte) walkRunWithHeartRate);
}
this.complete = true;
}
@ -661,7 +771,7 @@ public class FitnessData {
this.commandId = id;
this.tlv = new HuaweiTLV()
.put(0x01, (byte)0x01)
.put(0x01, (byte) 0x01)
.put(0x02, temperatureSwitch);
this.complete = true;
@ -672,8 +782,8 @@ public class FitnessData {
public static class Type {
// TODO: enum?
public static final byte goal = 0x01;
public static final byte motion = 0x00;
public static final byte data = 0x01;
public static final byte goal = 0x01;
public static final byte motion = 0x00;
public static final byte data = 0x01;
}
}

View File

@ -42,11 +42,11 @@ public class SendFitnessUserInfoRequest extends Request {
try {
// Hardcoded values till interface for goal
ActivityUser activityUser = new ActivityUser();
byte gender = 3;
byte gender = UserInfo.UserInfoData.GENDER_UNKNOWN;
if (activityUser.getGender() == ActivityUser.GENDER_FEMALE) {
gender = 2;
gender = UserInfo.UserInfoData.GENDER_FEMALE;
} else if (activityUser.getGender() == ActivityUser.GENDER_MALE) {
gender = 1;
gender = UserInfo.UserInfoData.GENDER_MALE;
}
LocalDate dateOfBirth = activityUser.getDateOfBirth();
@ -54,13 +54,26 @@ public class SendFitnessUserInfoRequest extends Request {
birthdayEncoded += dateOfBirth.getMonthValue() << 8;
birthdayEncoded += dateOfBirth.getDayOfMonth();
return new UserInfo.Request(paramsProvider,
boolean unknownGenderSupported = supportProvider.getHuaweiCoordinator().supportsUnknownGender();
//TODO: discover Vo2Max capability and retrieve calculate and set proper values. Currently disabled.
boolean vo2Supported = false;
int vo2Max = 0;
int vo2Time = 0;
boolean precisionWeightSupported = supportProvider.getHuaweiCoordinator().supportsPrecisionWeight();
UserInfo.UserInfoData userInfoData = new UserInfo.UserInfoData(
activityUser.getHeightCm(),
activityUser.getWeightKg(),
activityUser.getAge(),
birthdayEncoded,
gender
).serialize();
gender,
unknownGenderSupported,
vo2Supported,
vo2Max,
vo2Time,
precisionWeightSupported);
return new UserInfo.Request(paramsProvider, userInfoData).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
}