mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-28 21:06:50 +01:00
Merge branch 'master' into feature-weather
This commit is contained in:
commit
16d9279728
@ -72,8 +72,6 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
||||
private TimestampTranslation tsTranslation;
|
||||
|
||||
private class Steps {
|
||||
private int initialSteps;
|
||||
|
||||
private int steps;
|
||||
private int lastTimestamp;
|
||||
private int currentStepsPerMinute;
|
||||
@ -90,39 +88,29 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
||||
}
|
||||
|
||||
public int getTotalSteps() {
|
||||
return steps - initialSteps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
public int getMaxStepsPerMinute() {
|
||||
return maxStepsPerMinute;
|
||||
}
|
||||
|
||||
public void updateCurrentSteps(int newSteps, int timestamp) {
|
||||
public void updateCurrentSteps(int stepsDelta, int timestamp) {
|
||||
try {
|
||||
if (steps == 0) {
|
||||
steps = newSteps;
|
||||
steps += stepsDelta;
|
||||
lastTimestamp = timestamp;
|
||||
|
||||
if (newSteps > 0) {
|
||||
initialSteps = newSteps;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (newSteps >= steps) {
|
||||
int stepsDelta = newSteps - steps;
|
||||
int timeDelta = timestamp - lastTimestamp;
|
||||
currentStepsPerMinute = calculateStepsPerMinute(stepsDelta, timeDelta);
|
||||
if (currentStepsPerMinute > maxStepsPerMinute) {
|
||||
maxStepsPerMinute = currentStepsPerMinute;
|
||||
maxStepsResetCounter = 0;
|
||||
}
|
||||
steps = newSteps;
|
||||
lastTimestamp = timestamp;
|
||||
} else {
|
||||
// TODO: handle new day?
|
||||
|
||||
int timeDelta = timestamp - lastTimestamp;
|
||||
currentStepsPerMinute = calculateStepsPerMinute(stepsDelta, timeDelta);
|
||||
if (currentStepsPerMinute > maxStepsPerMinute) {
|
||||
maxStepsPerMinute = currentStepsPerMinute;
|
||||
maxStepsResetCounter = 0;
|
||||
}
|
||||
steps += stepsDelta;
|
||||
lastTimestamp = timestamp;
|
||||
} catch (Exception ex) {
|
||||
GB.toast(LiveActivityFragment.this.getContext(), ex.getMessage(), Toast.LENGTH_SHORT, GB.ERROR, ex);
|
||||
}
|
||||
@ -136,7 +124,7 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
||||
throw new IllegalArgumentException("delta in seconds is <= 0 -- time change?");
|
||||
}
|
||||
|
||||
int oneMinute = 60 * 1000;
|
||||
int oneMinute = 60;
|
||||
float factor = oneMinute / seconds;
|
||||
int result = (int) (stepsDelta * factor);
|
||||
if (result > MAX_STEPS_PER_MINUTE) {
|
||||
@ -152,24 +140,27 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
switch (action) {
|
||||
case DeviceService.ACTION_REALTIME_STEPS: {
|
||||
int steps = intent.getIntExtra(DeviceService.EXTRA_REALTIME_STEPS, 0);
|
||||
int timestamp = translateTimestampFrom(intent);
|
||||
addEntries(steps, timestamp);
|
||||
break;
|
||||
}
|
||||
case DeviceService.ACTION_HEARTRATE_MEASUREMENT: {
|
||||
int heartRate = intent.getIntExtra(DeviceService.EXTRA_HEART_RATE_VALUE, 0);
|
||||
int timestamp = translateTimestampFrom(intent);
|
||||
if (isValidHeartRateValue(heartRate)) {
|
||||
setCurrentHeartRate(heartRate, timestamp);
|
||||
}
|
||||
case DeviceService.ACTION_REALTIME_SAMPLES: {
|
||||
ActivitySample sample = (ActivitySample) intent.getSerializableExtra(DeviceService.EXTRA_REALTIME_SAMPLE);
|
||||
addSample(sample);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void addSample(ActivitySample sample) {
|
||||
int heartRate = sample.getHeartRate();
|
||||
int timestamp = tsTranslation.shorten(sample.getTimestamp());
|
||||
if (isValidHeartRateValue(heartRate)) {
|
||||
setCurrentHeartRate(heartRate, timestamp);
|
||||
}
|
||||
int steps = sample.getSteps();
|
||||
if (steps != ActivitySample.NOT_MEASURED) {
|
||||
addEntries(steps, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
private int translateTimestampFrom(Intent intent) {
|
||||
return translateTimestamp(intent.getLongExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis()));
|
||||
}
|
||||
@ -251,8 +242,7 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
IntentFilter filterLocal = new IntentFilter();
|
||||
filterLocal.addAction(DeviceService.ACTION_REALTIME_STEPS);
|
||||
filterLocal.addAction(DeviceService.ACTION_HEARTRATE_MEASUREMENT);
|
||||
filterLocal.addAction(DeviceService.ACTION_REALTIME_SAMPLES);
|
||||
heartRateValues = new ArrayList<>();
|
||||
tsTranslation = new TimestampTranslation();
|
||||
|
||||
@ -377,6 +367,9 @@ public class LiveActivityFragment extends AbstractChartFragment {
|
||||
// chart.getXAxis().setPosition(XAxis.XAxisPosition.TOP);
|
||||
chart.getXAxis().setDrawLabels(false);
|
||||
chart.getXAxis().setEnabled(false);
|
||||
chart.getXAxis().setTextColor(CHART_TEXT_COLOR);
|
||||
chart.getAxisLeft().setTextColor(CHART_TEXT_COLOR);
|
||||
|
||||
chart.setBackgroundColor(BACKGROUND_COLOR);
|
||||
chart.getDescription().setTextColor(DESCRIPTION_COLOR);
|
||||
chart.getDescription().setText(title);
|
||||
|
@ -38,11 +38,6 @@ public interface DeviceService extends EventHandler {
|
||||
String ACTION_SET_ALARMS = PREFIX + ".action.set_alarms";
|
||||
String ACTION_ENABLE_REALTIME_STEPS = PREFIX + ".action.enable_realtime_steps";
|
||||
String ACTION_REALTIME_SAMPLES = PREFIX + ".action.realtime_samples";
|
||||
/**
|
||||
* Use EXTRA_REALTIME_SAMPLE instead
|
||||
*/
|
||||
@Deprecated
|
||||
String ACTION_REALTIME_STEPS = PREFIX + ".action.realtime_steps";
|
||||
String ACTION_ENABLE_REALTIME_HEARTRATE_MEASUREMENT = PREFIX + ".action.realtime_hr_measurement";
|
||||
String ACTION_ENABLE_HEARTRATE_SLEEP_SUPPORT = PREFIX + ".action.enable_heartrate_sleep_support";
|
||||
String ACTION_HEARTRATE_MEASUREMENT = PREFIX + ".action.hr_measurement";
|
||||
|
@ -950,30 +950,25 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
||||
MiBandSampleProvider provider = new MiBandSampleProvider(gbDevice, session);
|
||||
MiBandActivitySample sample = createActivitySample(device, user, ts, provider);
|
||||
sample.setHeartRate(getHeartrateBpm());
|
||||
sample.setSteps(getSteps());
|
||||
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||
sample.setRawKind(MiBandSampleProvider.TYPE_ACTIVITY); // to make it visible in the charts TODO: add a MANUAL kind for that?
|
||||
|
||||
// TODO: remove this once fully ported to REALTIME_SAMPLES
|
||||
if (sample.getSteps() != ActivitySample.NOT_MEASURED) {
|
||||
Intent intent = new Intent(DeviceService.ACTION_REALTIME_STEPS)
|
||||
.putExtra(DeviceService.EXTRA_REALTIME_STEPS, sample.getSteps())
|
||||
.putExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis());
|
||||
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
}
|
||||
if (sample.getHeartRate() != ActivitySample.NOT_MEASURED) {
|
||||
Intent intent = new Intent(DeviceService.ACTION_HEARTRATE_MEASUREMENT)
|
||||
.putExtra(DeviceService.EXTRA_HEART_RATE_VALUE, sample.getHeartRate())
|
||||
.putExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis());
|
||||
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
// Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES)
|
||||
// .putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample);
|
||||
// LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
|
||||
LOG.debug("Storing realtime sample: " + sample);
|
||||
provider.addGBActivitySample(sample);
|
||||
|
||||
// set the steps only afterwards, since realtime steps are also recorded
|
||||
// in the regular samples and we must not count them twice
|
||||
// Note: we know that the DAO sample is never committed again, so we simply
|
||||
// change the value here in memory.
|
||||
sample.setSteps(getSteps());
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("realtime sample: " + sample);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES)
|
||||
.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample);
|
||||
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Unable to acquire db for saving realtime samples", e);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ public abstract class RealtimeSamplesSupport {
|
||||
|
||||
protected int steps;
|
||||
protected int heartrateBpm;
|
||||
private int lastSteps;
|
||||
// subclasses may add more
|
||||
|
||||
private Timer realtimeStorageTimer;
|
||||
@ -56,12 +57,27 @@ public abstract class RealtimeSamplesSupport {
|
||||
return realtimeStorageTimer != null;
|
||||
}
|
||||
|
||||
public void setSteps(int stepsPerMinute) {
|
||||
public synchronized void setSteps(int stepsPerMinute) {
|
||||
this.steps = stepsPerMinute;
|
||||
}
|
||||
|
||||
public int getSteps() {
|
||||
return steps;
|
||||
/**
|
||||
* Returns the number of steps recorded since the last measurements. If no
|
||||
* steps are available yet, ActivitySample.NOT_MEASURED is returned.
|
||||
* @return
|
||||
*/
|
||||
public synchronized int getSteps() {
|
||||
if (steps == ActivitySample.NOT_MEASURED) {
|
||||
return ActivitySample.NOT_MEASURED;
|
||||
}
|
||||
if (lastSteps == 0) {
|
||||
return ActivitySample.NOT_MEASURED; // wait until we have a delta between two samples
|
||||
}
|
||||
int delta = steps - lastSteps;
|
||||
if (delta < 0) {
|
||||
return 0;
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
public void setHeartrateBpm(int hrBpm) {
|
||||
@ -77,7 +93,10 @@ public abstract class RealtimeSamplesSupport {
|
||||
resetCurrentValues();
|
||||
}
|
||||
|
||||
protected void resetCurrentValues() {
|
||||
protected synchronized void resetCurrentValues() {
|
||||
if (steps >= lastSteps) {
|
||||
lastSteps = steps;
|
||||
}
|
||||
steps = ActivitySample.NOT_MEASURED;
|
||||
heartrateBpm = ActivitySample.NOT_MEASURED;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ public class FetchActivityOperation extends AbstractMiBand1Operation {
|
||||
private final boolean hasExtendedActivityData;
|
||||
|
||||
private static class ActivityStruct {
|
||||
private int lastNotifiedProgress;
|
||||
private final byte[] activityDataHolder;
|
||||
private final int activityDataHolderSize;
|
||||
//index of the buffer above
|
||||
@ -129,6 +130,7 @@ public class FetchActivityOperation extends AbstractMiBand1Operation {
|
||||
public void bufferFlushed(int minutes) {
|
||||
activityDataTimestampProgress.add(Calendar.MINUTE, minutes);
|
||||
activityDataHolderProgress = 0;
|
||||
lastNotifiedProgress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,9 +201,16 @@ public class FetchActivityOperation extends AbstractMiBand1Operation {
|
||||
} else {
|
||||
bufferActivityData(value);
|
||||
}
|
||||
LOG.debug("activity data: length: " + value.length + ", remaining bytes: " + activityStruct.activityDataRemainingBytes);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("activity data: length: " + value.length + ", remaining bytes: " + activityStruct.activityDataRemainingBytes);
|
||||
}
|
||||
|
||||
GB.updateTransferNotification(getContext().getString(R.string.busy_task_fetch_activity_data), true, (int) (((float) (activityStruct.activityDataUntilNextHeader - activityStruct.activityDataRemainingBytes)) / activityStruct.activityDataUntilNextHeader * 100), getContext());
|
||||
int progress = (int) (((float) (activityStruct.activityDataUntilNextHeader - activityStruct.activityDataRemainingBytes)) / activityStruct.activityDataUntilNextHeader * 100);
|
||||
// avoid too many notifications overloading the system
|
||||
if (progress - activityStruct.lastNotifiedProgress >= 8) {
|
||||
activityStruct.lastNotifiedProgress = progress;
|
||||
GB.updateTransferNotification(getContext().getString(R.string.busy_task_fetch_activity_data), true, progress, getContext());
|
||||
}
|
||||
|
||||
if (activityStruct.isBlockFinished()) {
|
||||
sendAckDataTransfer(activityStruct.activityDataTimestampToAck, activityStruct.activityDataUntilNextHeader);
|
||||
|
@ -70,7 +70,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.Dev
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.heartrate.HeartRateProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.CheckAuthenticationNeededAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.DeviceInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBandSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.RealtimeSamplesSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.FetchActivityOperation;
|
||||
@ -983,26 +982,22 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
|
||||
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||
sample.setRawKind(MiBand2SampleProvider.TYPE_ACTIVITY); // to make it visible in the charts TODO: add a MANUAL kind for that?
|
||||
|
||||
// TODO: remove this once fully ported to REALTIME_SAMPLES
|
||||
if (sample.getSteps() != ActivitySample.NOT_MEASURED) {
|
||||
Intent intent = new Intent(DeviceService.ACTION_REALTIME_STEPS)
|
||||
.putExtra(DeviceService.EXTRA_REALTIME_STEPS, sample.getSteps())
|
||||
.putExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis());
|
||||
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
}
|
||||
if (sample.getHeartRate() != ActivitySample.NOT_MEASURED) {
|
||||
Intent intent = new Intent(DeviceService.ACTION_HEARTRATE_MEASUREMENT)
|
||||
.putExtra(DeviceService.EXTRA_HEART_RATE_VALUE, sample.getHeartRate())
|
||||
.putExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis());
|
||||
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
// Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES)
|
||||
// .putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample);
|
||||
// LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
|
||||
LOG.debug("Storing realtime sample: " + sample);
|
||||
provider.addGBActivitySample(sample);
|
||||
|
||||
// set the steps only afterwards, since realtime steps are also recorded
|
||||
// in the regular samples and we must not count them twice
|
||||
// Note: we know that the DAO sample is never committed again, so we simply
|
||||
// change the value here in memory.
|
||||
sample.setSteps(getSteps());
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("realtime sample: " + sample);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(DeviceService.ACTION_REALTIME_SAMPLES)
|
||||
.putExtra(DeviceService.EXTRA_REALTIME_SAMPLE, sample);
|
||||
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Unable to acquire db for saving realtime samples", e);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user