diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index 1025643aab..f04106e84f 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -56,7 +56,7 @@ public class GBDaoGenerator { private static final String TIMESTAMP_TO = "timestampTo"; public static void main(String[] args) throws Exception { - final Schema schema = new Schema(118, MAIN_PACKAGE + ".entities"); + final Schema schema = new Schema(119, MAIN_PACKAGE + ".entities"); Entity userAttributes = addUserAttributes(schema); Entity user = addUserInfo(schema, userAttributes); @@ -172,6 +172,8 @@ public class GBDaoGenerator { addHuaweiSleepStageSample(schema, user, device); addHuaweiSleepStatsSample(schema, user, device); addHuaweiTemperatureSample(schema, user, device); + addHuaweiHrvValuesSample(schema, user, device); + addHuaweiEmotionsSample(schema, user, device); addUltrahumanActivitySample(schema, user, device); addUltrahumanDeviceStateSample(schema, user, device); @@ -1558,6 +1560,7 @@ public class GBDaoGenerator { ); activitySample.addIntProperty("spo").notNull(); activitySample.addIntProperty("heartRate").notNull(); + activitySample.addIntProperty("restingHeartRate").notNull(); return activitySample; } @@ -1596,6 +1599,29 @@ public class GBDaoGenerator { sample.addDoubleProperty("minBreathRate").notNull(); sample.addDoubleProperty("maxBreathRate").notNull(); + sample.addIntProperty("hrvDayToBaseline").notNull(); + sample.addIntProperty("maxHrvBaseline").notNull(); + sample.addIntProperty("minHrvBaseline").notNull(); + sample.addIntProperty("avgHrv").notNull(); + sample.addIntProperty("breathRateDayToBaseline").notNull(); + sample.addIntProperty("maxBreathRateBaseline").notNull(); + sample.addIntProperty("minBreathRateBaseline").notNull(); + sample.addIntProperty("avgBreathRate").notNull(); + sample.addIntProperty("oxygenSaturationDayToBaseline").notNull(); + sample.addIntProperty("maxOxygenSaturationBaseline").notNull(); + sample.addIntProperty("minOxygenSaturationBaseline").notNull(); + sample.addIntProperty("avgOxygenSaturation").notNull(); + sample.addIntProperty("heartRateDayToBaseline").notNull(); + sample.addIntProperty("maxHeartRateBaseline").notNull(); + sample.addIntProperty("minHeartRateBaseline").notNull(); + sample.addIntProperty("avgHeartRate").notNull(); + sample.addIntProperty("rdi").notNull(); + sample.addIntProperty("wakeCount").notNull(); + sample.addIntProperty("turnOverCount").notNull(); + sample.addLongProperty("prepareSleepTime").notNull(); + sample.addIntProperty("wakeUpFeeling").notNull(); + sample.addIntProperty("sleepVersion").notNull(); + final Index indexWakeUp = new Index(); indexWakeUp.addProperty(wakeupTime); sample.addIndex(indexWakeUp); @@ -1613,6 +1639,26 @@ public class GBDaoGenerator { return sample; } + private static Entity addHuaweiHrvValuesSample(Schema schema, Entity user, Entity device) { + Entity sample = addEntity(schema, "HuaweiHrvValueSample"); + addCommonTimeSampleProperties("AbstractHrvValueSample", sample, user, device); + sample.addLongProperty("lastTimestamp").notNull().index(); + sample.addIntProperty("value").notNull().codeBeforeGetter(OVERRIDE); + return sample; + } + + private static Entity addHuaweiEmotionsSample(Schema schema, Entity user, Entity device) { + Entity sample = addEntity(schema, "HuaweiEmotionsSample"); + addCommonTimeSampleProperties("AbstractTimeSample", sample, user, device); + sample.addLongProperty("lastTimestamp").notNull().index(); + sample.addIntProperty("status").notNull(); + sample.addDoubleProperty("valenceCharacter"); + sample.addIntProperty("originStatus"); + sample.addDoubleProperty("arousalCharacter"); + + return sample; + } + private static Entity addHuaweiWorkoutSummarySample(Schema schema, Entity user, Entity device) { Entity workoutSummary = addEntity(schema, "HuaweiWorkoutSummarySample"); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_118.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_118.java index 488e752ad5..d21b9d2b15 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_118.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_118.java @@ -54,3 +54,4 @@ public class GadgetbridgeUpdate_118 implements DBUpdateScript { public void downgradeSchema(SQLiteDatabase db) { } } + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_119.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_119.java new file mode 100644 index 0000000000..c10d474780 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/schema/GadgetbridgeUpdate_119.java @@ -0,0 +1,135 @@ +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.HuaweiActivitySampleDao; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepStatsSampleDao; + +public class GadgetbridgeUpdate_119 implements DBUpdateScript { + @Override + public void upgradeSchema(final SQLiteDatabase db) { + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.HrvDayToBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.HrvDayToBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MaxHrvBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MaxHrvBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MinHrvBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MinHrvBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.AvgHrv.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.AvgHrv.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.BreathRateDayToBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.BreathRateDayToBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MaxBreathRateBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MaxBreathRateBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MinBreathRateBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MinBreathRateBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.AvgBreathRate.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.AvgBreathRate.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.OxygenSaturationDayToBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.OxygenSaturationDayToBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MaxOxygenSaturationBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MaxOxygenSaturationBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MinOxygenSaturationBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MinOxygenSaturationBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.AvgOxygenSaturation.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.AvgOxygenSaturation.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.HeartRateDayToBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.HeartRateDayToBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MaxHeartRateBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MaxHeartRateBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.MinHeartRateBaseline.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.MinHeartRateBaseline.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.AvgHeartRate.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.AvgHeartRate.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.Rdi.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.Rdi.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.WakeCount.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.WakeCount.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.TurnOverCount.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.TurnOverCount.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.PrepareSleepTime.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.PrepareSleepTime.columnName + "\" LONG NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.WakeUpFeeling.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.WakeUpFeeling.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + if (!DBHelper.existsColumn(HuaweiSleepStatsSampleDao.TABLENAME, HuaweiSleepStatsSampleDao.Properties.SleepVersion.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiSleepStatsSampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiSleepStatsSampleDao.Properties.SleepVersion.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + + if (!DBHelper.existsColumn(HuaweiActivitySampleDao.TABLENAME, HuaweiActivitySampleDao.Properties.RestingHeartRate.columnName, db)) { + final String statement = "ALTER TABLE " + HuaweiActivitySampleDao.TABLENAME + " ADD COLUMN \"" + + HuaweiActivitySampleDao.Properties.RestingHeartRate.columnName + "\" INTEGER NOT NULL DEFAULT -1;"; + db.execSQL(statement); + } + } + + @Override + public void downgradeSchema(SQLiteDatabase database) { + + } +} \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java index 34aa930269..e6d3315418 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiBRCoordinator.java @@ -40,6 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser; +import nodomain.freeyourgadget.gadgetbridge.model.HrvValueSample; import nodomain.freeyourgadget.gadgetbridge.model.SleepScoreSample; import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample; import nodomain.freeyourgadget.gadgetbridge.model.StressSample; @@ -235,6 +236,8 @@ public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordin @Override public boolean supportsSleepScore(@NonNull final GBDevice device) { return huaweiCoordinator.getSupportsNewTrueSleep(device); } + @Override + public boolean supportsHrvMeasurement(@NonNull GBDevice device) { return huaweiCoordinator.supportsHRV();} @Override public InstallHandler findInstallHandler(Uri uri, Context context) { @@ -271,6 +274,11 @@ public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordin return new HuaweiSleepScoreSampleProvider(device, session); } + @Override + public TimeSampleProvider getHrvValueSampleProvider(final GBDevice device, final DaoSession session) { + return new HuaweiHrvValueSampleProvider(device, session); + } + @Override public int[] getStressRanges() { return huaweiCoordinator.getStressRanges(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java index 9bc75beab4..f0f94547e1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java @@ -50,9 +50,12 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiActivitySampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiDictData; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiDictDataDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiDictDataValuesDao; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEmotionsSampleDao; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiHrvValueSampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepStageSampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepStatsSampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiStressSampleDao; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiTemperatureSampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSpO2SampleDao; @@ -140,6 +143,13 @@ public class HuaweiCoordinator { QueryBuilder stressQb = session.getHuaweiStressSampleDao().queryBuilder(); stressQb.where(HuaweiStressSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities(); + QueryBuilder hrvQb = session.getHuaweiHrvValueSampleDao().queryBuilder(); + hrvQb.where(HuaweiHrvValueSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities(); + + session.getHuaweiTemperatureSampleDao().queryBuilder().where(HuaweiTemperatureSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities(); + + session.getHuaweiEmotionsSampleDao().queryBuilder().where(HuaweiEmotionsSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities(); + QueryBuilder qb2 = session.getHuaweiWorkoutSummarySampleDao().queryBuilder(); List workouts = qb2.where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).build().list(); for (HuaweiWorkoutSummarySample sample : workouts) { @@ -972,7 +982,11 @@ public class HuaweiCoordinator { return false; } - + public boolean supportsHRV() { + if (supportsExpandCapability()) + return supportsExpandCapability(235); + return false; + } public boolean supportsPromptPushMessage () { // do not ask for capabilities under specific condition diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiDictTypes.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiDictTypes.java index b976a5f7c2..3fa0881080 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiDictTypes.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiDictTypes.java @@ -27,4 +27,15 @@ public class HuaweiDictTypes { public static final int SLEEP_DETAILS_CLASS = 700013; public static final int ARRHYTHMIA_CLASS = 700004; + + public static final int HRV_CLASS = 500044; + public static final int HRV_RMSSD_VALUE = 500044831; + + public static final int EMOTION_CLASS = 500031; + + public static final int EMOTION_STATUS_VALUE = 500031195; + public static final int EMOTION_VALENCE_CHARACTER_VALUE = 500031347; + public static final int EMOTION_ORIGIN_STATUS_VALUE = 500031160; + public static final int EMOTION_AROUSAL_CHARACTER_VALUE = 500031842; + } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiEmotionsSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiEmotionsSampleProvider.java new file mode 100644 index 0000000000..29f80b3641 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiEmotionsSampleProvider.java @@ -0,0 +1,67 @@ +package nodomain.freeyourgadget.gadgetbridge.devices.huawei; + +import androidx.annotation.NonNull; + +import java.util.List; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.query.QueryBuilder; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractTimeSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEmotionsSample; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEmotionsSampleDao; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; + +public class HuaweiEmotionsSampleProvider extends AbstractTimeSampleProvider { + public HuaweiEmotionsSampleProvider(final GBDevice device, final DaoSession session) { + super(device, session); + } + + @NonNull + @Override + public AbstractDao getSampleDao() { + return getSession().getHuaweiEmotionsSampleDao(); + } + + @NonNull + @Override + protected Property getTimestampSampleProperty() { + return HuaweiEmotionsSampleDao.Properties.Timestamp; + } + + @NonNull + @Override + protected Property getDeviceIdentifierSampleProperty() { + return HuaweiEmotionsSampleDao.Properties.DeviceId; + } + + @Override + public HuaweiEmotionsSample createSample() { + return new HuaweiEmotionsSample(); + } + + + public long getLastFetchTimestamp() { + QueryBuilder qb = getSampleDao().queryBuilder(); + Device dbDevice = DBHelper.findDevice(getDevice(), getSession()); + if (dbDevice == null) + return 0; + final Property deviceProperty = HuaweiEmotionsSampleDao.Properties.DeviceId; + final Property timestampProperty = HuaweiEmotionsSampleDao.Properties.LastTimestamp; + + qb.where(deviceProperty.eq(dbDevice.getId())) + .orderDesc(timestampProperty) + .limit(1); + + List samples = qb.build().list(); + if (samples.isEmpty()) + return 0; + + HuaweiEmotionsSample sample = samples.get(0); + return sample.getLastTimestamp(); + } + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiHrvValueSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiHrvValueSampleProvider.java new file mode 100644 index 0000000000..692d8a012c --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiHrvValueSampleProvider.java @@ -0,0 +1,67 @@ +package nodomain.freeyourgadget.gadgetbridge.devices.huawei; + +import androidx.annotation.NonNull; + +import java.util.List; + +import de.greenrobot.dao.AbstractDao; +import de.greenrobot.dao.Property; +import de.greenrobot.dao.query.QueryBuilder; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractTimeSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiHrvValueSample; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiHrvValueSampleDao; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; + +public class HuaweiHrvValueSampleProvider extends AbstractTimeSampleProvider { + public HuaweiHrvValueSampleProvider(final GBDevice device, final DaoSession session) { + super(device, session); + } + + @NonNull + @Override + public AbstractDao getSampleDao() { + return getSession().getHuaweiHrvValueSampleDao(); + } + + @NonNull + @Override + protected Property getTimestampSampleProperty() { + return HuaweiHrvValueSampleDao.Properties.Timestamp; + } + + @NonNull + @Override + protected Property getDeviceIdentifierSampleProperty() { + return HuaweiHrvValueSampleDao.Properties.DeviceId; + } + + @Override + public HuaweiHrvValueSample createSample() { + return new HuaweiHrvValueSample(); + } + + + public long getLastFetchTimestamp() { + QueryBuilder qb = getSampleDao().queryBuilder(); + Device dbDevice = DBHelper.findDevice(getDevice(), getSession()); + if (dbDevice == null) + return 0; + final Property deviceProperty = HuaweiHrvValueSampleDao.Properties.DeviceId; + final Property timestampProperty = HuaweiHrvValueSampleDao.Properties.LastTimestamp; + + qb.where(deviceProperty.eq(dbDevice.getId())) + .orderDesc(timestampProperty) + .limit(1); + + List samples = qb.build().list(); + if (samples.isEmpty()) + return 0; + + HuaweiHrvValueSample sample = samples.get(0); + return sample.getLastTimestamp(); + } + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java index 987882f512..eec2578bc2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiLECoordinator.java @@ -41,6 +41,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser; +import nodomain.freeyourgadget.gadgetbridge.model.HrvValueSample; import nodomain.freeyourgadget.gadgetbridge.model.SleepScoreSample; import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample; import nodomain.freeyourgadget.gadgetbridge.model.StressSample; @@ -244,6 +245,9 @@ public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator i @Override public boolean supportsSleepScore(@NonNull final GBDevice device) { return huaweiCoordinator.getSupportsNewTrueSleep(device); } + @Override + public boolean supportsHrvMeasurement(@NonNull GBDevice device) { return huaweiCoordinator.supportsHRV();} + @Override public InstallHandler findInstallHandler(Uri uri, Context context) { return huaweiCoordinator.getInstallHandler(uri, context); @@ -279,6 +283,11 @@ public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator i return new HuaweiSleepScoreSampleProvider(device, session); } + @Override + public TimeSampleProvider getHrvValueSampleProvider(final GBDevice device, final DaoSession session) { + return new HuaweiHrvValueSampleProvider(device, session); + } + @Override public int[] getStressRanges() { return huaweiCoordinator.getStressRanges(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSampleProvider.java index 5da36979c5..a3aaebda5a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiSampleProvider.java @@ -215,7 +215,8 @@ public class HuaweiSampleProvider extends AbstractSampleProvider unknownTVs = null; @Override @@ -414,7 +416,7 @@ public class FitnessData { private static void parseData(SubContainer returnValue, byte[] data) { int i = 0; - if (data.length <= 0) { + if (data.length == 0) { returnValue.parsedData = null; returnValue.parsedDataError = "Data is missing feature bitmap."; return; @@ -491,6 +493,8 @@ public class FitnessData { if (bitToCheck == 0x01) returnValue.spo = value; + else if (bitToCheck == 0x02) + returnValue.restingHeartRate = value; else returnValue.unknownTVs.add(tv); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java index 1b6dba2e3d..5ab1270e85 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java @@ -71,7 +71,9 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupp import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCoordinatorSupplier.HuaweiDeviceType; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiCrypto; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiDictTypes; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiEmotionsSampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiGpsParser; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiHrvValueSampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSequenceDataFileParser; @@ -92,6 +94,8 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary; import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiActivitySample; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiEmotionsSample; +import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiHrvValueSample; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepStageSample; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiSleepStatsSample; import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiStressSample; @@ -864,7 +868,7 @@ public class HuaweiSupportProvider { try { // NOTE: register all DAta Sync handlers on the early stage. We can receive requests from the watch during initialization. - if(getHuaweiCoordinator().getSendCountryCodeEnabled(getDevice())) { + if (getHuaweiCoordinator().getSendCountryCodeEnabled(getDevice())) { huaweiDataSyncFeatureManager = new HuaweiDataSyncFeatureManager(HuaweiSupportProvider.this); } @@ -883,13 +887,13 @@ public class HuaweiSupportProvider { if (getHuaweiCoordinator().supportsArrhythmia() && getHuaweiCoordinator().isShowForceCountrySpecificFeatures(getCoordinator().getDevice())) { huaweiDataSyncArrhythmia = new HuaweiDataSyncArrhythmia(HuaweiSupportProvider.this); } - if (getHuaweiCoordinator().supportsECG() && getHuaweiCoordinator().isShowForceCountrySpecificFeatures(getCoordinator().getDevice())) { + if (getHuaweiCoordinator().supportsECG() && getHuaweiCoordinator().isShowForceCountrySpecificFeatures(getCoordinator().getDevice())) { huaweiDataSyncEcg = new HuaweiDataSyncEcg(HuaweiSupportProvider.this); } - if(getHuaweiCoordinator().supportsSleepApnea()) { + if (getHuaweiCoordinator().supportsSleepApnea()) { huaweiDataSyncSleepApnea = new HuaweiDataSyncSleepApnea(HuaweiSupportProvider.this); } - if(getHuaweiCoordinator().supportsArterialStiffnessDetection()) { + if (getHuaweiCoordinator().supportsArterialStiffnessDetection()) { huaweiDataSyncArterialStiffnessDetection = new HuaweiDataSyncArterialStiffnessDetection(HuaweiSupportProvider.this); } @@ -1573,7 +1577,7 @@ public class HuaweiSupportProvider { HuaweiP2PDataDictionarySyncService P2PSyncService = HuaweiP2PDataDictionarySyncService.getRegisteredInstance(huaweiP2PManager); if (P2PSyncService != null) { - List list = P2PSyncService.checkSupported(this.getHuaweiCoordinator(), Arrays.asList(HuaweiDictTypes.SKIN_TEMPERATURE_CLASS)); + List list = P2PSyncService.checkSupported(this.getHuaweiCoordinator(), Arrays.asList(HuaweiDictTypes.SKIN_TEMPERATURE_CLASS, HuaweiDictTypes.HRV_CLASS, HuaweiDictTypes.EMOTION_CLASS)); if (!list.isEmpty()) { syncState.setP2pSync(true); P2PSyncService.startSync(list, new HuaweiP2PDataDictionarySyncService.DictionarySyncCallback() { @@ -1588,6 +1592,22 @@ public class HuaweiSupportProvider { LOG.warn("Exception for getting temperature start time", e); } return 0; + } else if (dictClass == HuaweiDictTypes.HRV_CLASS) { + try (DBHandler db = GBApplication.acquireDB()) { + HuaweiHrvValueSampleProvider hrvStatsSampleProvider = new HuaweiHrvValueSampleProvider(gbDevice, db.getDaoSession()); + return hrvStatsSampleProvider.getLastFetchTimestamp(); + } catch (Exception e) { + LOG.warn("Exception for getting HRV start time", e); + } + return 0; + } else if (dictClass == HuaweiDictTypes.EMOTION_CLASS) { + try (DBHandler db = GBApplication.acquireDB()) { + HuaweiEmotionsSampleProvider emotionsStatsSampleProvider = new HuaweiEmotionsSampleProvider(gbDevice, db.getDaoSession()); + return emotionsStatsSampleProvider.getLastFetchTimestamp(); + } catch (Exception e) { + LOG.warn("Exception for getting HRV start time", e); + } + return 0; } return -1; } @@ -1613,7 +1633,6 @@ public class HuaweiSupportProvider { temperatureSamples.add(sample); } } - } } try (DBHandler db = GBApplication.acquireDB()) { @@ -1622,6 +1641,88 @@ public class HuaweiSupportProvider { } catch (Exception e) { LOG.error("Cannot save skin temperature samples, continue"); } + } else if (dictClass == HuaweiDictTypes.HRV_CLASS) { + List hrvSamples = new ArrayList<>(); + for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) { + long timestamp = dt.getStartTimestamp(); + long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp()); + for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) { + if (val.getTag() == 10 && val.getDataType() == HuaweiDictTypes.HRV_RMSSD_VALUE) { + double rmssd = HuaweiUtil.convBytes2Double(val.getValue()); + int value = (int) rmssd; + if (value >= 0 && value <= 200) { + HuaweiHrvValueSample sample = new HuaweiHrvValueSample(); + sample.setTimestamp(timestamp); + sample.setLastTimestamp(lastTime); + sample.setValue(value); + hrvSamples.add(sample); + } + } + } + } + try (DBHandler db = GBApplication.acquireDB()) { + final DaoSession session = db.getDaoSession(); + new HuaweiHrvValueSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, hrvSamples); + } catch (Exception e) { + LOG.error("Cannot save skin HRV samples, continue"); + } + } else if (dictClass == HuaweiDictTypes.EMOTION_CLASS) { + List emotionsSamples = new ArrayList<>(); + for (HuaweiP2PDataDictionarySyncService.DictData dt : dictData) { + long timestamp = dt.getStartTimestamp(); + long lastTime = Math.max(dt.getEndTimestamp(), dt.getModifyTimestamp()); + Integer status = null; + Double valenceCharacter = null; + Integer originStatus = null; + Double arousalCharacter = null; + for (HuaweiP2PDataDictionarySyncService.DictData.DictDataValue val : dt.getData()) { + if (val.getTag() != 10) { + LOG.info("emotions unexpected tag: {}", val.getTag()); + continue; + } + if (val.getDataType() == HuaweiDictTypes.EMOTION_STATUS_VALUE) { + double value = HuaweiUtil.convBytes2Double(val.getValue()); + if (value >= 0 && value < 100) { + status = (int) value; + } + } else if (val.getDataType() == HuaweiDictTypes.EMOTION_VALENCE_CHARACTER_VALUE) { + double value = HuaweiUtil.convBytes2Double(val.getValue()); + if (value >= 0 && value <= 100) { + valenceCharacter = value; + } + } else if (val.getDataType() == HuaweiDictTypes.EMOTION_ORIGIN_STATUS_VALUE) { + double value = HuaweiUtil.convBytes2Double(val.getValue()); + if (value >= 0 && value < 100) { + originStatus = (int) value; + } + } else if (val.getDataType() == HuaweiDictTypes.EMOTION_AROUSAL_CHARACTER_VALUE) { + double value = HuaweiUtil.convBytes2Double(val.getValue()); + if (value >= 0 && value <= 100) { + arousalCharacter = value; + } + } else { + LOG.info("emotions unknown data type: {}", val.getDataType()); + } + + } + if (status != null || valenceCharacter != null || originStatus != null || arousalCharacter != null) { + HuaweiEmotionsSample sample = new HuaweiEmotionsSample(); + sample.setTimestamp(timestamp); + sample.setLastTimestamp(lastTime); + sample.setStatus(status == null ? 0 : status); + sample.setValenceCharacter(valenceCharacter); + sample.setOriginStatus(originStatus); + sample.setArousalCharacter(arousalCharacter); + emotionsSamples.add(sample); + } + + } + try (DBHandler db = GBApplication.acquireDB()) { + final DaoSession session = db.getDaoSession(); + new HuaweiEmotionsSampleProvider(gbDevice, session).persistForDevice(context, gbDevice, emotionsSamples); + } catch (Exception e) { + LOG.error("Cannot save skin emotions samples, continue"); + } } } @@ -1896,6 +1997,7 @@ public class HuaweiSupportProvider { ActivitySample.NOT_MEASURED, ActivitySample.NOT_MEASURED, ActivitySample.NOT_MEASURED, + ActivitySample.NOT_MEASURED, ActivitySample.NOT_MEASURED ); activitySample.setProvider(sampleProvider); @@ -2319,14 +2421,14 @@ public class HuaweiSupportProvider { } public void setSleepBreath() { - if(huaweiDataSyncSleepApnea != null) { + if (huaweiDataSyncSleepApnea != null) { boolean sleepBreathSwitch = GBApplication .getDeviceSpecificSharedPrefs(this.getDevice().getAddress()) .getBoolean(HuaweiConstants.PREF_HUAWEI_SLEEP_BREATH, false); - if(!huaweiDataSyncSleepApnea.changeSleepBreatheState(sleepBreathSwitch)) { + if (!huaweiDataSyncSleepApnea.changeSleepBreatheState(sleepBreathSwitch)) { LOG.error("Failed to configure sleep breathing"); } - if(!huaweiDataSyncSleepApnea.changeSleepApneaState(sleepBreathSwitch)) { + if (!huaweiDataSyncSleepApnea.changeSleepApneaState(sleepBreathSwitch)) { LOG.error("Failed to configure sleep apnea"); } } else { @@ -2568,11 +2670,11 @@ public class HuaweiSupportProvider { } private void activateArrhythmia() { - if(huaweiDataSyncArrhythmia != null) { + if (huaweiDataSyncArrhythmia != null) { boolean arrhythmiaEnabled = GBApplication .getDeviceSpecificSharedPrefs(getDevice().getAddress()) .getBoolean(HuaweiConstants.PREF_HUAWEI_ARRHYTHMIA_SWITCH, false); - if(!huaweiDataSyncArrhythmia.changeState(arrhythmiaEnabled)) { + if (!huaweiDataSyncArrhythmia.changeState(arrhythmiaEnabled)) { LOG.error("Error Arrhythmia change state"); } } @@ -2580,22 +2682,22 @@ public class HuaweiSupportProvider { } private void setArrhythmiaAutomatic() { - if(huaweiDataSyncArrhythmia != null) { + if (huaweiDataSyncArrhythmia != null) { boolean automaticArrhythmiaEnabled = GBApplication .getDeviceSpecificSharedPrefs(getDevice().getAddress()) .getBoolean(HuaweiConstants.PREF_HUAWEI_ARRHYTHMIA_AUTOMATIC, false); - if(!huaweiDataSyncArrhythmia.setAutomatic(automaticArrhythmiaEnabled)) { + if (!huaweiDataSyncArrhythmia.setAutomatic(automaticArrhythmiaEnabled)) { LOG.error("Error Arrhythmia change automatic"); } } } private void setArrhythmiaAlert() { - if(huaweiDataSyncArrhythmia != null) { + if (huaweiDataSyncArrhythmia != null) { boolean arrhythmiaAlertEnabled = GBApplication .getDeviceSpecificSharedPrefs(getDevice().getAddress()) .getBoolean(HuaweiConstants.PREF_HUAWEI_ARRHYTHMIA_ALERT, false); - if(!huaweiDataSyncArrhythmia.setAlert(arrhythmiaAlertEnabled)) { + if (!huaweiDataSyncArrhythmia.setAlert(arrhythmiaAlertEnabled)) { LOG.error("Error Arrhythmia change alert"); } } @@ -2970,25 +3072,29 @@ public class HuaweiSupportProvider { sleepStat.setMaxOxygenSaturation(sleepDataSummary.maxOxygenSaturation); sleepStat.setMinBreathRate(sleepDataSummary.minBreathRate); sleepStat.setMaxBreathRate(sleepDataSummary.maxBreathRate); - //TODO: // validData -- not needed -// hrvDayToBaseline -// maxHrvBaseline -// minHrvBaseline -// avgHrv -// breathRateDayToBaseline -// maxBreathRateBaseline -// minBreathRateBaseline -// avgBreathRate -// oxygenSaturationDayToBaseline -// maxOxygenSaturationBaseline -// minOxygenSaturationBaseline -// avgOxygenSaturation -// heartRateDayToBaseline -// maxHeartRateBaseline -// minHeartRateBaseline -// avgHeartRate -// rdi + sleepStat.setHrvDayToBaseline(sleepDataSummary.hrvDayToBaseline); + sleepStat.setMaxHrvBaseline(sleepDataSummary.maxHrvBaseline); + sleepStat.setMinHrvBaseline(sleepDataSummary.minHrvBaseline); + sleepStat.setAvgHrv(sleepDataSummary.avgHrv); + sleepStat.setBreathRateDayToBaseline(sleepDataSummary.breathRateDayToBaseline); + sleepStat.setMaxBreathRateBaseline(sleepDataSummary.maxBreathRateBaseline); + sleepStat.setMinBreathRateBaseline(sleepDataSummary.minBreathRateBaseline); + sleepStat.setAvgBreathRate(sleepDataSummary.avgBreathRate); + sleepStat.setOxygenSaturationDayToBaseline(sleepDataSummary.oxygenSaturationDayToBaseline); + sleepStat.setMaxOxygenSaturationBaseline(sleepDataSummary.maxOxygenSaturationBaseline); + sleepStat.setMinOxygenSaturationBaseline(sleepDataSummary.minOxygenSaturationBaseline); + sleepStat.setAvgOxygenSaturation(sleepDataSummary.avgOxygenSaturation); + sleepStat.setHeartRateDayToBaseline(sleepDataSummary.heartRateDayToBaseline); + sleepStat.setMaxHeartRateBaseline(sleepDataSummary.maxHeartRateBaseline); + sleepStat.setMinHeartRateBaseline(sleepDataSummary.minHeartRateBaseline); + sleepStat.setAvgHeartRate(sleepDataSummary.avgHeartRate); + sleepStat.setRdi(sleepDataSummary.rdi); + sleepStat.setWakeCount(sleepDataSummary.wakeCount); + sleepStat.setTurnOverCount(sleepDataSummary.turnOverCount); + sleepStat.setPrepareSleepTime(sleepDataSummary.prepareSleepTime); + sleepStat.setWakeUpFeeling(sleepDataSummary.wakeUpFeeling); + sleepStat.setSleepVersion(sleepDataSummary.sleepVersion); sleepStatsSamples.add(sleepStat); long time = HuaweiTrueSleepSequenceDataParser.getTime(sleepDataSummary.fallAsleepTime, sleepDataSummary.bedTime, sleepDataSummary.validData, getHuaweiCoordinator().supportsBedTime()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java index 7c2faba5dc..99782ff2cb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/p2p/HuaweiP2PDataDictionarySyncService.java @@ -87,6 +87,10 @@ public class HuaweiP2PDataDictionarySyncService extends HuaweiBaseP2PService { result.add(cl); } else if(cl == HuaweiDictTypes.BLOOD_PRESSURE_CLASS && coordinator.supportsBloodPressure()) { result.add(cl); + } else if(cl == HuaweiDictTypes.HRV_CLASS && coordinator.supportsHRV()) { + result.add(cl); + } else if(cl == HuaweiDictTypes.EMOTION_CLASS && coordinator.supportsEmotion()) { + result.add(cl); } } return result; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetStepDataRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetStepDataRequest.java index 06deb35ca5..93d6435fd2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetStepDataRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/GetStepDataRequest.java @@ -84,6 +84,8 @@ public class GetStepDataRequest extends Request { byte heartrate = (byte) subContainer.heartrate; byte spo = (byte) subContainer.spo; + byte restingHeartRate = (byte) subContainer.restingHeartRate; + if (steps == -1) steps = 0; if (calories == -1) @@ -109,7 +111,8 @@ public class GetStepDataRequest extends Request { calories, distance, spo, - heartrate + heartrate, + restingHeartRate ); activitySample.setProvider(sampleProvider); samples.add(activitySample);