mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-25 16:15:55 +01:00
Huawei: Re-parse workout details when opening details
This commit is contained in:
parent
967ae31b7a
commit
183bf8725f
@ -23,19 +23,16 @@ import android.net.Uri;
|
|||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.greenrobot.dao.query.QueryBuilder;
|
import de.greenrobot.dao.query.QueryBuilder;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLClassicDeviceCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLClassicDeviceCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||||
@ -49,9 +46,11 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
|
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiBRSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiBRSupport;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWorkoutGbParser;
|
||||||
|
|
||||||
public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordinator implements HuaweiCoordinatorSupplier {
|
public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordinator implements HuaweiCoordinatorSupplier {
|
||||||
|
|
||||||
@ -209,6 +208,11 @@ public abstract class HuaweiBRCoordinator extends AbstractBLClassicDeviceCoordin
|
|||||||
return huaweiCoordinator.getInstallHandler(uri, context);
|
return huaweiCoordinator.getInstallHandler(uri, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActivitySummaryParser getActivitySummaryParser(final GBDevice device, final Context context) {
|
||||||
|
return new HuaweiWorkoutGbParser(device, context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SampleProvider<? extends AbstractActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
|
public SampleProvider<? extends AbstractActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
|
||||||
return new HuaweiSampleProvider(device, session);
|
return new HuaweiSampleProvider(device, session);
|
||||||
|
@ -47,9 +47,11 @@ import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
|
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiLESupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiLESupport;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiWorkoutGbParser;
|
||||||
|
|
||||||
public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator implements HuaweiCoordinatorSupplier {
|
public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator implements HuaweiCoordinatorSupplier {
|
||||||
|
|
||||||
@ -215,6 +217,11 @@ public abstract class HuaweiLECoordinator extends AbstractBLEDeviceCoordinator i
|
|||||||
return huaweiCoordinator.getInstallHandler(uri, context);
|
return huaweiCoordinator.getInstallHandler(uri, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActivitySummaryParser getActivitySummaryParser(final GBDevice device, final Context context) {
|
||||||
|
return new HuaweiWorkoutGbParser(device, context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SampleProvider<? extends AbstractActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
|
public SampleProvider<? extends AbstractActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
|
||||||
return new HuaweiSampleProvider(device, session);
|
return new HuaweiSampleProvider(device, session);
|
||||||
|
@ -70,7 +70,7 @@ public class HuaweiSettingsCustomizer implements DeviceSpecificSettingsCustomize
|
|||||||
if (preference.getKey().equals("huawei_reparse_workout_data")) {
|
if (preference.getKey().equals("huawei_reparse_workout_data")) {
|
||||||
if (((SwitchPreferenceCompat) preference).isChecked()) {
|
if (((SwitchPreferenceCompat) preference).isChecked()) {
|
||||||
GB.toast("Starting workout reparse", Toast.LENGTH_SHORT, 0);
|
GB.toast("Starting workout reparse", Toast.LENGTH_SHORT, 0);
|
||||||
HuaweiWorkoutGbParser.parseAllWorkouts();
|
new HuaweiWorkoutGbParser(handler.getDevice(), handler.getContext()).parseAllWorkouts();
|
||||||
GB.toast("Workout reparse is complete", Toast.LENGTH_SHORT, 0);
|
GB.toast("Workout reparse is complete", Toast.LENGTH_SHORT, 0);
|
||||||
|
|
||||||
((SwitchPreferenceCompat) preference).setChecked(false);
|
((SwitchPreferenceCompat) preference).setChecked(false);
|
||||||
|
@ -90,12 +90,10 @@ public class ActivitySummaryJsonSummary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getCorrectSummary(BaseActivitySummary item, final boolean forDetails){
|
private String getCorrectSummary(BaseActivitySummary item, final boolean forDetails){
|
||||||
if (item.getRawSummaryData() != null || item.getRawDetailsPath() != null) {
|
try {
|
||||||
try {
|
item = summaryParser.parseBinaryData(item, forDetails);
|
||||||
item = summaryParser.parseBinaryData(item, forDetails);
|
} catch (final Exception e) {
|
||||||
} catch (final Exception e) {
|
LOG.error("Failed to re-parse corrected summary", e);
|
||||||
LOG.error("Failed to re-parse corrected summary", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return item.getSummaryData();
|
return item.getSummaryData();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,17 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.model;
|
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import de.greenrobot.dao.query.QueryBuilder;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
|
||||||
public interface ActivitySummaryParser {
|
public interface ActivitySummaryParser {
|
||||||
/**
|
/**
|
||||||
@ -30,4 +40,31 @@ public interface ActivitySummaryParser {
|
|||||||
* @return the update {@link BaseActivitySummary}
|
* @return the update {@link BaseActivitySummary}
|
||||||
*/
|
*/
|
||||||
BaseActivitySummary parseBinaryData(BaseActivitySummary summary, final boolean forDetails);
|
BaseActivitySummary parseBinaryData(BaseActivitySummary summary, final boolean forDetails);
|
||||||
|
|
||||||
|
static BaseActivitySummary findOrCreateBaseActivitySummary(final DaoSession session,
|
||||||
|
final GBDevice gbDevice,
|
||||||
|
final int timestampSeconds) {
|
||||||
|
final Device device = DBHelper.getDevice(gbDevice, session);
|
||||||
|
final User user = DBHelper.getUser(session);
|
||||||
|
final BaseActivitySummaryDao summaryDao = session.getBaseActivitySummaryDao();
|
||||||
|
final QueryBuilder<BaseActivitySummary> qb = summaryDao.queryBuilder();
|
||||||
|
qb.where(BaseActivitySummaryDao.Properties.StartTime.eq(new Date(timestampSeconds * 1000L)));
|
||||||
|
qb.where(BaseActivitySummaryDao.Properties.DeviceId.eq(device.getId()));
|
||||||
|
qb.where(BaseActivitySummaryDao.Properties.UserId.eq(user.getId()));
|
||||||
|
final List<BaseActivitySummary> summaries = qb.build().list();
|
||||||
|
if (summaries.isEmpty()) {
|
||||||
|
final BaseActivitySummary summary = new BaseActivitySummary();
|
||||||
|
summary.setStartTime(new Date(timestampSeconds * 1000L));
|
||||||
|
summary.setDevice(device);
|
||||||
|
summary.setUser(user);
|
||||||
|
|
||||||
|
// These will be set later, once we parse the summary
|
||||||
|
summary.setEndTime(new Date(timestampSeconds * 1000L));
|
||||||
|
summary.setActivityKind(ActivityKind.UNKNOWN.getCode());
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
return summaries.get(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.FileType;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.FileType;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionHrvStatus;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionHrvStatus;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionSleepStage;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionSleepStage;
|
||||||
@ -299,9 +300,11 @@ public class FitImporter {
|
|||||||
// This ensures idempotency when re-processing
|
// This ensures idempotency when re-processing
|
||||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
final DaoSession session = dbHandler.getDaoSession();
|
final DaoSession session = dbHandler.getDaoSession();
|
||||||
final Device device = DBHelper.getDevice(gbDevice, session);
|
summary = ActivitySummaryParser.findOrCreateBaseActivitySummary(
|
||||||
final User user = DBHelper.getUser(session);
|
session,
|
||||||
summary = findOrCreateBaseActivitySummary(session, device, user, Objects.requireNonNull(fileId.getTimeCreated()).intValue());
|
gbDevice,
|
||||||
|
Objects.requireNonNull(fileId.getTimeCreated()).intValue()
|
||||||
|
);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
GB.toast(context, "Error finding base summary", Toast.LENGTH_LONG, GB.ERROR, e);
|
GB.toast(context, "Error finding base summary", Toast.LENGTH_LONG, GB.ERROR, e);
|
||||||
return;
|
return;
|
||||||
@ -325,34 +328,6 @@ public class FitImporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static BaseActivitySummary findOrCreateBaseActivitySummary(final DaoSession session,
|
|
||||||
final Device device,
|
|
||||||
final User user,
|
|
||||||
final int timestampSeconds) {
|
|
||||||
final BaseActivitySummaryDao summaryDao = session.getBaseActivitySummaryDao();
|
|
||||||
final QueryBuilder<BaseActivitySummary> qb = summaryDao.queryBuilder();
|
|
||||||
qb.where(BaseActivitySummaryDao.Properties.StartTime.eq(new Date(timestampSeconds * 1000L)));
|
|
||||||
qb.where(BaseActivitySummaryDao.Properties.DeviceId.eq(device.getId()));
|
|
||||||
qb.where(BaseActivitySummaryDao.Properties.UserId.eq(user.getId()));
|
|
||||||
final List<BaseActivitySummary> summaries = qb.build().list();
|
|
||||||
if (summaries.isEmpty()) {
|
|
||||||
final BaseActivitySummary summary = new BaseActivitySummary();
|
|
||||||
summary.setStartTime(new Date(timestampSeconds * 1000L));
|
|
||||||
summary.setDevice(device);
|
|
||||||
summary.setUser(user);
|
|
||||||
|
|
||||||
// These will be set later, once we parse the summary
|
|
||||||
summary.setEndTime(new Date(timestampSeconds * 1000L));
|
|
||||||
summary.setActivityKind(ActivityKind.UNKNOWN.getCode());
|
|
||||||
|
|
||||||
return summary;
|
|
||||||
}
|
|
||||||
if (summaries.size() > 1) {
|
|
||||||
LOG.warn("Found multiple summaries for {}", timestampSeconds);
|
|
||||||
}
|
|
||||||
return summaries.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reset() {
|
private void reset() {
|
||||||
activitySamplesPerTimestamp.clear();
|
activitySamplesPerTimestamp.clear();
|
||||||
stressSamples.clear();
|
stressSamples.clear();
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -32,18 +33,23 @@ import de.greenrobot.dao.query.QueryBuilder;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Workout;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Workout;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutDataSampleDao;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutPaceSampleDao;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.HuaweiWorkoutSummarySampleDao;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryData;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryData;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryEntries;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||||
|
|
||||||
@ -52,11 +58,49 @@ import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
|||||||
* It also re-parses the unknown data from the workout tables
|
* It also re-parses the unknown data from the workout tables
|
||||||
* It is a separate class so it can easily be used to re-parse the data without database migrations
|
* It is a separate class so it can easily be used to re-parse the data without database migrations
|
||||||
*/
|
*/
|
||||||
public class HuaweiWorkoutGbParser {
|
public class HuaweiWorkoutGbParser implements ActivitySummaryParser {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(HuaweiWorkoutGbParser.class);
|
private static final Logger LOG = LoggerFactory.getLogger(HuaweiWorkoutGbParser.class);
|
||||||
|
|
||||||
// TODO: Might be nicer to propagate the exceptions, so they can be handled upstream
|
// TODO: Might be nicer to propagate the exceptions, so they can be handled upstream
|
||||||
|
|
||||||
|
private final GBDevice gbDevice;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public HuaweiWorkoutGbParser(final GBDevice gbDevice, final Context context) {
|
||||||
|
this.gbDevice = gbDevice;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseActivitySummary parseBinaryData(final BaseActivitySummary summary, final boolean forDetails) {
|
||||||
|
if (!forDetails) {
|
||||||
|
// Our parsing is too slow, especially without a RecyclerView
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the existing HuaweiWorkoutSummarySample
|
||||||
|
try (DBHandler db = GBApplication.acquireDB()) {
|
||||||
|
final DaoSession session = db.getDaoSession();
|
||||||
|
final Device device = DBHelper.getDevice(gbDevice, session);
|
||||||
|
final User user = DBHelper.getUser(session);
|
||||||
|
|
||||||
|
QueryBuilder<HuaweiWorkoutSummarySample> qb = session.getHuaweiWorkoutSummarySampleDao().queryBuilder();
|
||||||
|
qb.where(HuaweiWorkoutSummarySampleDao.Properties.StartTimestamp.eq(summary.getStartTime().getTime() / 1000));
|
||||||
|
qb.where(HuaweiWorkoutSummarySampleDao.Properties.DeviceId.eq(device.getId()));
|
||||||
|
qb.where(HuaweiWorkoutSummarySampleDao.Properties.UserId.eq(user.getId()));
|
||||||
|
final List<HuaweiWorkoutSummarySample> huaweiSummaries = qb.build().list();
|
||||||
|
if (huaweiSummaries.isEmpty()) {
|
||||||
|
LOG.warn("Failed to find huawei summary for {}", summary.getStartTime());
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
updateBaseSummary(db, huaweiSummaries.get(0), summary);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Failed to update summary");
|
||||||
|
}
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
public enum HuaweiActivityType {
|
public enum HuaweiActivityType {
|
||||||
// Based on nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.enums.GarminSport
|
// Based on nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.enums.GarminSport
|
||||||
|
|
||||||
@ -159,7 +203,7 @@ public class HuaweiWorkoutGbParser {
|
|||||||
MOTOR_AUTO_RACING(216, ActivityKind.AUTO_RACING),
|
MOTOR_AUTO_RACING(216, ActivityKind.AUTO_RACING),
|
||||||
ESPORTS(223, ActivityKind.ESPORTS),
|
ESPORTS(223, ActivityKind.ESPORTS),
|
||||||
PADEL(224, ActivityKind.PADEL),
|
PADEL(224, ActivityKind.PADEL),
|
||||||
OTHER(255, ActivityKind.EXERCISE)
|
OTHER(255, ActivityKind.EXERCISE),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final byte type;
|
private final byte type;
|
||||||
@ -187,7 +231,7 @@ public class HuaweiWorkoutGbParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parseAllWorkouts() {
|
public void parseAllWorkouts() {
|
||||||
parseUnknownWorkoutData();
|
parseUnknownWorkoutData();
|
||||||
|
|
||||||
try (DBHandler db = GBApplication.acquireDB()) {
|
try (DBHandler db = GBApplication.acquireDB()) {
|
||||||
@ -261,7 +305,7 @@ public class HuaweiWorkoutGbParser {
|
|||||||
return ActivityKind.UNKNOWN;
|
return ActivityKind.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parseWorkout(Long workoutId) {
|
public void parseWorkout(Long workoutId) {
|
||||||
if (workoutId == null)
|
if (workoutId == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -274,32 +318,34 @@ public class HuaweiWorkoutGbParser {
|
|||||||
return;
|
return;
|
||||||
HuaweiWorkoutSummarySample summary = summarySamples.get(0);
|
HuaweiWorkoutSummarySample summary = summarySamples.get(0);
|
||||||
|
|
||||||
|
final BaseActivitySummary baseSummary = ActivitySummaryParser.findOrCreateBaseActivitySummary(
|
||||||
|
db.getDaoSession(),
|
||||||
|
gbDevice,
|
||||||
|
summary.getStartTimestamp()
|
||||||
|
);
|
||||||
|
|
||||||
|
updateBaseSummary(db, summary, baseSummary);
|
||||||
|
|
||||||
|
db.getDaoSession().getBaseActivitySummaryDao().insertOrReplace(baseSummary);
|
||||||
|
} catch (Exception e) {
|
||||||
|
GB.toast("Exception parsing workout data", Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||||
|
LOG.error("Exception parsing workout data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBaseSummary(final DBHandler db,
|
||||||
|
final HuaweiWorkoutSummarySample summary,
|
||||||
|
final BaseActivitySummary baseSummary) {
|
||||||
|
try {
|
||||||
QueryBuilder<HuaweiWorkoutDataSample> qbData = db.getDaoSession().getHuaweiWorkoutDataSampleDao().queryBuilder().where(
|
QueryBuilder<HuaweiWorkoutDataSample> qbData = db.getDaoSession().getHuaweiWorkoutDataSampleDao().queryBuilder().where(
|
||||||
HuaweiWorkoutDataSampleDao.Properties.WorkoutId.eq(workoutId)
|
HuaweiWorkoutDataSampleDao.Properties.WorkoutId.eq(summary.getWorkoutId())
|
||||||
);
|
);
|
||||||
List<HuaweiWorkoutDataSample> dataSamples = qbData.build().list();
|
List<HuaweiWorkoutDataSample> dataSamples = qbData.build().list();
|
||||||
|
|
||||||
QueryBuilder<HuaweiWorkoutPaceSample> qbPace = db.getDaoSession().getHuaweiWorkoutPaceSampleDao().queryBuilder().where(
|
QueryBuilder<HuaweiWorkoutPaceSample> qbPace = db.getDaoSession().getHuaweiWorkoutPaceSampleDao().queryBuilder().where(
|
||||||
HuaweiWorkoutPaceSampleDao.Properties.WorkoutId.eq(workoutId)
|
HuaweiWorkoutPaceSampleDao.Properties.WorkoutId.eq(summary.getWorkoutId())
|
||||||
);
|
);
|
||||||
|
|
||||||
long userId = summary.getUserId();
|
|
||||||
long deviceId = summary.getDeviceId();
|
|
||||||
Date start = new Date(summary.getStartTimestamp() * 1000L);
|
|
||||||
Date end = new Date(summary.getEndTimestamp() * 1000L);
|
|
||||||
|
|
||||||
// Avoid duplicates
|
|
||||||
QueryBuilder<BaseActivitySummary> qb = db.getDaoSession().getBaseActivitySummaryDao().queryBuilder().where(
|
|
||||||
BaseActivitySummaryDao.Properties.UserId.eq(userId),
|
|
||||||
BaseActivitySummaryDao.Properties.DeviceId.eq(deviceId),
|
|
||||||
BaseActivitySummaryDao.Properties.StartTime.eq(start),
|
|
||||||
BaseActivitySummaryDao.Properties.EndTime.eq(end)
|
|
||||||
);
|
|
||||||
List<BaseActivitySummary> duplicates = qb.build().list();
|
|
||||||
BaseActivitySummary previous = null;
|
|
||||||
if (!duplicates.isEmpty())
|
|
||||||
previous = duplicates.get(0);
|
|
||||||
|
|
||||||
ActivityKind type = huaweiTypeToGbType(summary.getType());
|
ActivityKind type = huaweiTypeToGbType(summary.getType());
|
||||||
|
|
||||||
ActivitySummaryData summaryData = new ActivitySummaryData();
|
ActivitySummaryData summaryData = new ActivitySummaryData();
|
||||||
@ -665,43 +711,13 @@ public class HuaweiWorkoutGbParser {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseActivitySummary baseSummary;
|
if (baseSummary.getName() == null) {
|
||||||
if (previous == null) {
|
baseSummary.setName("Workout " + summary.getWorkoutNumber());
|
||||||
baseSummary = new BaseActivitySummary(
|
|
||||||
null,
|
|
||||||
"Workout " + summary.getWorkoutNumber(),
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
type.getCode(),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
deviceId,
|
|
||||||
userId,
|
|
||||||
summaryData.toString(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
baseSummary = new BaseActivitySummary(
|
|
||||||
previous.getId(),
|
|
||||||
previous.getName(),
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
type.getCode(),
|
|
||||||
previous.getBaseLongitude(),
|
|
||||||
previous.getBaseLatitude(),
|
|
||||||
previous.getBaseAltitude(),
|
|
||||||
previous.getGpxTrack(),
|
|
||||||
previous.getRawDetailsPath(),
|
|
||||||
deviceId,
|
|
||||||
userId,
|
|
||||||
summaryData.toString(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
db.getDaoSession().getBaseActivitySummaryDao().insertOrReplace(baseSummary);
|
// start time never changes
|
||||||
|
baseSummary.setEndTime(new Date(summary.getEndTimestamp() * 1000L));
|
||||||
|
baseSummary.setActivityKind(type.getCode());
|
||||||
|
baseSummary.setSummaryData(summaryData.toString());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
GB.toast("Exception parsing workout data", Toast.LENGTH_SHORT, GB.ERROR, e);
|
GB.toast("Exception parsing workout data", Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||||
LOG.error("Exception parsing workout data", e);
|
LOG.error("Exception parsing workout data", e);
|
||||||
|
@ -112,9 +112,9 @@ public class GetWorkoutDataRequest extends Request {
|
|||||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||||
this.nextRequest(nextRequest);
|
this.nextRequest(nextRequest);
|
||||||
} else {
|
} else {
|
||||||
HuaweiWorkoutGbParser.parseWorkout(this.databaseId);
|
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(this.databaseId);
|
||||||
|
|
||||||
if (remainder.size() > 0) {
|
if (!remainder.isEmpty()) {
|
||||||
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
|
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
|
||||||
this.supportProvider,
|
this.supportProvider,
|
||||||
remainder.remove(0),
|
remainder.remove(0),
|
||||||
|
@ -89,9 +89,9 @@ public class GetWorkoutPaceRequest extends Request {
|
|||||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||||
this.nextRequest(nextRequest);
|
this.nextRequest(nextRequest);
|
||||||
} else {
|
} else {
|
||||||
HuaweiWorkoutGbParser.parseWorkout(this.databaseId);
|
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(this.databaseId);
|
||||||
|
|
||||||
if (remainder.size() > 0) {
|
if (!remainder.isEmpty()) {
|
||||||
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
|
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
|
||||||
this.supportProvider,
|
this.supportProvider,
|
||||||
remainder.remove(0),
|
remainder.remove(0),
|
||||||
|
@ -103,9 +103,9 @@ public class GetWorkoutTotalsRequest extends Request {
|
|||||||
nextRequest.setFinalizeReq(this.finalizeReq);
|
nextRequest.setFinalizeReq(this.finalizeReq);
|
||||||
this.nextRequest(nextRequest);
|
this.nextRequest(nextRequest);
|
||||||
} else {
|
} else {
|
||||||
HuaweiWorkoutGbParser.parseWorkout(databaseId);
|
new HuaweiWorkoutGbParser(getDevice(), getContext()).parseWorkout(databaseId);
|
||||||
|
|
||||||
if (remainder.size() > 0) {
|
if (!remainder.isEmpty()) {
|
||||||
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
|
GetWorkoutTotalsRequest nextRequest = new GetWorkoutTotalsRequest(
|
||||||
this.supportProvider,
|
this.supportProvider,
|
||||||
remainder.remove(0),
|
remainder.remove(0),
|
||||||
|
Loading…
Reference in New Issue
Block a user