Huawei: Save stress data to database and display to users

This commit is contained in:
Me7c7
2025-03-30 19:25:03 +00:00
committed by José Rebelo
parent cd3d995664
commit f26c973d3a
7 changed files with 121 additions and 4 deletions
@@ -56,7 +56,7 @@ public class GBDaoGenerator {
public static void main(String[] args) throws Exception {
final Schema schema = new Schema(99, MAIN_PACKAGE + ".entities");
final Schema schema = new Schema(100, MAIN_PACKAGE + ".entities");
Entity userAttributes = addUserAttributes(schema);
Entity user = addUserInfo(schema, userAttributes);
@@ -159,6 +159,7 @@ public class GBDaoGenerator {
addColmiTemperatureSample(schema, user, device);
addHuaweiActivitySample(schema, user, device);
addHuaweiStressSample(schema, user, device);
addUltrahumanActivitySample(schema, user, device);
addUltrahumanDeviceStateSample(schema, user, device);
@@ -1428,6 +1429,15 @@ public class GBDaoGenerator {
return activitySample;
}
private static Entity addHuaweiStressSample(Schema schema, Entity user, Entity device) {
Entity stressSample = addEntity(schema, "HuaweiStressSample");
addCommonTimeSampleProperties("AbstractStressSample", stressSample, user, device);
stressSample.addIntProperty(SAMPLE_STRESS).notNull().codeBeforeGetter(OVERRIDE);
stressSample.addByteProperty("level").notNull();
stressSample.addLongProperty("startTime").notNull();
return stressSample;
}
private static Entity addHuaweiWorkoutSummarySample(Schema schema, Entity user, Entity device) {
Entity workoutSummary = addEntity(schema, "HuaweiWorkoutSummarySample");
@@ -42,6 +42,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
import nodomain.freeyourgadget.gadgetbridge.model.StressSample;
import nodomain.freeyourgadget.gadgetbridge.model.TemperatureSample;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiBRSupport;
@@ -214,6 +215,11 @@ public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordin
return huaweiCoordinator.supportsTemperature();
}
@Override
public boolean supportsStressMeasurement() {
return huaweiCoordinator.supportsAutoStress();
}
@Override
public InstallHandler findInstallHandler(Uri uri, Context context) {
return huaweiCoordinator.getInstallHandler(uri, context);
@@ -239,6 +245,16 @@ public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordin
return new HuaweiTemperatureSampleProvider(device, session);
}
@Override
public TimeSampleProvider<? extends StressSample> getStressSampleProvider(final GBDevice device, final DaoSession session) {
return new HuaweiStressSampleProvider(device, session);
}
@Override
public int[] getStressRanges() {
return huaweiCoordinator.getStressRanges();
}
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
return huaweiCoordinator.getDeviceSpecificSettings(device);
}
@@ -49,6 +49,7 @@ 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.HuaweiStressSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSpO2SampleDao;
@@ -125,6 +126,9 @@ public class HuaweiCoordinator {
QueryBuilder<?> qb = session.getHuaweiActivitySampleDao().queryBuilder();
qb.where(HuaweiActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
QueryBuilder<?> stressQb = session.getHuaweiStressSampleDao().queryBuilder();
stressQb.where(HuaweiStressSampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
QueryBuilder<HuaweiWorkoutSummarySample> qb2 = session.getHuaweiWorkoutSummarySampleDao().queryBuilder();
List<HuaweiWorkoutSummarySample> workouts = qb2.where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(deviceId)).build().list();
for (HuaweiWorkoutSummarySample sample : workouts) {
@@ -1053,4 +1057,13 @@ public class HuaweiCoordinator {
public void setOtaSignatureLength(int otaSignatureLength) {
this.otaSignatureLength = otaSignatureLength;
}
public int[] getStressRanges() {
// 1-29 = relaxed
// 30-59 = mild
// 60-79 = moderate
// 80-100 = high
return new int[]{1, 30, 60, 80};
}
}
@@ -42,6 +42,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
import nodomain.freeyourgadget.gadgetbridge.model.StressSample;
import nodomain.freeyourgadget.gadgetbridge.model.TemperatureSample;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiLESupport;
@@ -222,6 +223,11 @@ public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator i
return huaweiCoordinator.supportsTemperature();
}
@Override
public boolean supportsStressMeasurement() {
return huaweiCoordinator.supportsAutoStress();
}
@Override
public InstallHandler findInstallHandler(Uri uri, Context context) {
return huaweiCoordinator.getInstallHandler(uri, context);
@@ -247,6 +253,16 @@ public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator i
return new HuaweiTemperatureSampleProvider(device, session);
}
@Override
public TimeSampleProvider<? extends StressSample> getStressSampleProvider(final GBDevice device, final DaoSession session) {
return new HuaweiStressSampleProvider(device, session);
}
@Override
public int[] getStressRanges() {
return huaweiCoordinator.getStressRanges();
}
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
return huaweiCoordinator.getDeviceSpecificSettings(device);
}
@@ -0,0 +1,40 @@
package nodomain.freeyourgadget.gadgetbridge.devices.huawei;
import androidx.annotation.NonNull;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractTimeSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiStressSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiStressSampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class HuaweiStressSampleProvider extends AbstractTimeSampleProvider<HuaweiStressSample> {
public HuaweiStressSampleProvider(final GBDevice device, final DaoSession session) {
super(device, session);
}
@NonNull
@Override
public AbstractDao<HuaweiStressSample, ?> getSampleDao() {
return getSession().getHuaweiStressSampleDao();
}
@NonNull
@Override
protected Property getTimestampSampleProperty() {
return HuaweiStressSampleDao.Properties.Timestamp;
}
@NonNull
@Override
protected Property getDeviceIdentifierSampleProperty() {
return HuaweiStressSampleDao.Properties.DeviceId;
}
@Override
public HuaweiStressSample createSample() {
return new HuaweiStressSample();
}
}
@@ -23,8 +23,6 @@ public class HuaweiStressScoreCalculation {
private static final int OUTPUT_MIN = 15;
private static final int OUTPUT_MAX = 90;
public static float calculateScoreFactor(float[] features) {
float[] copyFeatures = features.clone();
@@ -67,6 +67,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiGpsParser;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiStressParser;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiStressSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTruSleepParser;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.CameraRemote;
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.GpsAndTime;
@@ -81,6 +82,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiDictData;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiDictDataDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiDictDataValues;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiDictDataValuesDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiStressSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSample;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
@@ -1720,6 +1722,26 @@ public class HuaweiSupportProvider {
}
}
public void addStressData(long startTime, long endTime, byte stress, byte level) {
try (DBHandler db = GBApplication.acquireDB()) {
final Device device = DBHelper.getDevice(getDevice(), db.getDaoSession());
final User user = DBHelper.getUser(db.getDaoSession());
HuaweiStressSampleProvider sampleProvider = new HuaweiStressSampleProvider(gbDevice, db.getDaoSession());
HuaweiStressSample stressSample = new HuaweiStressSample();
stressSample.setTimestamp(endTime);
stressSample.setStartTime(startTime);
stressSample.setStress(stress);
stressSample.setLevel(level);
stressSample.setDevice(device);
stressSample.setUser(user);
sampleProvider.addSample(stressSample);
} catch (Exception e) {
LOG.error("Failed to add step data to database", e);
}
}
public void addTotalFitnessData(int steps, int calories, int distance) {
LOG.debug("FITNESS total steps: {}", steps);
LOG.debug("FITNESS total calories: {}", calories); // TODO: May actually be kilocalories
@@ -2733,7 +2755,6 @@ public class HuaweiSupportProvider {
LOG.debug("Parsing stress file");
HuaweiStressParser.RriFileData results = HuaweiStressParser.parseRri(fileRequest.getData());
LOG.info("stress result: {}", results);
// TODO: process and save
if(results != null && !results.stressData.isEmpty()) {
HuaweiStressParser.StressData stressData = results.stressData.get(results.stressData.size() - 1);
LOG.info("Last stored stress data: {}", stressData);
@@ -2741,6 +2762,9 @@ public class HuaweiSupportProvider {
if(currentStressData == null || stressData.endTime > currentStressData.endTime) {
storeLastStressData(stressData);
}
for(HuaweiStressParser.StressData dt: results.stressData) {
addStressData(dt.startTime, dt.endTime, dt.score, dt.level);
}
}
} else {