mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-03-13 17:50:23 +01:00
Allow gadgets to provide distance and calories
This commit is contained in:
parent
6258ccd4db
commit
c700d49bf0
@ -61,16 +61,14 @@ public class Widget extends AppWidgetProvider {
|
|||||||
static BroadcastReceiver broadcastReceiver = null;
|
static BroadcastReceiver broadcastReceiver = null;
|
||||||
|
|
||||||
|
|
||||||
private long[] getSteps(GBDevice gbDevice) {
|
private DailyTotals getSteps(GBDevice gbDevice) {
|
||||||
Context context = GBApplication.getContext();
|
Context context = GBApplication.getContext();
|
||||||
Calendar day = GregorianCalendar.getInstance();
|
Calendar day = GregorianCalendar.getInstance();
|
||||||
|
|
||||||
if (!(context instanceof GBApplication)) {
|
if (!(context instanceof GBApplication)) {
|
||||||
return new long[]{0, 0, 0};
|
return new DailyTotals();
|
||||||
}
|
}
|
||||||
DailyTotals ds = new DailyTotals();
|
return DailyTotals.getDailyTotalsForDevice(gbDevice, day);
|
||||||
return ds.getDailyTotalsForDevice(gbDevice, day);
|
|
||||||
//return ds.getDailyTotalsForAllDevices(day);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getHM(long value) {
|
private String getHM(long value) {
|
||||||
@ -117,16 +115,17 @@ public class Widget extends AppWidgetProvider {
|
|||||||
PendingIntent startChartsPIntent = PendingIntentUtils.getActivity(context, appWidgetId, startChartsIntent, PendingIntent.FLAG_CANCEL_CURRENT, false);
|
PendingIntent startChartsPIntent = PendingIntentUtils.getActivity(context, appWidgetId, startChartsIntent, PendingIntent.FLAG_CANCEL_CURRENT, false);
|
||||||
views.setOnClickPendingIntent(R.id.todaywidget_bottom_layout, startChartsPIntent);
|
views.setOnClickPendingIntent(R.id.todaywidget_bottom_layout, startChartsPIntent);
|
||||||
|
|
||||||
long[] dailyTotals = getSteps(deviceForWidget);
|
DailyTotals dailyTotals = getSteps(deviceForWidget);
|
||||||
int steps = (int) dailyTotals[0];
|
int steps = (int) dailyTotals.getSteps();
|
||||||
int sleep = (int) dailyTotals[1];
|
int sleep = (int) dailyTotals.getSleep();
|
||||||
|
int distanceCm = (int) dailyTotals.getDistance();
|
||||||
ActivityUser activityUser = new ActivityUser();
|
ActivityUser activityUser = new ActivityUser();
|
||||||
int stepGoal = activityUser.getStepsGoal();
|
int stepGoal = activityUser.getStepsGoal();
|
||||||
int sleepGoal = activityUser.getSleepDurationGoal();
|
int sleepGoal = activityUser.getSleepDurationGoal();
|
||||||
int sleepGoalMinutes = sleepGoal * 60;
|
int sleepGoalMinutes = sleepGoal * 60;
|
||||||
int distanceGoal = activityUser.getDistanceGoalMeters() * 100;
|
int distanceGoal = activityUser.getDistanceGoalMeters() * 100;
|
||||||
int stepLength = activityUser.getStepLengthCm();
|
int stepLength = activityUser.getStepLengthCm();
|
||||||
double distanceMeters = dailyTotals[0] * stepLength * 0.01;
|
double distanceMeters = (distanceCm > 0 ? distanceCm : steps * stepLength) * 0.01;
|
||||||
String distanceFormatted = FormatUtils.getFormattedDistanceLabel(distanceMeters);
|
String distanceFormatted = FormatUtils.getFormattedDistanceLabel(distanceMeters);
|
||||||
|
|
||||||
if (sleep < 1) {
|
if (sleep < 1) {
|
||||||
|
@ -66,7 +66,7 @@ public class DevicesFragment extends Fragment {
|
|||||||
private RecyclerView deviceListView;
|
private RecyclerView deviceListView;
|
||||||
private FloatingActionButton fab;
|
private FloatingActionButton fab;
|
||||||
List<GBDevice> deviceList;
|
List<GBDevice> deviceList;
|
||||||
private HashMap<String,long[]> deviceActivityHashMap = new HashMap();
|
private HashMap<String, DailyTotals> deviceActivityHashMap = new HashMap();
|
||||||
|
|
||||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
@ -219,11 +219,10 @@ public class DevicesFragment extends Fragment {
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long[] getSteps(GBDevice device, DBHandler db) {
|
private DailyTotals getSteps(GBDevice device, DBHandler db) {
|
||||||
Calendar day = GregorianCalendar.getInstance();
|
Calendar day = GregorianCalendar.getInstance();
|
||||||
|
|
||||||
DailyTotals ds = new DailyTotals();
|
return DailyTotals.getDailyTotalsForDevice(device, day, db);
|
||||||
return ds.getDailyTotalsForDevice(device, day, db);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshPairedDevices() {
|
public void refreshPairedDevices() {
|
||||||
@ -266,7 +265,7 @@ public class DevicesFragment extends Fragment {
|
|||||||
final DeviceCoordinator coordinator = gbDevice.getDeviceCoordinator();
|
final DeviceCoordinator coordinator = gbDevice.getDeviceCoordinator();
|
||||||
final boolean showActivityCard = GBApplication.getDevicePrefs(gbDevice).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD, true);
|
final boolean showActivityCard = GBApplication.getDevicePrefs(gbDevice).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD, true);
|
||||||
if (coordinator.supportsActivityTracking() && showActivityCard) {
|
if (coordinator.supportsActivityTracking() && showActivityCard) {
|
||||||
final long[] stepsAndSleepData = getSteps(gbDevice, db);
|
final DailyTotals stepsAndSleepData = getSteps(gbDevice, db);
|
||||||
deviceActivityHashMap.put(gbDevice.getAddress(), stepsAndSleepData);
|
deviceActivityHashMap.put(gbDevice.getAddress(), stepsAndSleepData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,11 @@ public class ActivityAnalysis {
|
|||||||
amount.addSteps(steps);
|
amount.addSteps(steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int distance = sample.getDistanceCm();
|
||||||
|
if (distance >= 0) {
|
||||||
|
amount.addDistance(distance);
|
||||||
|
}
|
||||||
|
|
||||||
if (previousSample != null) {
|
if (previousSample != null) {
|
||||||
long timeDifference = sample.getTimestamp() - previousSample.getTimestamp();
|
long timeDifference = sample.getTimestamp() - previousSample.getTimestamp();
|
||||||
if (previousSample.getRawKind() == sample.getRawKind()) {
|
if (previousSample.getRawKind() == sample.getRawKind()) {
|
||||||
|
@ -35,7 +35,7 @@ public class StepAnalysis {
|
|||||||
private int totalDailySteps = 0;
|
private int totalDailySteps = 0;
|
||||||
|
|
||||||
public List<ActivitySession> calculateStepSessions(List<? extends ActivitySample> samples) {
|
public List<ActivitySession> calculateStepSessions(List<? extends ActivitySample> samples) {
|
||||||
LOG.debug("get all samples activitysessions: " + samples.toArray().length);
|
LOG.debug("get all samples activity sessions: {}", samples.size());
|
||||||
List<ActivitySession> result = new ArrayList<>();
|
List<ActivitySession> result = new ArrayList<>();
|
||||||
ActivityUser activityUser = new ActivityUser();
|
ActivityUser activityUser = new ActivityUser();
|
||||||
final int MIN_SESSION_LENGTH = 60 * GBApplication.getPrefs().getInt("chart_list_min_session_length", 5);
|
final int MIN_SESSION_LENGTH = 60 * GBApplication.getPrefs().getInt("chart_list_min_session_length", 5);
|
||||||
@ -50,7 +50,9 @@ public class StepAnalysis {
|
|||||||
Date sessionStart = null;
|
Date sessionStart = null;
|
||||||
Date sessionEnd;
|
Date sessionEnd;
|
||||||
int activeSteps = 0; //steps that we count
|
int activeSteps = 0; //steps that we count
|
||||||
|
int activeDistanceCm = 0;
|
||||||
int stepsBetweenActivePeriods = 0; //steps during time when we maybe take a rest but then restart
|
int stepsBetweenActivePeriods = 0; //steps during time when we maybe take a rest but then restart
|
||||||
|
int distanceBetweenActivePeriods = 0;
|
||||||
int durationSinceLastActiveStep = 0;
|
int durationSinceLastActiveStep = 0;
|
||||||
ActivityKind activityKind;
|
ActivityKind activityKind;
|
||||||
|
|
||||||
@ -77,7 +79,18 @@ public class StepAnalysis {
|
|||||||
|
|
||||||
if (sessionStart == null) {
|
if (sessionStart == null) {
|
||||||
sessionStart = getDateFromSample(sample);
|
sessionStart = getDateFromSample(sample);
|
||||||
activeSteps = sample.getSteps();
|
if (sample.getSteps() >= 0) {
|
||||||
|
activeSteps = sample.getSteps();
|
||||||
|
} else {
|
||||||
|
activeSteps = 0;
|
||||||
|
}
|
||||||
|
if (sample.getDistanceCm() >= 0) {
|
||||||
|
activeDistanceCm = sample.getDistanceCm();
|
||||||
|
} else if (activeSteps > 0) {
|
||||||
|
activeDistanceCm = activeSteps * stepLengthCm;
|
||||||
|
} else {
|
||||||
|
activeDistanceCm = 0;
|
||||||
|
}
|
||||||
activeIntensity = sample.getIntensity();
|
activeIntensity = sample.getIntensity();
|
||||||
heartRateSum = new ArrayList<>();
|
heartRateSum = new ArrayList<>();
|
||||||
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
||||||
@ -85,6 +98,7 @@ public class StepAnalysis {
|
|||||||
}
|
}
|
||||||
durationSinceLastActiveStep = 0;
|
durationSinceLastActiveStep = 0;
|
||||||
stepsBetweenActivePeriods = 0;
|
stepsBetweenActivePeriods = 0;
|
||||||
|
distanceBetweenActivePeriods = 0;
|
||||||
heartRateBetweenActivePeriodsSum = new ArrayList<>();
|
heartRateBetweenActivePeriodsSum = new ArrayList<>();
|
||||||
previousSample = null;
|
previousSample = null;
|
||||||
}
|
}
|
||||||
@ -94,6 +108,11 @@ public class StepAnalysis {
|
|||||||
if (sample.getSteps() > MIN_STEPS_PER_MINUTE || //either some steps
|
if (sample.getSteps() > MIN_STEPS_PER_MINUTE || //either some steps
|
||||||
(sample.getIntensity() > MIN_SESSION_INTENSITY && sample.getSteps() > 0)) { //or some intensity plus at least one step
|
(sample.getIntensity() > MIN_SESSION_INTENSITY && sample.getSteps() > 0)) { //or some intensity plus at least one step
|
||||||
activeSteps += sample.getSteps() + stepsBetweenActivePeriods;
|
activeSteps += sample.getSteps() + stepsBetweenActivePeriods;
|
||||||
|
if (sample.getDistanceCm() >= 0) {
|
||||||
|
activeDistanceCm += sample.getDistanceCm() + distanceBetweenActivePeriods;
|
||||||
|
} else {
|
||||||
|
activeDistanceCm += sample.getSteps() * stepLengthCm + distanceBetweenActivePeriods;
|
||||||
|
}
|
||||||
activeIntensity += sample.getIntensity() + intensityBetweenActivePeriods;
|
activeIntensity += sample.getIntensity() + intensityBetweenActivePeriods;
|
||||||
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
||||||
heartRateSum.add(sample.getHeartRate());
|
heartRateSum.add(sample.getHeartRate());
|
||||||
@ -101,11 +120,19 @@ public class StepAnalysis {
|
|||||||
heartRateSum.addAll(heartRateBetweenActivePeriodsSum);
|
heartRateSum.addAll(heartRateBetweenActivePeriodsSum);
|
||||||
heartRateBetweenActivePeriodsSum = new ArrayList<>();
|
heartRateBetweenActivePeriodsSum = new ArrayList<>();
|
||||||
stepsBetweenActivePeriods = 0;
|
stepsBetweenActivePeriods = 0;
|
||||||
|
distanceBetweenActivePeriods = 0;
|
||||||
intensityBetweenActivePeriods = 0;
|
intensityBetweenActivePeriods = 0;
|
||||||
durationSinceLastActiveStep = 0;
|
durationSinceLastActiveStep = 0;
|
||||||
|
|
||||||
} else { //short break data to remember, we will add it to the rest later, if break not too long
|
} else { //short break data to remember, we will add it to the rest later, if break not too long
|
||||||
stepsBetweenActivePeriods += sample.getSteps();
|
if (sample.getSteps() >= 0) {
|
||||||
|
stepsBetweenActivePeriods += sample.getSteps();
|
||||||
|
}
|
||||||
|
if (sample.getDistanceCm() >= 0) {
|
||||||
|
distanceBetweenActivePeriods += sample.getDistanceCm();
|
||||||
|
} else if (sample.getSteps() > 0) {
|
||||||
|
distanceBetweenActivePeriods += sample.getSteps() * stepLengthCm;
|
||||||
|
}
|
||||||
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
if (heartRateUtilsInstance.isValidHeartRateValue(sample.getHeartRate())) {
|
||||||
heartRateBetweenActivePeriodsSum.add(sample.getHeartRate());
|
heartRateBetweenActivePeriodsSum.add(sample.getHeartRate());
|
||||||
}
|
}
|
||||||
@ -120,7 +147,7 @@ public class StepAnalysis {
|
|||||||
|
|
||||||
if (session_length >= MIN_SESSION_LENGTH) { //valid activity session
|
if (session_length >= MIN_SESSION_LENGTH) { //valid activity session
|
||||||
int heartRateAverage = heartRateSum.toArray().length > 0 ? calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length : 0;
|
int heartRateAverage = heartRateSum.toArray().length > 0 ? calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length : 0;
|
||||||
float distance = (float) (activeSteps * STEP_LENGTH_M);
|
float distance = activeDistanceCm * 0.01f;
|
||||||
sessionEnd = new Date((sample.getTimestamp() - durationSinceLastActiveStep) * 1000L);
|
sessionEnd = new Date((sample.getTimestamp() - durationSinceLastActiveStep) * 1000L);
|
||||||
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
|
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
|
||||||
ActivitySession activitySession = new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind);
|
ActivitySession activitySession = new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind);
|
||||||
@ -135,14 +162,14 @@ public class StepAnalysis {
|
|||||||
}
|
}
|
||||||
//trailing activity: make sure we show the last portion of the data as well in case no further activity is recorded yet
|
//trailing activity: make sure we show the last portion of the data as well in case no further activity is recorded yet
|
||||||
|
|
||||||
if (sessionStart != null && previousSample != null) {
|
if (sessionStart != null) {
|
||||||
int current = previousSample.getTimestamp();
|
int current = previousSample.getTimestamp();
|
||||||
int starting = (int) (sessionStart.getTime() / 1000);
|
int starting = (int) (sessionStart.getTime() / 1000);
|
||||||
int session_length = current - starting - durationSinceLastActiveStep;
|
int session_length = current - starting - durationSinceLastActiveStep;
|
||||||
|
|
||||||
if (session_length >= MIN_SESSION_LENGTH) {
|
if (session_length >= MIN_SESSION_LENGTH) {
|
||||||
int heartRateAverage = heartRateSum.toArray().length > 0 ? calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length : 0;
|
int heartRateAverage = heartRateSum.toArray().length > 0 ? calculateSumOfInts(heartRateSum) / heartRateSum.toArray().length : 0;
|
||||||
float distance = (float) (activeSteps * STEP_LENGTH_M);
|
float distance = activeDistanceCm * 0.01f;
|
||||||
sessionEnd = getDateFromSample(previousSample);
|
sessionEnd = getDateFromSample(previousSample);
|
||||||
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
|
activityKind = detect_activity_kind(session_length, activeSteps, heartRateAverage, activeIntensity);
|
||||||
ActivitySession ongoingActivity = new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind);
|
ActivitySession ongoingActivity = new ActivitySession(sessionStart, sessionEnd, activeSteps, heartRateAverage, activeIntensity, distance, activityKind);
|
||||||
|
@ -291,8 +291,7 @@ public class StepStreaksDashboard extends MaterialDialogFragment {
|
|||||||
int all_steps = 0;
|
int all_steps = 0;
|
||||||
int firstDataTimestamp = 0;
|
int firstDataTimestamp = 0;
|
||||||
|
|
||||||
DailyTotals dailyTotals = new DailyTotals();
|
ActivitySample firstSample = DailyTotals.getFirstSample(db, device);
|
||||||
ActivitySample firstSample = dailyTotals.getFirstSample(db, device);
|
|
||||||
if (firstSample == null) { //no data at all
|
if (firstSample == null) { //no data at all
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -306,8 +305,8 @@ public class StepStreaksDashboard extends MaterialDialogFragment {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
long[] daily_data = dailyTotals.getDailyTotalsForDevice(device, day, db);
|
DailyTotals daily_data = DailyTotals.getDailyTotalsForDevice(device, day, db);
|
||||||
int steps_this_day = (int) daily_data[0];
|
int steps_this_day = (int) daily_data.getSteps();
|
||||||
|
|
||||||
if (steps_this_day > 0) {
|
if (steps_this_day > 0) {
|
||||||
all_step_days++;
|
all_step_days++;
|
||||||
|
@ -51,20 +51,25 @@ abstract class StepsFragment<T extends ChartsData> extends AbstractChartFragment
|
|||||||
List<StepsDay> daysData = new ArrayList<>();;
|
List<StepsDay> daysData = new ArrayList<>();;
|
||||||
for (int counter = 0; counter < TOTAL_DAYS; counter++) {
|
for (int counter = 0; counter < TOTAL_DAYS; counter++) {
|
||||||
long totalSteps = 0;
|
long totalSteps = 0;
|
||||||
|
long totalDistance = 0;
|
||||||
ActivityAmounts amounts = getActivityAmountsForDay(db, day, device);
|
ActivityAmounts amounts = getActivityAmountsForDay(db, day, device);
|
||||||
for (ActivityAmount amount : amounts.getAmounts()) {
|
for (ActivityAmount amount : amounts.getAmounts()) {
|
||||||
if (amount.getTotalSteps() > 0) {
|
if (amount.getTotalSteps() > 0) {
|
||||||
totalSteps += amount.getTotalSteps();
|
totalSteps += amount.getTotalSteps();
|
||||||
}
|
}
|
||||||
|
if (amount.getTotalDistance() > 0) {
|
||||||
|
totalDistance += amount.getTotalDistance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
double distance = 0;
|
double distance = totalDistance;
|
||||||
if (totalSteps > 0) {
|
if (totalDistance == 0 && totalSteps > 0) {
|
||||||
|
// For gadgets that do not report distance, compute it from the steps
|
||||||
ActivityUser activityUser = new ActivityUser();
|
ActivityUser activityUser = new ActivityUser();
|
||||||
int stepLength = activityUser.getStepLengthCm();
|
int stepLength = activityUser.getStepLengthCm();
|
||||||
distance = ((stepLength * 1.0 / 100) * totalSteps) / 1000;
|
distance = stepLength * totalSteps;
|
||||||
}
|
}
|
||||||
Calendar d = (Calendar) day.clone();
|
Calendar d = (Calendar) day.clone();
|
||||||
daysData.add(new StepsDay(d, totalSteps, distance));
|
daysData.add(new StepsDay(d, totalSteps, distance / 100_000));
|
||||||
day.add(Calendar.DATE, 1);
|
day.add(Calendar.DATE, 1);
|
||||||
}
|
}
|
||||||
return daysData;
|
return daysData;
|
||||||
|
@ -122,6 +122,7 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceFolder;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.DailyTotals;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
@ -143,10 +144,10 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
|
|||||||
private String expandedDeviceAddress = "";
|
private String expandedDeviceAddress = "";
|
||||||
private String expandedFolderName = "";
|
private String expandedFolderName = "";
|
||||||
private ViewGroup parent;
|
private ViewGroup parent;
|
||||||
private HashMap<String, long[]> deviceActivityMap = new HashMap();
|
private HashMap<String, DailyTotals> deviceActivityMap = new HashMap<>();
|
||||||
private final StableIdGenerator idGenerator = new StableIdGenerator();
|
private final StableIdGenerator idGenerator = new StableIdGenerator();
|
||||||
|
|
||||||
public GBDeviceAdapterv2(Context context, List<GBDevice> deviceList, HashMap<String,long[]> deviceMap) {
|
public GBDeviceAdapterv2(Context context, List<GBDevice> deviceList, HashMap<String, DailyTotals> deviceMap) {
|
||||||
super(new GBDeviceDiffUtil());
|
super(new GBDeviceDiffUtil());
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.deviceList = deviceList;
|
this.deviceList = deviceList;
|
||||||
@ -304,7 +305,7 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
|
|||||||
holder.container.setVisibility(View.VISIBLE);
|
holder.container.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
long[] dailyTotals = new long[]{0, 0};
|
DailyTotals dailyTotals = new DailyTotals();
|
||||||
if (deviceActivityMap.containsKey(device.getAddress())) {
|
if (deviceActivityMap.containsKey(device.getAddress())) {
|
||||||
dailyTotals = deviceActivityMap.get(device.getAddress());
|
dailyTotals = deviceActivityMap.get(device.getAddress());
|
||||||
}
|
}
|
||||||
@ -1331,7 +1332,7 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
|
|||||||
snackbar.show();
|
snackbar.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setActivityCard(ViewHolder holder, final GBDevice device, long[] dailyTotals) {
|
private void setActivityCard(ViewHolder holder, final GBDevice device, DailyTotals dailyTotals) {
|
||||||
boolean showActivityCard = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD, true);
|
boolean showActivityCard = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress()).getBoolean(DeviceSettingsPreferenceConst.PREFS_ACTIVITY_IN_DEVICE_CARD, true);
|
||||||
holder.cardViewActivityCardLayout.setVisibility(showActivityCard ? View.VISIBLE : View.GONE);
|
holder.cardViewActivityCardLayout.setVisibility(showActivityCard ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
@ -1339,15 +1340,16 @@ public class GBDeviceAdapterv2 extends ListAdapter<GBDevice, GBDeviceAdapterv2.V
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int steps = (int) dailyTotals[0];
|
int steps = (int) dailyTotals.getSteps();
|
||||||
int sleep = (int) dailyTotals[1];
|
int sleep = (int) dailyTotals.getSleep();
|
||||||
|
int distanceCm = (int) dailyTotals.getDistance();
|
||||||
ActivityUser activityUser = new ActivityUser();
|
ActivityUser activityUser = new ActivityUser();
|
||||||
int stepGoal = activityUser.getStepsGoal();
|
int stepGoal = activityUser.getStepsGoal();
|
||||||
int sleepGoal = activityUser.getSleepDurationGoal();
|
int sleepGoal = activityUser.getSleepDurationGoal();
|
||||||
int sleepGoalMinutes = sleepGoal * 60;
|
int sleepGoalMinutes = sleepGoal * 60;
|
||||||
int distanceGoal = activityUser.getDistanceGoalMeters() * 100;
|
int distanceGoal = activityUser.getDistanceGoalMeters() * 100;
|
||||||
int stepLength = activityUser.getStepLengthCm();
|
int stepLength = activityUser.getStepLengthCm();
|
||||||
double distanceMeters = dailyTotals[0] * stepLength * 0.01;
|
double distanceMeters = (distanceCm > 0 ? distanceCm : steps * stepLength) * 0.01;
|
||||||
String distanceFormatted = FormatUtils.getFormattedDistanceLabel(distanceMeters);
|
String distanceFormatted = FormatUtils.getFormattedDistanceLabel(distanceMeters);
|
||||||
|
|
||||||
setUpChart(holder.TotalStepsChart);
|
setUpChart(holder.TotalStepsChart);
|
||||||
|
@ -28,6 +28,7 @@ import java.time.LocalDate;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -197,7 +198,10 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
// Steps on the Garmin Watch are reported cumulatively per day - convert them to
|
// Steps on the Garmin Watch are reported cumulatively per day - convert them to
|
||||||
// This slightly breaks activity recognition, because we don't have per-minute granularity...
|
// This slightly breaks activity recognition, because we don't have per-minute granularity...
|
||||||
int prevSteps = samples.get(0).getSteps();
|
int prevSteps = samples.get(0).getSteps();
|
||||||
|
int prevDistance = samples.get(0).getDistanceCm();
|
||||||
|
int prevActiveCalories = samples.get(0).getActiveCalories();
|
||||||
samples.get(0).setTimestamp((samples.get(0).getTimestamp() / 60) * 60);
|
samples.get(0).setTimestamp((samples.get(0).getTimestamp() / 60) * 60);
|
||||||
|
int bak;
|
||||||
|
|
||||||
for (int i = 1; i < samples.size(); i++) {
|
for (int i = 1; i < samples.size(); i++) {
|
||||||
final T s1 = samples.get(i - 1);
|
final T s1 = samples.get(i - 1);
|
||||||
@ -207,11 +211,26 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
if (!sameDay(s1, s2)) {
|
if (!sameDay(s1, s2)) {
|
||||||
// went past midnight - reset steps
|
// went past midnight - reset steps
|
||||||
prevSteps = s2.getSteps() > 0 ? s2.getSteps() : 0;
|
prevSteps = s2.getSteps() > 0 ? s2.getSteps() : 0;
|
||||||
} else if (s2.getSteps() > 0) {
|
prevDistance = s2.getDistanceCm() > 0 ? s2.getDistanceCm() : 0;
|
||||||
// New steps sample for the current day - subtract the previous seen sample
|
prevActiveCalories = s2.getActiveCalories() > 0 ? s2.getActiveCalories() : 0;
|
||||||
int bak = s2.getSteps();
|
} else {
|
||||||
s2.setSteps(s2.getSteps() - prevSteps);
|
// New value for the current day - subtract the previous seen sample
|
||||||
prevSteps = bak;
|
|
||||||
|
if (s2.getSteps() > 0) {
|
||||||
|
bak = s2.getSteps();
|
||||||
|
s2.setSteps(s2.getSteps() - prevSteps);
|
||||||
|
prevSteps = bak;
|
||||||
|
}
|
||||||
|
if (s2.getDistanceCm() > 0) {
|
||||||
|
bak = s2.getDistanceCm();
|
||||||
|
s2.setDistanceCm(s2.getDistanceCm() - prevDistance);
|
||||||
|
prevDistance = bak;
|
||||||
|
}
|
||||||
|
if (s2.getActiveCalories() > 0) {
|
||||||
|
bak = s2.getActiveCalories();
|
||||||
|
s2.setActiveCalories(s2.getActiveCalories() - prevActiveCalories);
|
||||||
|
prevActiveCalories = bak;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +274,7 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
|
|
||||||
final long nanoStart = System.nanoTime();
|
final long nanoStart = System.nanoTime();
|
||||||
|
|
||||||
final List<T> ret = new ArrayList<>(samples);
|
final List<T> ret = new LinkedList<>(samples);
|
||||||
|
|
||||||
//ret.sort(Comparator.comparingLong(T::getTimestamp));
|
//ret.sort(Comparator.comparingLong(T::getTimestamp));
|
||||||
|
|
||||||
@ -263,13 +282,7 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
if (firstTimestamp - timestamp_from > 60) {
|
if (firstTimestamp - timestamp_from > 60) {
|
||||||
// Gap at the start
|
// Gap at the start
|
||||||
for (int ts = timestamp_from; ts <= firstTimestamp + 60; ts += 60) {
|
for (int ts = timestamp_from; ts <= firstTimestamp + 60; ts += 60) {
|
||||||
final T dummySample = createActivitySample();
|
ret.add(0, createDummySample(ts));
|
||||||
dummySample.setTimestamp(ts);
|
|
||||||
dummySample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
|
||||||
dummySample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
|
||||||
dummySample.setSteps(ActivitySample.NOT_MEASURED);
|
|
||||||
dummySample.setProvider(this);
|
|
||||||
ret.add(0, dummySample);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,13 +292,7 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
if (minTo - lastTimestamp > 60) {
|
if (minTo - lastTimestamp > 60) {
|
||||||
// Gap at the end
|
// Gap at the end
|
||||||
for (int ts = lastTimestamp + 60; ts <= minTo; ts += 60) {
|
for (int ts = lastTimestamp + 60; ts <= minTo; ts += 60) {
|
||||||
final T dummySample = createActivitySample();
|
ret.add(createDummySample(ts));
|
||||||
dummySample.setTimestamp(ts);
|
|
||||||
dummySample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
|
||||||
dummySample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
|
||||||
dummySample.setSteps(ActivitySample.NOT_MEASURED);
|
|
||||||
dummySample.setProvider(this);
|
|
||||||
ret.add(dummySample);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,13 +304,7 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
if (sample.getTimestamp() - previousSample.getTimestamp() > 60) {
|
if (sample.getTimestamp() - previousSample.getTimestamp() > 60) {
|
||||||
LOG.trace("Filling gap between {} and {}", Instant.ofEpochSecond(previousSample.getTimestamp() + 60), Instant.ofEpochSecond(sample.getTimestamp()));
|
LOG.trace("Filling gap between {} and {}", Instant.ofEpochSecond(previousSample.getTimestamp() + 60), Instant.ofEpochSecond(sample.getTimestamp()));
|
||||||
for (int ts = previousSample.getTimestamp() + 60; ts < sample.getTimestamp(); ts += 60) {
|
for (int ts = previousSample.getTimestamp() + 60; ts < sample.getTimestamp(); ts += 60) {
|
||||||
final T dummySample = createActivitySample();
|
it.add(createDummySample(ts));
|
||||||
dummySample.setTimestamp(ts);
|
|
||||||
dummySample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
|
||||||
dummySample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
|
||||||
dummySample.setSteps(ActivitySample.NOT_MEASURED);
|
|
||||||
dummySample.setProvider(this);
|
|
||||||
it.add(dummySample);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previousSample = sample;
|
previousSample = sample;
|
||||||
@ -318,4 +319,17 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private T createDummySample(final int ts) {
|
||||||
|
final T dummySample = createActivitySample();
|
||||||
|
dummySample.setTimestamp(ts);
|
||||||
|
dummySample.setRawKind(ActivityKind.UNKNOWN.getCode());
|
||||||
|
dummySample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||||
|
dummySample.setSteps(ActivitySample.NOT_MEASURED);
|
||||||
|
dummySample.setHeartRate(ActivitySample.NOT_MEASURED);
|
||||||
|
dummySample.setDistanceCm(ActivitySample.NOT_MEASURED);
|
||||||
|
dummySample.setActiveCalories(ActivitySample.NOT_MEASURED);
|
||||||
|
dummySample.setProvider(this);
|
||||||
|
return dummySample;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@ -39,8 +37,6 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
|
|
||||||
public class TestSampleProvider extends AbstractSampleProvider<TestSampleProvider.TestActivitySample> {
|
public class TestSampleProvider extends AbstractSampleProvider<TestSampleProvider.TestActivitySample> {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TestSampleProvider.class);
|
|
||||||
|
|
||||||
public TestSampleProvider(final GBDevice device, final DaoSession session) {
|
public TestSampleProvider(final GBDevice device, final DaoSession session) {
|
||||||
super(device, session);
|
super(device, session);
|
||||||
}
|
}
|
||||||
@ -59,12 +55,14 @@ public class TestSampleProvider extends AbstractSampleProvider<TestSampleProvide
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected Property getTimestampSampleProperty() {
|
protected Property getTimestampSampleProperty() {
|
||||||
|
//noinspection DataFlowIssue not database-backed
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected Property getDeviceIdentifierSampleProperty() {
|
protected Property getDeviceIdentifierSampleProperty() {
|
||||||
|
//noinspection DataFlowIssue not database-backed
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +157,7 @@ public class TestSampleProvider extends AbstractSampleProvider<TestSampleProvide
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
steps += TestDeviceRand.randInt(ts, -steps, 100 - steps) * dayActivityFactor;
|
steps += (int) (TestDeviceRand.randInt(ts, -steps, 100 - steps) * dayActivityFactor);
|
||||||
intensity += TestDeviceRand.randInt(ts, -1, 1);
|
intensity += TestDeviceRand.randInt(ts, -1, 1);
|
||||||
hr += TestDeviceRand.randInt(ts, -2, 2);
|
hr += TestDeviceRand.randInt(ts, -2, 2);
|
||||||
}
|
}
|
||||||
@ -250,5 +248,15 @@ public class TestSampleProvider extends AbstractSampleProvider<TestSampleProvide
|
|||||||
public int getSteps() {
|
public int getSteps() {
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDistanceCm() {
|
||||||
|
return steps * 67;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getActiveCalories() {
|
||||||
|
return (int) Math.round(steps * 0.04);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
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.entities;
|
package nodomain.freeyourgadget.gadgetbridge.entities;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||||
@ -29,7 +31,7 @@ public abstract class AbstractActivitySample implements ActivitySample {
|
|||||||
return mProvider;
|
return mProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProvider(SampleProvider provider) {
|
public void setProvider(SampleProvider<?> provider) {
|
||||||
mProvider = provider;
|
mProvider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +59,12 @@ public abstract class AbstractActivitySample implements ActivitySample {
|
|||||||
public void setSteps(int steps) {
|
public void setSteps(int steps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDistanceCm(int distance) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveCalories(int activeCalories) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unix timestamp of the sample, i.e. the number of seconds since 1970-01-01 00:00:00 UTC.
|
* Unix timestamp of the sample, i.e. the number of seconds since 1970-01-01 00:00:00 UTC.
|
||||||
*/
|
*/
|
||||||
@ -89,6 +97,17 @@ public abstract class AbstractActivitySample implements ActivitySample {
|
|||||||
return NOT_MEASURED;
|
return NOT_MEASURED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDistanceCm() {
|
||||||
|
return NOT_MEASURED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getActiveCalories() {
|
||||||
|
return NOT_MEASURED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
ActivityKind kind = getProvider() != null ? getKind() : ActivityKind.NOT_MEASURED;
|
ActivityKind kind = getProvider() != null ? getKind() : ActivityKind.NOT_MEASURED;
|
||||||
@ -97,7 +116,9 @@ public abstract class AbstractActivitySample implements ActivitySample {
|
|||||||
"timestamp=" + DateTimeUtils.formatDateTime(DateTimeUtils.parseTimeStamp(getTimestamp())) +
|
"timestamp=" + DateTimeUtils.formatDateTime(DateTimeUtils.parseTimeStamp(getTimestamp())) +
|
||||||
", intensity=" + intensity +
|
", intensity=" + intensity +
|
||||||
", steps=" + getSteps() +
|
", steps=" + getSteps() +
|
||||||
", heartrate=" + getHeartRate() +
|
", distanceCm=" + getDistanceCm() +
|
||||||
|
", activeCalories=" + getActiveCalories() +
|
||||||
|
", heartRate=" + getHeartRate() +
|
||||||
", type=" + kind +
|
", type=" + kind +
|
||||||
", userId=" + getUserId() +
|
", userId=" + getUserId() +
|
||||||
", deviceId=" + getDeviceId() +
|
", deviceId=" + getDeviceId() +
|
||||||
|
@ -23,6 +23,7 @@ public class ActivityAmount {
|
|||||||
private short percent;
|
private short percent;
|
||||||
private long totalSeconds;
|
private long totalSeconds;
|
||||||
private long totalSteps;
|
private long totalSteps;
|
||||||
|
private long totalDistance;
|
||||||
private Date startDate = null;
|
private Date startDate = null;
|
||||||
private Date endDate = null;
|
private Date endDate = null;
|
||||||
|
|
||||||
@ -38,6 +39,10 @@ public class ActivityAmount {
|
|||||||
totalSteps += steps;
|
totalSteps += steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDistance(long distance) {
|
||||||
|
totalDistance += distance;
|
||||||
|
}
|
||||||
|
|
||||||
public long getTotalSeconds() {
|
public long getTotalSeconds() {
|
||||||
return totalSeconds;
|
return totalSeconds;
|
||||||
}
|
}
|
||||||
@ -46,6 +51,10 @@ public class ActivityAmount {
|
|||||||
return totalSteps;
|
return totalSteps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getTotalDistance() {
|
||||||
|
return totalDistance;
|
||||||
|
}
|
||||||
|
|
||||||
public ActivityKind getActivityKind() {
|
public ActivityKind getActivityKind() {
|
||||||
return activityKind;
|
return activityKind;
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,16 @@ public interface ActivitySample extends TimeStamped {
|
|||||||
*/
|
*/
|
||||||
int getSteps();
|
int getSteps();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the distance moved during the period of this sample, in cm. -1 if unknown.
|
||||||
|
*/
|
||||||
|
int getDistanceCm();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the calories burned during the period of this sample, in kcal. -1 if unknown.
|
||||||
|
*/
|
||||||
|
int getActiveCalories();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the heart rate measured at the corresponding timestamp.
|
* Returns the heart rate measured at the corresponding timestamp.
|
||||||
* The value is returned in heart beats per minute, in the range from
|
* The value is returned in heart beats per minute, in the range from
|
||||||
|
@ -19,9 +19,12 @@ package nodomain.freeyourgadget.gadgetbridge.model;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -34,47 +37,46 @@ import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
|
||||||
|
|
||||||
public class DailyTotals {
|
public class DailyTotals implements Serializable {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DailyTotals.class);
|
private static final Logger LOG = LoggerFactory.getLogger(DailyTotals.class);
|
||||||
|
|
||||||
|
private final long steps;
|
||||||
|
private final long distance;
|
||||||
|
private final long[] sleep; // light deep rem awake
|
||||||
|
|
||||||
public long[] getDailyTotalsForAllDevices(Calendar day) {
|
public DailyTotals() {
|
||||||
Context context = GBApplication.getContext();
|
this(0, 0, new long[]{0, 0, 0 ,0});
|
||||||
//get today's steps for all devices in GB
|
|
||||||
long all_steps = 0;
|
|
||||||
long all_sleep = 0;
|
|
||||||
|
|
||||||
if (context instanceof GBApplication) {
|
|
||||||
GBApplication gbApp = (GBApplication) context;
|
|
||||||
List<? extends GBDevice> devices = gbApp.getDeviceManager().getDevices();
|
|
||||||
for (GBDevice device : devices) {
|
|
||||||
DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
|
||||||
if (!coordinator.supportsActivityDataFetching() && !coordinator.supportsActivityTracking()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
long[] all_daily = getDailyTotalsForDevice(device, day);
|
|
||||||
all_steps += all_daily[0];
|
|
||||||
all_sleep += all_daily[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//LOG.debug("gbwidget daily totals, all steps:" + all_steps);
|
|
||||||
//LOG.debug("gbwidget daily totals, all sleep:" + all_sleep);
|
|
||||||
return new long[]{all_steps, all_sleep};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DailyTotals(final long steps, final long distance, final long[] sleep) {
|
||||||
|
this.steps = steps;
|
||||||
|
this.distance = distance;
|
||||||
|
this.sleep = sleep;
|
||||||
|
}
|
||||||
|
|
||||||
public long[] getDailyTotalsForDevice(GBDevice device, Calendar day) {
|
public long getSteps() {
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDistance() {
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSleep() {
|
||||||
|
return (long) Arrays.stream(sleep).asDoubleStream().sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DailyTotals getDailyTotalsForDevice(GBDevice device, Calendar day) {
|
||||||
|
|
||||||
try (DBHandler handler = GBApplication.acquireDB()) {
|
try (DBHandler handler = GBApplication.acquireDB()) {
|
||||||
return getDailyTotalsForDevice(device, day, handler);
|
return getDailyTotalsForDevice(device, day, handler);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//GB.toast("Error loading sleep/steps widget data for device: " + device, Toast.LENGTH_SHORT, GB.ERROR, e);
|
//GB.toast("Error loading sleep/steps widget data for device: " + device, Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||||
return new long[]{0, 0};
|
return new DailyTotals();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long[] getDailyTotalsForDevice(GBDevice device, Calendar day, DBHandler handler) {
|
public static DailyTotals getDailyTotalsForDevice(GBDevice device, Calendar day, DBHandler handler) {
|
||||||
ActivityAnalysis analysis = new ActivityAnalysis();
|
ActivityAnalysis analysis = new ActivityAnalysis();
|
||||||
ActivityAmounts amountsSteps;
|
ActivityAmounts amountsSteps;
|
||||||
ActivityAmounts amountsSleep;
|
ActivityAmounts amountsSleep;
|
||||||
@ -83,13 +85,13 @@ public class DailyTotals {
|
|||||||
amountsSleep = analysis.calculateActivityAmounts(getSamplesOfDay(handler, day, -12, device));
|
amountsSleep = analysis.calculateActivityAmounts(getSamplesOfDay(handler, day, -12, device));
|
||||||
|
|
||||||
long[] sleep = getTotalsSleepForActivityAmounts(amountsSleep);
|
long[] sleep = getTotalsSleepForActivityAmounts(amountsSleep);
|
||||||
long steps = getTotalsStepsForActivityAmounts(amountsSteps);
|
Pair<Long, Long> stepsDistance = getTotalsStepsForActivityAmounts(amountsSteps);
|
||||||
|
|
||||||
// Purposely not including awake sleep
|
// Purposely not including awake sleep
|
||||||
return new long[]{steps, sleep[0] + sleep[1] + sleep[2]};
|
return new DailyTotals(stepsDistance.getLeft(), stepsDistance.getRight(), sleep);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long[] getTotalsSleepForActivityAmounts(ActivityAmounts activityAmounts) {
|
private static long[] getTotalsSleepForActivityAmounts(ActivityAmounts activityAmounts) {
|
||||||
long totalSecondsDeepSleep = 0;
|
long totalSecondsDeepSleep = 0;
|
||||||
long totalSecondsLightSleep = 0;
|
long totalSecondsLightSleep = 0;
|
||||||
long totalSecondsRemSleep = 0;
|
long totalSecondsRemSleep = 0;
|
||||||
@ -109,21 +111,21 @@ public class DailyTotals {
|
|||||||
long totalMinutesLightSleep = (totalSecondsLightSleep / 60);
|
long totalMinutesLightSleep = (totalSecondsLightSleep / 60);
|
||||||
long totalMinutesRemSleep = (totalSecondsRemSleep / 60);
|
long totalMinutesRemSleep = (totalSecondsRemSleep / 60);
|
||||||
long totalMinutesAwakeSleep = (totalSecondsAwakeSleep / 60);
|
long totalMinutesAwakeSleep = (totalSecondsAwakeSleep / 60);
|
||||||
return new long[]{totalMinutesDeepSleep, totalMinutesLightSleep, totalMinutesRemSleep, totalMinutesAwakeSleep};
|
return new long[]{totalMinutesLightSleep, totalMinutesDeepSleep, totalMinutesRemSleep, totalMinutesAwakeSleep};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Pair<Long, Long> getTotalsStepsForActivityAmounts(ActivityAmounts activityAmounts) {
|
||||||
public long getTotalsStepsForActivityAmounts(ActivityAmounts activityAmounts) {
|
|
||||||
long totalSteps = 0;
|
long totalSteps = 0;
|
||||||
|
long totalDistance = 0;
|
||||||
|
|
||||||
for (ActivityAmount amount : activityAmounts.getAmounts()) {
|
for (ActivityAmount amount : activityAmounts.getAmounts()) {
|
||||||
totalSteps += amount.getTotalSteps();
|
totalSteps += amount.getTotalSteps();
|
||||||
|
totalDistance += amount.getTotalDistance();
|
||||||
}
|
}
|
||||||
return totalSteps;
|
return Pair.of(totalSteps, totalDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<? extends ActivitySample> getSamplesOfDay(DBHandler db, Calendar day, int offsetHours, GBDevice device) {
|
||||||
private List<? extends ActivitySample> getSamplesOfDay(DBHandler db, Calendar day, int offsetHours, GBDevice device) {
|
|
||||||
int startTs;
|
int startTs;
|
||||||
int endTs;
|
int endTs;
|
||||||
|
|
||||||
@ -139,23 +141,21 @@ public class DailyTotals {
|
|||||||
return getSamples(db, device, startTs, endTs);
|
return getSamples(db, device, startTs, endTs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
||||||
public List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
|
||||||
return getAllSamples(db, device, tsFrom, tsTo);
|
return getAllSamples(db, device, tsFrom, tsTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static SampleProvider<? extends AbstractActivitySample> getProvider(DBHandler db, GBDevice device) {
|
||||||
protected SampleProvider<? extends AbstractActivitySample> getProvider(DBHandler db, GBDevice device) {
|
|
||||||
DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
DeviceCoordinator coordinator = device.getDeviceCoordinator();
|
||||||
return coordinator.getSampleProvider(device, db.getDaoSession());
|
return coordinator.getSampleProvider(device, db.getDaoSession());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<? extends ActivitySample> getAllSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
protected static List<? extends ActivitySample> getAllSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
|
||||||
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
|
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
|
||||||
return provider.getAllActivitySamples(tsFrom, tsTo);
|
return provider.getAllActivitySamples(tsFrom, tsTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActivitySample getFirstSample(DBHandler db, GBDevice device) {
|
public static ActivitySample getFirstSample(DBHandler db, GBDevice device) {
|
||||||
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
|
SampleProvider<? extends ActivitySample> provider = getProvider(db, device);
|
||||||
return provider.getFirstActivitySample();
|
return provider.getFirstActivitySample();
|
||||||
}
|
}
|
||||||
|
@ -42,11 +42,10 @@ import nodomain.freeyourgadget.gadgetbridge.model.DailyTotals;
|
|||||||
public class DashboardUtils {
|
public class DashboardUtils {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DashboardUtils.class);
|
private static final Logger LOG = LoggerFactory.getLogger(DashboardUtils.class);
|
||||||
|
|
||||||
public static long getSteps(GBDevice device, DBHandler db, int timeTo) {
|
public static DailyTotals getDailyTotals(GBDevice device, DBHandler db, int timeTo) {
|
||||||
Calendar day = GregorianCalendar.getInstance();
|
Calendar day = GregorianCalendar.getInstance();
|
||||||
day.setTimeInMillis(timeTo * 1000L);
|
day.setTimeInMillis(timeTo * 1000L);
|
||||||
DailyTotals ds = new DailyTotals();
|
return DailyTotals.getDailyTotalsForDevice(device, day, db);
|
||||||
return ds.getDailyTotalsForDevice(device, day, db)[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getStepsTotal(DashboardFragment.DashboardData dashboardData) {
|
public static int getStepsTotal(DashboardFragment.DashboardData dashboardData) {
|
||||||
@ -55,7 +54,7 @@ public class DashboardUtils {
|
|||||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
for (GBDevice dev : devices) {
|
for (GBDevice dev : devices) {
|
||||||
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
|
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||||
totalSteps += getSteps(dev, dbHandler, dashboardData.timeTo);
|
totalSteps += (int) getDailyTotals(dev, dbHandler, dashboardData.timeTo).getSteps();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -76,8 +75,7 @@ public class DashboardUtils {
|
|||||||
public static long getSleep(GBDevice device, DBHandler db, int timeTo) {
|
public static long getSleep(GBDevice device, DBHandler db, int timeTo) {
|
||||||
Calendar day = GregorianCalendar.getInstance();
|
Calendar day = GregorianCalendar.getInstance();
|
||||||
day.setTimeInMillis(timeTo * 1000L);
|
day.setTimeInMillis(timeTo * 1000L);
|
||||||
DailyTotals ds = new DailyTotals();
|
return DailyTotals.getDailyTotalsForDevice(device, day, db).getSleep();
|
||||||
return ds.getDailyTotalsForDevice(device, day, db)[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getSleepMinutesTotal(DashboardFragment.DashboardData dashboardData) {
|
public static long getSleepMinutesTotal(DashboardFragment.DashboardData dashboardData) {
|
||||||
@ -105,20 +103,26 @@ public class DashboardUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static float getDistanceTotal(DashboardFragment.DashboardData dashboardData) {
|
public static float getDistanceTotal(DashboardFragment.DashboardData dashboardData) {
|
||||||
|
ActivityUser activityUser = new ActivityUser();
|
||||||
|
int stepLength = activityUser.getStepLengthCm();
|
||||||
|
|
||||||
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
List<GBDevice> devices = GBApplication.app().getDeviceManager().getDevices();
|
||||||
long totalSteps = 0;
|
long totalDistanceCm = 0;
|
||||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
for (GBDevice dev : devices) {
|
for (GBDevice dev : devices) {
|
||||||
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
|
if ((dashboardData.showAllDevices || dashboardData.showDeviceList.contains(dev.getAddress())) && dev.getDeviceCoordinator().supportsActivityTracking()) {
|
||||||
totalSteps += getSteps(dev, dbHandler, dashboardData.timeTo);
|
final DailyTotals dailyTotals = getDailyTotals(dev, dbHandler, dashboardData.timeTo);
|
||||||
|
if (dailyTotals.getSteps() > 0 && dailyTotals.getDistance() > 0) {
|
||||||
|
totalDistanceCm += dailyTotals.getDistance();
|
||||||
|
} else {
|
||||||
|
totalDistanceCm += dailyTotals.getSteps() * stepLength;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.warn("Could not calculate total distance: ", e);
|
LOG.warn("Could not calculate total distance: ", e);
|
||||||
}
|
}
|
||||||
ActivityUser activityUser = new ActivityUser();
|
return totalDistanceCm * 0.01f;
|
||||||
int stepLength = activityUser.getStepLengthCm();
|
|
||||||
return totalSteps * stepLength * 0.01f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float getDistanceGoalFactor(DashboardFragment.DashboardData dashboardData) {
|
public static float getDistanceGoalFactor(DashboardFragment.DashboardData dashboardData) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user