diff --git a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java index 4b457d9e5..68d4846cb 100644 --- a/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java +++ b/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java @@ -45,7 +45,7 @@ public class GBDaoGenerator { public static void main(String[] args) throws Exception { - final Schema schema = new Schema(64, MAIN_PACKAGE + ".entities"); + final Schema schema = new Schema(65, MAIN_PACKAGE + ".entities"); Entity userAttributes = addUserAttributes(schema); Entity user = addUserInfo(schema, userAttributes); @@ -72,6 +72,7 @@ public class GBDaoGenerator { addHuamiSleepRespiratoryRateSample(schema, user, device); addXiaomiActivitySample(schema, user, device); addXiaomiSleepTimeSamples(schema, user, device); + addXiaomiDailySummarySamples(schema, user, device); addPebbleHealthActivitySample(schema, user, device); addPebbleHealthActivityKindOverlay(schema, user, device); addPebbleMisfitActivitySample(schema, user, device); @@ -347,6 +348,37 @@ public class GBDaoGenerator { return sample; } + private static Entity addXiaomiDailySummarySamples(Schema schema, Entity user, Entity device) { + Entity sample = addEntity(schema, "XiaomiDailySummarySample"); + addCommonTimeSampleProperties("AbstractTimeSample", sample, user, device); + sample.addIntProperty("timezone"); + sample.addIntProperty("steps"); + sample.addIntProperty("hrResting"); + sample.addIntProperty("hrMax"); + sample.addIntProperty("hrMaxTs"); + sample.addIntProperty("hrMin"); + sample.addIntProperty("hrMinTs"); + sample.addIntProperty("hrAvg"); + sample.addIntProperty("stressAvg"); + sample.addIntProperty("stressMax"); + sample.addIntProperty("stressMin"); + sample.addIntProperty("standing"); + sample.addIntProperty("calories"); + sample.addIntProperty("spo2Max"); + sample.addIntProperty("spo2MaxTs"); + sample.addIntProperty("spo2Min"); + sample.addIntProperty("spo2MinTs"); + sample.addIntProperty("spo2Avg"); + sample.addIntProperty("trainingLoadDay"); + sample.addIntProperty("trainingLoadWeek"); + sample.addIntProperty("trainingLoadLevel"); + sample.addIntProperty("vitalityIncreaseLight"); + sample.addIntProperty("vitalityIncreaseModerate"); + sample.addIntProperty("vitalityIncreaseHigh"); + sample.addIntProperty("vitalityCurrent"); + return sample; + } + private static void addHeartRateProperties(Entity activitySample) { activitySample.addIntProperty(SAMPLE_HEART_RATE).notNull().codeBeforeGetterAndSetter(OVERRIDE); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/DailySummaryParser.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/DailySummaryParser.java index 786fb23a0..16a069889 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/DailySummaryParser.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xiaomi/activity/impl/DailySummaryParser.java @@ -16,12 +16,21 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.impl; +import android.widget.Toast; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.devices.xiaomi.XiaomiDailySummarySampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.XiaomiDailySummarySample; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.XiaomiSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.XiaomiActivityFileId; import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.activity.XiaomiActivityParser; @@ -49,39 +58,62 @@ public class DailySummaryParser extends XiaomiActivityParser { LOG.debug("Header: {}", GB.hexdump(header)); - final int steps = buf.getInt(); + final XiaomiDailySummarySample sample = new XiaomiDailySummarySample(); + sample.setTimestamp(fileId.getTimestamp().getTime()); + sample.setTimezone(fileId.getTimezone()); + + sample.setSteps(buf.getInt()); final int unk1 = buf.get() & 0xff; // 0 final int unk2 = buf.get() & 0xff; // 0 final int unk3 = buf.get() & 0xff; // 0 - final int hrResting = buf.get() & 0xff; - final int hrMax = buf.get() & 0xff; - final int hrMaxTs = buf.getInt(); - final int hrMin = buf.get() & 0xff; - final int hrMinTs = buf.getInt(); - final int hrAvg = buf.get() & 0xff; - final int stressAvg = buf.get() & 0xff; - final int stressMax = buf.get() & 0xff; - final int stressMin = buf.get() & 0xff; - final int unk4 = buf.get() & 0xff; // 0 - final int unk5 = buf.get() & 0xff; // 0 - final int unk6 = buf.get() & 0xff; // 0 - final int calories = buf.getShort(); + sample.setHrResting(buf.get() & 0xff); + sample.setHrMax(buf.get() & 0xff); + sample.setHrMaxTs(buf.getInt()); + sample.setHrMin(buf.get() & 0xff); + sample.setHrMinTs(buf.getInt()); + sample.setHrAvg(buf.get() & 0xff); + sample.setStressAvg(buf.get() & 0xff); + sample.setStressMax(buf.get() & 0xff); + sample.setStressMin(buf.get() & 0xff); + final byte[] standingArr = new byte[3]; + buf.get(standingArr); + // each bit represents one hour where the user was standing up for that day, + // starting at 00:00-01:00. Let's convert it to an int + int standing = (standingArr[0] | (standingArr[1] << 8) | (standingArr[2] << 16)) & 0x00FFFFFF; + sample.setStanding(standing); + sample.setCalories((int) buf.getShort()); final int unk7 = buf.get() & 0xff; // 0 final int unk8 = buf.get() & 0xff; // 0 final int unk9 = buf.get() & 0xff; // 0 - final int spo2Max = buf.get() & 0xff; - final int spo2MaxTs = buf.getInt(); - final int spo2Min = buf.get() & 0xff; - final int spo2MinTs = buf.getInt(); - final int spo2Avg = buf.get() & 0xff; - final int trainingLoadMaybe1 = buf.getShort(); - final int trainingLoadMaybe2 = buf.getShort(); - final int trainingLoadMaybe3 = buf.get() & 0xff; + sample.setSpo2Max(buf.get() & 0xff); + sample.setSpo2MaxTs(buf.getInt()); + sample.setSpo2Min(buf.get() & 0xff); + sample.setSpo2MinTs(buf.getInt()); + sample.setSpo2Avg(buf.get() & 0xff); + sample.setTrainingLoadDay((int) buf.getShort()); + sample.setTrainingLoadWeek((int) buf.getShort()); + sample.setTrainingLoadLevel(buf.get() & 0xff); // TODO confirm - 1 for low training load level? + sample.setVitalityIncreaseLight(buf.get() & 0xff); + sample.setVitalityIncreaseModerate(buf.get() & 0xff); + sample.setVitalityIncreaseHigh(buf.get() & 0xff); + sample.setVitalityCurrent((int) buf.getShort()); - // TODO vitality somewhere? - // TODO persist everything + LOG.debug("Persisting 1 daily summary sample"); - LOG.warn("Persisting daily summary is not implemented"); + try (DBHandler handler = GBApplication.acquireDB()) { + final DaoSession session = handler.getDaoSession(); + final GBDevice device = support.getDevice(); + + sample.setDevice(DBHelper.getDevice(device, session)); + sample.setUser(DBHelper.getUser(session)); + + final XiaomiDailySummarySampleProvider sampleProvider = new XiaomiDailySummarySampleProvider(device, session); + sampleProvider.addSample(sample); + } catch (final Exception e) { + GB.toast(support.getContext(), "Error saving daily summary", Toast.LENGTH_LONG, GB.ERROR); + LOG.error("Error saving daily summary", e); + return false; + } return true; }