From 858c962dd074ae95de1e422de9f4fc58fe85045b Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 27 Jul 2015 23:49:53 +0200 Subject: [PATCH] Refactoring #45 - add some device and db independent model interfaces for activity samples - use these model interfaces where possible - chart activity does not do device dependent rendering anymore and uses normalized values for all devices - initial interface for daily summaries --- .../gadgetbridge/DeviceCoordinator.java | 3 + .../gadgetbridge/GBActivitySample.java | 53 ++++----- .../UnknownDeviceCoordinator.java | 35 ++++++ .../activities/AbstractChartFragment.java | 110 +++++++----------- .../ActivitySleepChartFragment.java | 8 +- .../activities/SleepChartFragment.java | 10 +- .../gadgetbridge/charts/ActivityAnalysis.java | 18 +-- .../gadgetbridge/charts/ActivityKind.java | 10 +- .../gadgetbridge/charts/SleepUtils.java | 2 +- .../database/ActivityDatabaseHandler.java | 58 +++++---- .../gadgetbridge/database/GBSummaryOfDay.java | 28 +++++ .../database/UsedConfiguration.java | 16 +++ .../miband/MiBandCoordinator.java | 11 ++ .../miband/MiBandSampleProvider.java | 64 ++++++++++ .../gadgetbridge/miband/MiBandSupport.java | 4 +- .../gadgetbridge/model/ActivitySample.java | 42 +++++++ .../gadgetbridge/model/SampleProvider.java | 16 +++ .../gadgetbridge/model/SummaryOfDay.java | 12 ++ .../pebble/GadgetbridgePblSupport.java | 3 +- .../pebble/MorpheuzSampleProvider.java | 54 +++++++++ .../gadgetbridge/pebble/MorpheuzSupport.java | 9 +- .../pebble/PebbleCoordinator.java | 13 +++ .../PebbleGadgetBridgeSampleProvider.java | 7 ++ 23 files changed, 433 insertions(+), 153 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/GBSummaryOfDay.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/UsedConfiguration.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSampleProvider.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySample.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SampleProvider.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SummaryOfDay.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSampleProvider.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleGadgetBridgeSampleProvider.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/DeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/DeviceCoordinator.java index ac4a693f5..3e2e23c38 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/DeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/DeviceCoordinator.java @@ -3,6 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge; import android.app.Activity; import nodomain.freeyourgadget.gadgetbridge.discovery.DeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public interface DeviceCoordinator { String EXTRA_DEVICE_MAC_ADDRESS = "nodomain.freeyourgadget.gadgetbridge.discovery.DeviceCandidate.EXTRA_MAC_ADDRESS"; @@ -16,4 +17,6 @@ public interface DeviceCoordinator { Class getPairingActivity(); Class getPrimaryActivity(); + + SampleProvider getSampleProvider(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBActivitySample.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBActivitySample.java index 18b8b9d44..9a965a5be 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBActivitySample.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBActivitySample.java @@ -1,32 +1,16 @@ package nodomain.freeyourgadget.gadgetbridge; -public class GBActivitySample { - public static final byte PROVIDER_MIBAND = 0; - public static final byte PROVIDER_PEBBLE_MORPHEUZ = 1; - public static final byte PROVIDER_PEBBLE_GADGETBRIDGE = 2; - -// public static final byte TYPE_CHARGING = 6; -// public static final byte TYPE_NONWEAR = 3; -// public static final byte TYPE_NREM = 5; // DEEP SLEEP -// public static final byte TYPE_ONBED = 7; -// public static final byte TYPE_REM = 4; // LIGHT SLEEP -// public static final byte TYPE_RUNNING = 2; -// public static final byte TYPE_SLIENT = 0; -// public static final byte TYPE_USER = 100; -// public static final byte TYPE_WALKING = 1; - - public static final byte TYPE_DEEP_SLEEP = 5; - public static final byte TYPE_LIGHT_SLEEP = 4; - public static final byte TYPE_UNKNOWN = -1; - // add more here +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; +public class GBActivitySample implements ActivitySample { private final int timestamp; - private final byte provider; + private final SampleProvider provider; private final short intensity; - private final byte steps; + private final short steps; private final byte type; - public GBActivitySample(int timestamp, byte provider, short intensity, byte steps, byte type) { + public GBActivitySample(SampleProvider provider, int timestamp, short intensity, short steps, byte type) { this.timestamp = timestamp; this.provider = provider; this.intensity = intensity; @@ -34,27 +18,38 @@ public class GBActivitySample { this.type = type; } - /** - * Timestamp of the sample, resolution is seconds! - */ + @Override public int getTimestamp() { return timestamp; } - public byte getProvider() { + @Override + public SampleProvider getProvider() { return provider; } - public short getIntensity() { + @Override + public short getRawIntensity() { return intensity; } - public byte getSteps() { + @Override + public float getIntensity() { + return getProvider().normalizeIntensity(getRawIntensity()); + } + + @Override + public short getSteps() { return steps; } - public byte getType() { + @Override + public byte getRawKind() { return type; } + @Override + public int getKind() { + return getProvider().normalizeType(getRawKind()); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/UnknownDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/UnknownDeviceCoordinator.java index e06982f49..e26689feb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/UnknownDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/UnknownDeviceCoordinator.java @@ -2,9 +2,39 @@ package nodomain.freeyourgadget.gadgetbridge; import android.app.Activity; +import nodomain.freeyourgadget.gadgetbridge.charts.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.discovery.DeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public class UnknownDeviceCoordinator implements DeviceCoordinator { + private final UnknownSampleProvider sampleProvider; + + private static final class UnknownSampleProvider implements SampleProvider { + @Override + public int normalizeType(byte rawType) { + return ActivityKind.TYPE_UNKNOWN; + } + + @Override + public byte toRawActivityKind(int activityKind) { + return 0; + } + + @Override + public float normalizeIntensity(short rawIntensity) { + return 0; + } + + @Override + public byte getID() { + return SampleProvider.PROVIDER_UNKNOWN; + } + } + + public UnknownDeviceCoordinator() { + sampleProvider = new UnknownSampleProvider(); + } + @Override public boolean supports(DeviceCandidate candidate) { return false; @@ -29,4 +59,9 @@ public class UnknownDeviceCoordinator implements DeviceCoordinator { public Class getPrimaryActivity() { return null; } + + @Override + public SampleProvider getSampleProvider() { + return sampleProvider; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractChartFragment.java index 6ded621d0..b96ae41a5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/AbstractChartFragment.java @@ -20,11 +20,16 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.List; +import nodomain.freeyourgadget.gadgetbridge.DeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBDevice; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.charts.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.charts.SleepUtils; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public abstract class AbstractChartFragment extends Fragment { private static final Logger LOG = LoggerFactory.getLogger(ActivitySleepChartFragment.class); @@ -33,21 +38,21 @@ public abstract class AbstractChartFragment extends Fragment { = "nodomain.freeyourgadget.gadgetbridge.chart.action.refresh"; - protected static final class ActivityKind { - public final byte type; + protected static final class ActivityConfig { + public final int type; public final String label; public final Integer color; - public ActivityKind(byte type, String label, Integer color) { - this.type = type; + public ActivityConfig(int kind, String label, Integer color) { + this.type = kind; this.label = label; this.color = color; } } - protected ActivityKind akActivity = new ActivityKind(GBActivitySample.TYPE_UNKNOWN, "Activity", Color.rgb(89, 178, 44)); - protected ActivityKind akLightSleep = new ActivityKind(GBActivitySample.TYPE_LIGHT_SLEEP, "Light Sleep", Color.rgb(182, 191, 255)); - protected ActivityKind akDeepSleep = new ActivityKind(GBActivitySample.TYPE_DEEP_SLEEP, "Deep Sleep", Color.rgb(76, 90, 255)); + protected ActivityConfig akActivity = new ActivityConfig(ActivityKind.TYPE_ACTIVITY, "Activity", Color.rgb(89, 178, 44)); + protected ActivityConfig akLightSleep = new ActivityConfig(ActivityKind.TYPE_LIGHT_SLEEP, "Light Sleep", Color.rgb(182, 191, 255)); + protected ActivityConfig akDeepSleep = new ActivityConfig(ActivityKind.TYPE_DEEP_SLEEP, "Deep Sleep", Color.rgb(76, 90, 255)); protected static final int BACKGROUND_COLOR = Color.rgb(24, 22, 24); protected static final int DESCRIPTION_COLOR = Color.WHITE; @@ -66,25 +71,16 @@ public abstract class AbstractChartFragment extends Fragment { return akActivity.color; } - protected byte getProvider(GBDevice device) { - byte provider = -1; - switch (device.getType()) { - case MIBAND: - provider = GBActivitySample.PROVIDER_MIBAND; - break; - case PEBBLE: - provider = GBActivitySample.PROVIDER_PEBBLE_MORPHEUZ; // FIXME - //provider = GBActivitySample.PROVIDER_PEBBLE_GADGETBRIDGE; - break; - } - return provider; + protected SampleProvider getProvider(GBDevice device) { + DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device); + return coordinator.getSampleProvider(); } - protected List getAllSamples(GBDevice device, int tsFrom, int tsTo) { + protected List getAllSamples(GBDevice device, int tsFrom, int tsTo) { if (tsFrom == -1) { tsFrom = getTSLast24Hours(); } - byte provider = getProvider(device); + SampleProvider provider = getProvider(device); return GBApplication.getActivityDatabaseHandler().getAllActivitySamples(tsFrom, tsTo, provider); } @@ -93,24 +89,24 @@ public abstract class AbstractChartFragment extends Fragment { return (int) ((now / 1000) - (24 * 60 * 60) & 0xffffffff); // -24 hours } - protected List getActivitySamples(GBDevice device, int tsFrom, int tsTo) { + protected List getActivitySamples(GBDevice device, int tsFrom, int tsTo) { if (tsFrom == -1) { tsFrom = getTSLast24Hours(); } - byte provider = getProvider(device); + SampleProvider provider = getProvider(device); return GBApplication.getActivityDatabaseHandler().getActivitySamples(tsFrom, tsTo, provider); } - protected List getSleepSamples(GBDevice device, int tsFrom, int tsTo) { + protected List getSleepSamples(GBDevice device, int tsFrom, int tsTo) { if (tsFrom == -1) { tsFrom = getTSLast24Hours(); } - byte provider = getProvider(device); + SampleProvider provider = getProvider(device); return GBApplication.getActivityDatabaseHandler().getSleepSamples(tsFrom, tsTo, provider); } - protected List getTestSamples(GBDevice device, int tsFrom, int tsTo) { + protected List getTestSamples(GBDevice device, int tsFrom, int tsTo) { Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(2015, Calendar.JUNE, 10, 6, 40); @@ -118,7 +114,7 @@ public abstract class AbstractChartFragment extends Fragment { tsTo = (int) ((cal.getTimeInMillis() / 1000) & 0xffffffff); tsFrom = tsTo - (24 * 60 * 60); - byte provider = getProvider(device); + SampleProvider provider = getProvider(device); return GBApplication.getActivityDatabaseHandler().getAllActivitySamples(tsFrom, tsTo, provider); } @@ -146,7 +142,7 @@ public abstract class AbstractChartFragment extends Fragment { chart.setDrawGridBackground(false); } - protected void refresh(GBDevice gbDevice, BarLineChartBase chart, List samples) { + protected void refresh(GBDevice gbDevice, BarLineChartBase chart, List samples) { if (gbDevice == null) { return; } @@ -162,37 +158,21 @@ public abstract class AbstractChartFragment extends Fragment { float movement_divisor; boolean annotate = true; boolean use_steps_as_movement; - switch (getProvider(gbDevice)) { - case GBActivitySample.PROVIDER_MIBAND: - // maybe this should be configurable 256 seems way off, though. - movement_divisor = 180.0f; //256.0f; - use_steps_as_movement = true; - break; - case GBActivitySample.PROVIDER_PEBBLE_GADGETBRIDGE: - movement_divisor = 63.0f; - use_steps_as_movement = false; - break; - default: // Morpheuz - movement_divisor = 5000.0f; - use_steps_as_movement = false; - break; - } + SampleProvider provider = getProvider(gbDevice); - byte last_type = GBActivitySample.TYPE_UNKNOWN; + int last_type = ActivityKind.TYPE_UNKNOWN; SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm"); SimpleDateFormat annotationDateFormat = new SimpleDateFormat("HH:mm"); int numEntries = samples.size(); List xLabels = new ArrayList<>(numEntries); -// List deepSleepEntries = new ArrayList<>(numEntries / 4); -// List lightSleepEntries = new ArrayList<>(numEntries / 4); List activityEntries = new ArrayList<>(numEntries); List colors = new ArrayList<>(numEntries); // this is kinda inefficient... for (int i = 0; i < numEntries; i++) { - GBActivitySample sample = samples.get(i); - byte type = sample.getType(); + ActivitySample sample = samples.get(i); + int type = sample.getKind(); // determine start and end dates if (i == 0) { @@ -205,29 +185,24 @@ public abstract class AbstractChartFragment extends Fragment { dateStringTo = dateFormat.format(date); } - short movement = sample.getIntensity(); + float movement = sample.getIntensity(); - float value; - if (type == GBActivitySample.TYPE_DEEP_SLEEP) { -// value = Y_VALUE_DEEP_SLEEP; - value = ((float) movement) / movement_divisor; + float value = movement; + if (type == ActivityKind.TYPE_DEEP_SLEEP) { value += SleepUtils.Y_VALUE_DEEP_SLEEP; activityEntries.add(createBarEntry(value, i)); colors.add(akDeepSleep.color); } else { - if (type == GBActivitySample.TYPE_LIGHT_SLEEP) { - value = ((float) movement) / movement_divisor; -// value += SleepUtils.Y_VALUE_LIGHT_SLEEP; -// value = Math.min(1.0f, Y_VALUE_LIGHT_SLEEP); + if (type == ActivityKind.TYPE_LIGHT_SLEEP) { activityEntries.add(createBarEntry(value, i)); colors.add(akLightSleep.color); } else { - byte steps = sample.getSteps(); - if (use_steps_as_movement && steps != 0) { - // I'm not sure using steps for this is actually a good idea - movement = steps; - } - value = ((float) movement) / movement_divisor; +// short steps = sample.getSteps(); +// if (use_steps_as_movement && steps != 0) { +// // I'm not sure using steps for this is actually a good idea +// movement = steps; +// } +// value = ((float) movement) / movement_divisor; activityEntries.add(createBarEntry(value, i)); colors.add(akActivity.color); } @@ -263,13 +238,9 @@ public abstract class AbstractChartFragment extends Fragment { chart.getXAxis().setValues(xLabels); -// BarDataSet deepSleepSet = createDeepSleepSet(deepSleepEntries, "Deep Sleep"); -// BarDataSet lightSleepSet = createLightSleepSet(lightSleepEntries, "Light Sleep"); BarDataSet activitySet = createActivitySet(activityEntries, colors, "Activity"); ArrayList dataSets = new ArrayList<>(); -// dataSets.add(deepSleepSet); -// dataSets.add(lightSleepSet); dataSets.add(activitySet); // create a data object with the datasets @@ -278,19 +249,16 @@ public abstract class AbstractChartFragment extends Fragment { chart.setDescription(getString(R.string.sleep_activity_date_range, dateStringFrom, dateStringTo)); // chart.setDescriptionPosition(?, ?); - // set data setupLegend(chart); chart.setData(data); chart.animateX(500, Easing.EasingOption.EaseInOutQuart); - -// textView.setText(dateStringFrom + " to " + dateStringTo); } } - protected abstract List getSamples(GBDevice device, int tsFrom, int tsTo); + protected abstract List getSamples(GBDevice device, int tsFrom, int tsTo); protected abstract void setupLegend(Chart chart); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySleepChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySleepChartFragment.java index 8e4bb121b..bed2d0b2a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySleepChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySleepChartFragment.java @@ -22,9 +22,9 @@ import java.util.ArrayList; import java.util.List; import nodomain.freeyourgadget.gadgetbridge.ControlCenter; -import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.GBDevice; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; public class ActivitySleepChartFragment extends AbstractChartFragment { @@ -48,7 +48,7 @@ public class ActivitySleepChartFragment extends AbstractChartFragment { mSmartAlarmTo = intent.getIntExtra("smartalarm_to", -1); mTimestampFrom = intent.getIntExtra("recording_base_timestamp", -1); mSmartAlarmGoneOff = intent.getIntExtra("alarm_gone_off", -1); - List samples = getSamples(mGBDevice, -1, -1); + List samples = getSamples(mGBDevice, -1, -1); refresh(mGBDevice, mChart, samples); } } @@ -108,7 +108,7 @@ public class ActivitySleepChartFragment extends AbstractChartFragment { yAxisRight.setDrawTopYLabelEntry(false); yAxisRight.setTextColor(CHART_TEXT_COLOR); - List samples = getSamples(mGBDevice, -1, -1); + List samples = getSamples(mGBDevice, -1, -1); refresh(mGBDevice, mChart, samples); mChart.getLegend().setTextColor(LEGEND_TEXT_COLOR); @@ -140,7 +140,7 @@ public class ActivitySleepChartFragment extends AbstractChartFragment { } @Override - protected List getSamples(GBDevice device, int tsFrom, int tsTo) { + protected List getSamples(GBDevice device, int tsFrom, int tsTo) { return getAllSamples(device, tsFrom, tsTo); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SleepChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SleepChartFragment.java index d2a01b808..63f6ddba6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SleepChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SleepChartFragment.java @@ -29,12 +29,12 @@ import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.ControlCenter; import nodomain.freeyourgadget.gadgetbridge.GB; -import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.GBDevice; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.charts.ActivityAmount; import nodomain.freeyourgadget.gadgetbridge.charts.ActivityAmounts; import nodomain.freeyourgadget.gadgetbridge.charts.ActivityAnalysis; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; public class SleepChartFragment extends AbstractChartFragment { @@ -65,7 +65,7 @@ public class SleepChartFragment extends AbstractChartFragment { }; private void refresh() { - List samples = getSamples(); + List samples = getSamples(); refresh(mGBDevice, mActivityChart, getSamples()); refreshSleepAmounts(mGBDevice, mSleepAmountChart, samples); @@ -73,11 +73,11 @@ public class SleepChartFragment extends AbstractChartFragment { mSleepAmountChart.invalidate(); } - private List getSamples() { + private List getSamples() { return getSamples(mGBDevice, -1, -1); } - private void refreshSleepAmounts(GBDevice mGBDevice, PieChart pieChart, List samples) { + private void refreshSleepAmounts(GBDevice mGBDevice, PieChart pieChart, List samples) { ActivityAnalysis analysis = new ActivityAnalysis(); ActivityAmounts amounts = analysis.calculateActivityAmounts(samples); String totalSleep = GB.formatDurationHoursMinutes(amounts.getTotalSeconds(), TimeUnit.SECONDS); @@ -202,7 +202,7 @@ public class SleepChartFragment extends AbstractChartFragment { } @Override - protected List getSamples(GBDevice device, int tsFrom, int tsTo) { + protected List getSamples(GBDevice device, int tsFrom, int tsTo) { return super.getSleepSamples(device, tsFrom, tsTo); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityAnalysis.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityAnalysis.java index dbc8a7e9f..0a12237ca 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityAnalysis.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityAnalysis.java @@ -2,26 +2,26 @@ package nodomain.freeyourgadget.gadgetbridge.charts; import java.util.List; -import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; public class ActivityAnalysis { - public ActivityAmounts calculateActivityAmounts(List samples) { + public ActivityAmounts calculateActivityAmounts(List samples) { ActivityAmount deepSleep = new ActivityAmount(ActivityKind.TYPE_DEEP_SLEEP); ActivityAmount lightSleep = new ActivityAmount(ActivityKind.TYPE_LIGHT_SLEEP); ActivityAmount activity = new ActivityAmount(ActivityKind.TYPE_ACTIVITY); ActivityAmount previousAmount = null; - GBActivitySample previousSample = null; - for (GBActivitySample sample : samples) { + ActivitySample previousSample = null; + for (ActivitySample sample : samples) { ActivityAmount amount = null; - switch (sample.getType()) { - case GBActivitySample.TYPE_DEEP_SLEEP: + switch (sample.getKind()) { + case ActivityKind.TYPE_DEEP_SLEEP: amount = deepSleep; break; - case GBActivitySample.TYPE_LIGHT_SLEEP: + case ActivityKind.TYPE_LIGHT_SLEEP: amount = lightSleep; break; - case GBActivitySample.TYPE_UNKNOWN: + case ActivityKind.TYPE_ACTIVITY: default: amount = activity; break; @@ -29,7 +29,7 @@ public class ActivityAnalysis { if (previousSample != null) { long timeDifference = sample.getTimestamp() - previousSample.getTimestamp(); - if (previousSample.getType() == sample.getType()) { + if (previousSample.getRawKind() == sample.getRawKind()) { amount.addSeconds(timeDifference); } else { long sharedTimeDifference = (long) (timeDifference / 2.0f); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityKind.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityKind.java index 6f9a8a06b..789ff6109 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityKind.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/ActivityKind.java @@ -3,25 +3,27 @@ package nodomain.freeyourgadget.gadgetbridge.charts; import java.util.Arrays; import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public class ActivityKind { + public static final int TYPE_UNKNOWN = 0; public static final int TYPE_ACTIVITY = 1; public static final int TYPE_LIGHT_SLEEP = 2; public static final int TYPE_DEEP_SLEEP = 4; public static final int TYPE_SLEEP = TYPE_LIGHT_SLEEP | TYPE_DEEP_SLEEP; public static final int TYPE_ALL = TYPE_ACTIVITY | TYPE_SLEEP; - public static byte[] mapToDBActivityTypes(int types) { + public static byte[] mapToDBActivityTypes(int types, SampleProvider provider) { byte[] result = new byte[3]; int i = 0; if ((types & ActivityKind.TYPE_ACTIVITY) != 0) { - result[i++] = GBActivitySample.TYPE_UNKNOWN; + result[i++] = provider.toRawActivityKind(TYPE_ACTIVITY); } if ((types & ActivityKind.TYPE_DEEP_SLEEP) != 0) { - result[i++] = GBActivitySample.TYPE_DEEP_SLEEP; + result[i++] = provider.toRawActivityKind(TYPE_DEEP_SLEEP); } if ((types & ActivityKind.TYPE_LIGHT_SLEEP) != 0) { - result[i++] = GBActivitySample.TYPE_LIGHT_SLEEP; + result[i++] = provider.toRawActivityKind(TYPE_LIGHT_SLEEP); } return Arrays.copyOf(result, i); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/SleepUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/SleepUtils.java index 7860dd274..7ba331f52 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/SleepUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/charts/SleepUtils.java @@ -7,6 +7,6 @@ public class SleepUtils { public static final float Y_VALUE_LIGHT_SLEEP = 0.016f; public static final boolean isSleep(byte type) { - return type == GBActivitySample.TYPE_DEEP_SLEEP || type == GBActivitySample.TYPE_LIGHT_SLEEP; + return type == ActivityKind.TYPE_DEEP_SLEEP || type == ActivityKind.TYPE_LIGHT_SLEEP; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java index a7f0283c2..7701df299 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java @@ -16,6 +16,8 @@ import nodomain.freeyourgadget.gadgetbridge.GB; import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.charts.ActivityKind; import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.DATABASE_NAME; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_INTENSITY; @@ -90,41 +92,49 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper { } } - public void addGBActivitySample(GBActivitySample GBActivitySample) { + public void addGBActivitySample(ActivitySample sample) { try (SQLiteDatabase db = this.getWritableDatabase()) { ContentValues values = new ContentValues(); - values.put(KEY_TIMESTAMP, GBActivitySample.getTimestamp()); - values.put(KEY_PROVIDER, GBActivitySample.getProvider()); - values.put(KEY_INTENSITY, GBActivitySample.getIntensity()); - values.put(KEY_STEPS, GBActivitySample.getSteps()); - values.put(KEY_TYPE, GBActivitySample.getType()); + values.put(KEY_TIMESTAMP, sample.getTimestamp()); + values.put(KEY_PROVIDER, sample.getProvider().getID()); + values.put(KEY_INTENSITY, sample.getRawIntensity()); + values.put(KEY_STEPS, sample.getSteps()); + values.put(KEY_TYPE, sample.getRawKind()); db.insert(TABLE_GBACTIVITYSAMPLES, null, values); } } - public void addGBActivitySample(int timestamp, byte provider, short intensity, byte steps, byte type) { + /** + * Adds the a new sample to the database + * @param timestamp the timestamp of the same, second-based! + * @param provider the SampleProvider ID + * @param intensity the sample's raw intensity value + * @param steps the sample's steps value + * @param kind the raw activity kind of the sample + */ + public void addGBActivitySample(int timestamp, byte provider, short intensity, byte steps, byte kind) { try (SQLiteDatabase db = this.getWritableDatabase()) { ContentValues values = new ContentValues(); values.put(KEY_TIMESTAMP, timestamp); values.put(KEY_PROVIDER, provider); values.put(KEY_INTENSITY, intensity); values.put(KEY_STEPS, steps); - values.put(KEY_TYPE, type); + values.put(KEY_TYPE, kind); db.insert(TABLE_GBACTIVITYSAMPLES, null, values); } } - public ArrayList getSleepSamples(int timestamp_from, int timestamp_to, byte provider) { + public ArrayList getSleepSamples(int timestamp_from, int timestamp_to, SampleProvider provider) { return getGBActivitySamples(timestamp_from, timestamp_to, ActivityKind.TYPE_SLEEP, provider); } - public ArrayList getActivitySamples(int timestamp_from, int timestamp_to, byte provider) { + public ArrayList getActivitySamples(int timestamp_from, int timestamp_to, SampleProvider provider) { return getGBActivitySamples(timestamp_from, timestamp_to, ActivityKind.TYPE_ACTIVITY, provider); } - public ArrayList getAllActivitySamples(int timestamp_from, int timestamp_to, byte provider) { + public ArrayList getAllActivitySamples(int timestamp_from, int timestamp_to, SampleProvider provider) { return getGBActivitySamples(timestamp_from, timestamp_to, ActivityKind.TYPE_ALL, provider); } @@ -135,42 +145,42 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper { * @param timestamp_from * @param timestamp_to * @param activityTypes ORed combination of #TYPE_DEEP_SLEEP, #TYPE_LIGHT_SLEEP, #TYPE_ACTIVITY - * @param provider + * @param provider the producer of the samples to be sought * @return */ - private ArrayList getGBActivitySamples(int timestamp_from, int timestamp_to, int activityTypes, byte provider) { + private ArrayList getGBActivitySamples(int timestamp_from, int timestamp_to, int activityTypes, SampleProvider provider) { if (timestamp_to == -1) { timestamp_to = Integer.MAX_VALUE; // dont know what happens when I use more than max of a signed int } - ArrayList GBActivitySampleList = new ArrayList(); - final String where = "(provider=" + provider + " and timestamp>=" + timestamp_from + " and timestamp<=" + timestamp_to + getWhereClauseFor(activityTypes) + ")"; + ArrayList samples = new ArrayList(); + final String where = "(provider=" + provider.getID() + " and timestamp>=" + timestamp_from + " and timestamp<=" + timestamp_to + getWhereClauseFor(activityTypes, provider) + ")"; final String order = "timestamp"; try (SQLiteDatabase db = this.getReadableDatabase()) { Cursor cursor = db.query(TABLE_GBACTIVITYSAMPLES, null, where, null, null, null, order); if (cursor.moveToFirst()) { do { - GBActivitySample GBActivitySample = new GBActivitySample( + GBActivitySample sample = new GBActivitySample( + provider, cursor.getInt(cursor.getColumnIndex(KEY_TIMESTAMP)), - (byte) cursor.getInt(cursor.getColumnIndex(KEY_PROVIDER)), - (short) cursor.getInt(cursor.getColumnIndex(KEY_INTENSITY)), - (byte) cursor.getInt(cursor.getColumnIndex(KEY_STEPS)), - (byte) cursor.getInt(cursor.getColumnIndex(KEY_TYPE))); - GBActivitySampleList.add(GBActivitySample); + cursor.getShort(cursor.getColumnIndex(KEY_INTENSITY)), + cursor.getShort(cursor.getColumnIndex(KEY_STEPS)), + (byte) cursor.getShort(cursor.getColumnIndex(KEY_TYPE))); + samples.add(sample); } while (cursor.moveToNext()); } } - return GBActivitySampleList; + return samples; } - private String getWhereClauseFor(int activityTypes) { + private String getWhereClauseFor(int activityTypes, SampleProvider provider) { if (activityTypes == ActivityKind.TYPE_ALL) { return ""; // no further restriction } StringBuilder builder = new StringBuilder(" and ("); - byte[] dbActivityTypes = ActivityKind.mapToDBActivityTypes(activityTypes); + byte[] dbActivityTypes = ActivityKind.mapToDBActivityTypes(activityTypes, provider); for (int i = 0; i < dbActivityTypes.length; i++) { builder.append(" type=").append(dbActivityTypes[i]); if (i + 1 < dbActivityTypes.length) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/GBSummaryOfDay.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/GBSummaryOfDay.java new file mode 100644 index 000000000..8c3b26e5a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/GBSummaryOfDay.java @@ -0,0 +1,28 @@ +package nodomain.freeyourgadget.gadgetbridge.database; + +import nodomain.freeyourgadget.gadgetbridge.model.SummaryOfDay; + +public class GBSummaryOfDay implements SummaryOfDay { + private byte provider; + private int steps; + private int dayStartWakeupTime; + private int dayEndFallAsleepTime; + + public byte getProvider() { + return provider; + } + + public int getSteps() { + return steps; + } + + public int getDayStartWakeupTime() { + return dayStartWakeupTime; + } + + public int getDayEndFallAsleepTime() { + return dayEndFallAsleepTime; + } + + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/UsedConfiguration.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/UsedConfiguration.java new file mode 100644 index 000000000..976dc8ade --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/UsedConfiguration.java @@ -0,0 +1,16 @@ +package nodomain.freeyourgadget.gadgetbridge.database; + +/** + * Contains the configuration used for particular activity samples. + */ +public class UsedConfiguration { + String fwVersion; + String userName; + short userWeight; + short userSize; + // ... + int usedFrom; // timestamp + int usedUntil; // timestamp + short sleepGoal; // minutes + short stepsGoal; +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandCoordinator.java index de1241c29..b6154e881 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandCoordinator.java @@ -15,9 +15,15 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBDevice; import nodomain.freeyourgadget.gadgetbridge.activities.ChartsActivity; import nodomain.freeyourgadget.gadgetbridge.discovery.DeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public class MiBandCoordinator implements DeviceCoordinator { private static final Logger LOG = LoggerFactory.getLogger(MiBandCoordinator.class); + private final MiBandSampleProvider sampleProvider; + + public MiBandCoordinator() { + sampleProvider = new MiBandSampleProvider(); + } @Override public boolean supports(DeviceCandidate candidate) { @@ -43,6 +49,11 @@ public class MiBandCoordinator implements DeviceCoordinator { return ChartsActivity.class; } + @Override + public SampleProvider getSampleProvider() { + return sampleProvider; + } + public static boolean hasValidUserInfo() { String dummyMacAddress = MiBandService.MAC_ADDRESS_FILTER + ":00:00:00"; try { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSampleProvider.java new file mode 100644 index 000000000..efc1ec753 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSampleProvider.java @@ -0,0 +1,64 @@ +package nodomain.freeyourgadget.gadgetbridge.miband; + +import nodomain.freeyourgadget.gadgetbridge.charts.ActivityKind; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; + +public class MiBandSampleProvider implements SampleProvider { + public static final byte TYPE_DEEP_SLEEP = 5; + public static final byte TYPE_LIGHT_SLEEP = 4; + public static final byte TYPE_ACTIVITY = -1; + public static final byte TYPE_UNKNOWN = -1; + +// public static final byte TYPE_CHARGING = 6; +// public static final byte TYPE_NONWEAR = 3; +// public static final byte TYPE_NREM = 5; // DEEP SLEEP +// public static final byte TYPE_ONBED = 7; +// public static final byte TYPE_REM = 4; // LIGHT SLEEP +// public static final byte TYPE_RUNNING = 2; +// public static final byte TYPE_SLIENT = 0; +// public static final byte TYPE_USER = 100; +// public static final byte TYPE_WALKING = 1; + + // maybe this should be configurable 256 seems way off, though. + private float movementDivisor = 180.0f; //256.0f; + + @Override + public int normalizeType(byte rawType) { + switch (rawType) { + case TYPE_DEEP_SLEEP: + return ActivityKind.TYPE_DEEP_SLEEP; + case TYPE_LIGHT_SLEEP: + return ActivityKind.TYPE_LIGHT_SLEEP; + case TYPE_ACTIVITY: + return ActivityKind.TYPE_ACTIVITY; + default: +// case TYPE_UNKNOWN: // fall through + return ActivityKind.TYPE_UNKNOWN; + } + } + + @Override + public byte toRawActivityKind(int activityKind) { + switch (activityKind) { + case ActivityKind.TYPE_ACTIVITY: + return TYPE_ACTIVITY; + case ActivityKind.TYPE_DEEP_SLEEP: + return TYPE_DEEP_SLEEP; + case ActivityKind.TYPE_LIGHT_SLEEP: + return TYPE_LIGHT_SLEEP; + case ActivityKind.TYPE_UNKNOWN: // fall through + default: + return TYPE_UNKNOWN; + } + } + + @Override + public float normalizeIntensity(short rawIntensity) { + return rawIntensity / movementDivisor; + } + + @Override + public byte getID() { + return SampleProvider.PROVIDER_MIBAND; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java index 43ef6726d..dc2088bfa 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java @@ -33,6 +33,7 @@ import nodomain.freeyourgadget.gadgetbridge.btle.BtLEAction; import nodomain.freeyourgadget.gadgetbridge.btle.SetDeviceBusyAction; import nodomain.freeyourgadget.gadgetbridge.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_COLOUR; import static nodomain.freeyourgadget.gadgetbridge.miband.MiBandConst.DEFAULT_VALUE_FLASH_COUNT; @@ -720,6 +721,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { byte category, intensity, steps; ActivityDatabaseHandler dbHandler = GBApplication.getActivityDatabaseHandler(); + try (SQLiteDatabase db = dbHandler.getWritableDatabase()) { // explicitly keep the db open while looping over the samples for (int i = 0; i < activityStruct.activityDataHolderProgress; i += 3) { //TODO: check if multiple of 3, if not something is wrong category = activityStruct.activityDataHolder[i]; @@ -728,7 +730,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { dbHandler.addGBActivitySample( (int) (activityStruct.activityDataTimestampProgress.getTimeInMillis() / 1000), - GBActivitySample.PROVIDER_MIBAND, + SampleProvider.PROVIDER_MIBAND, intensity, steps, category); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySample.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySample.java new file mode 100644 index 000000000..4e5123aaa --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/ActivitySample.java @@ -0,0 +1,42 @@ +package nodomain.freeyourgadget.gadgetbridge.model; + +import nodomain.freeyourgadget.gadgetbridge.charts.ActivityKind; + +public interface ActivitySample { + /** + * Returns the provider of the data. + * @return who created the sample data + */ + SampleProvider getProvider(); + + /** + * Timestamp of the sample, resolution is seconds! + */ + int getTimestamp(); + + /** + * Returns the raw activity kind value as recorded by the SampleProvider + */ + byte getRawKind(); + + /** + * Returns the activity kind value as recorded by the SampleProvider + * @see ActivityKind + */ + int getKind(); + + /** + * Returns the raw intensity value as recorded by the SampleProvider + */ + short getRawIntensity(); + + /** + * Returns the normalized intensity value between 0 and 1 + */ + float getIntensity(); + + /** + * Returns the number of steps performed during the period of this sample + */ + short getSteps(); +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SampleProvider.java new file mode 100644 index 000000000..331127610 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SampleProvider.java @@ -0,0 +1,16 @@ +package nodomain.freeyourgadget.gadgetbridge.model; + +public interface SampleProvider { + public static final byte PROVIDER_MIBAND = 0; + public static final byte PROVIDER_PEBBLE_MORPHEUZ = 1; + public static final byte PROVIDER_PEBBLE_GADGETBRIDGE = 2; + public static final byte PROVIDER_UNKNOWN = 100; + + int normalizeType(byte rawType); + + byte toRawActivityKind(int activityKind); + + float normalizeIntensity(short rawIntensity); + + byte getID(); +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SummaryOfDay.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SummaryOfDay.java new file mode 100644 index 000000000..e656c382b --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/SummaryOfDay.java @@ -0,0 +1,12 @@ +package nodomain.freeyourgadget.gadgetbridge.model; + +public interface SummaryOfDay { + public byte getProvider(); + + public int getSteps(); + + public int getDayStartWakeupTime(); + + public int getDayEndFallAsleepTime(); + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/GadgetbridgePblSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/GadgetbridgePblSupport.java index 01bb537ea..f4a6520d2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/GadgetbridgePblSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/GadgetbridgePblSupport.java @@ -16,6 +16,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBActivitySample; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public class GadgetbridgePblSupport { @@ -52,7 +53,7 @@ public class GadgetbridgePblSupport { byte type = (byte) ((sample & 0xe000) >>> 13); byte intensity = (byte) ((sample & 0x1f80) >>> 7); byte steps = (byte) (sample & 0x007f); - GBApplication.getActivityDatabaseHandler().addGBActivitySample(timestamp + offset_seconds, GBActivitySample.PROVIDER_PEBBLE_GADGETBRIDGE, intensity, steps, type); + GBApplication.getActivityDatabaseHandler().addGBActivitySample(timestamp + offset_seconds, SampleProvider.PROVIDER_PEBBLE_GADGETBRIDGE, intensity, steps, type); offset_seconds += 60; } break; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSampleProvider.java new file mode 100644 index 000000000..c45ed8fab --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSampleProvider.java @@ -0,0 +1,54 @@ +package nodomain.freeyourgadget.gadgetbridge.pebble; + +import nodomain.freeyourgadget.gadgetbridge.charts.ActivityKind; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; + +public class MorpheuzSampleProvider implements SampleProvider { + // raw types + public static final byte TYPE_DEEP_SLEEP = 5; + public static final byte TYPE_LIGHT_SLEEP = 4; + public static final byte TYPE_ACTIVITY = -1; + public static final byte TYPE_UNKNOWN = -1; + + protected float movementDivisor = 5000f; + + @Override + public int normalizeType(byte rawType) { + switch (rawType) { + case TYPE_DEEP_SLEEP: + return ActivityKind.TYPE_DEEP_SLEEP; + case TYPE_LIGHT_SLEEP: + return ActivityKind.TYPE_LIGHT_SLEEP; + case TYPE_ACTIVITY: + return ActivityKind.TYPE_ACTIVITY; + default: +// case TYPE_UNKNOWN: // fall through + return ActivityKind.TYPE_UNKNOWN; + } + } + + @Override + public byte toRawActivityKind(int activityKind) { + switch (activityKind) { + case ActivityKind.TYPE_ACTIVITY: + return TYPE_ACTIVITY; + case ActivityKind.TYPE_DEEP_SLEEP: + return TYPE_DEEP_SLEEP; + case ActivityKind.TYPE_LIGHT_SLEEP: + return TYPE_LIGHT_SLEEP; + case ActivityKind.TYPE_UNKNOWN: // fall through + default: + return TYPE_UNKNOWN; + } + } + + @Override + public float normalizeIntensity(short rawIntensity) { + return rawIntensity/movementDivisor; + } + + @Override + public byte getID() { + return SampleProvider.PROVIDER_PEBBLE_MORPHEUZ; + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSupport.java index 95f822101..9ca4b0391 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/MorpheuzSupport.java @@ -16,6 +16,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSleepMonitorResult; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public class MorpheuzSupport { @@ -101,14 +102,14 @@ public class MorpheuzSupport { short index = (short) ((int) pair.second >> 16); short intensity = (short) ((int) pair.second & 0xffff); LOG.info("got point:" + index + " " + intensity); - byte type = GBActivitySample.TYPE_UNKNOWN; + byte type = MorpheuzSampleProvider.TYPE_UNKNOWN; if (intensity <= 120) { - type = GBActivitySample.TYPE_DEEP_SLEEP; + type = MorpheuzSampleProvider.TYPE_DEEP_SLEEP; } else if (intensity <= 1000) { - type = GBActivitySample.TYPE_LIGHT_SLEEP; + type = MorpheuzSampleProvider.TYPE_LIGHT_SLEEP; } if (index >= 0) { - GBApplication.getActivityDatabaseHandler().addGBActivitySample(recording_base_timestamp + index * 600, GBActivitySample.PROVIDER_PEBBLE_MORPHEUZ, intensity, (byte) 0, type); + GBApplication.getActivityDatabaseHandler().addGBActivitySample(recording_base_timestamp + index * 600, SampleProvider.PROVIDER_PEBBLE_MORPHEUZ, intensity, (byte) 0, type); } ctrl_message = MorpheuzSupport.CTRL_VERSION_DONE | MorpheuzSupport.CTRL_SET_LAST_SENT | MorpheuzSupport.CTRL_DO_NEXT; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleCoordinator.java index 2e1f135fc..1ddd6217e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleCoordinator.java @@ -7,8 +7,16 @@ import nodomain.freeyourgadget.gadgetbridge.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.DeviceType; import nodomain.freeyourgadget.gadgetbridge.GBDevice; import nodomain.freeyourgadget.gadgetbridge.discovery.DeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.SampleProvider; public class PebbleCoordinator implements DeviceCoordinator { + private MorpheuzSampleProvider sampleProvider; + + public PebbleCoordinator() { + sampleProvider = new MorpheuzSampleProvider(); +// sampleProvider = new PebbleGadgetBridgeSampleProvider(); + } + @Override public boolean supports(DeviceCandidate candidate) { return candidate.getName().startsWith("Pebble"); @@ -32,4 +40,9 @@ public class PebbleCoordinator implements DeviceCoordinator { public Class getPrimaryActivity() { return AppManagerActivity.class; } + + @Override + public SampleProvider getSampleProvider() { + return sampleProvider; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleGadgetBridgeSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleGadgetBridgeSampleProvider.java new file mode 100644 index 000000000..4407e3b62 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/pebble/PebbleGadgetBridgeSampleProvider.java @@ -0,0 +1,7 @@ +package nodomain.freeyourgadget.gadgetbridge.pebble; + +public class PebbleGadgetBridgeSampleProvider extends MorpheuzSampleProvider { + public PebbleGadgetBridgeSampleProvider() { + movementDivisor = 63.0f; + } +}