Cycling sensor: added basic chart classes

This commit is contained in:
Daniel Dakhno 2023-05-18 01:41:50 +02:00
parent 274573324d
commit 7ce2786072
12 changed files with 148 additions and 24 deletions

View File

@ -257,6 +257,9 @@ public class ChartsActivity extends AbstractGBFragmentActivity implements Charts
if (!coordinator.supportsRealtimeData()) { if (!coordinator.supportsRealtimeData()) {
arrayList.remove("livestats"); arrayList.remove("livestats");
} }
if (!coordinator.supportsCyclingData()) {
arrayList.remove("cycling");
}
return arrayList; return arrayList;
} }
@ -398,6 +401,8 @@ public class ChartsActivity extends AbstractGBFragmentActivity implements Charts
public Fragment getItem(int position) { public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page. // getItem is called to instantiate the fragment for the given page.
switch (enabledTabsList.get(position)) { switch (enabledTabsList.get(position)) {
case "cycling":
return new CyclingDataFragment();
case "activity": case "activity":
return new ActivitySleepChartFragment(); return new ActivitySleepChartFragment();
case "activitylist": case "activitylist":

View File

@ -0,0 +1,84 @@
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.github.mikephil.charting.charts.Chart;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.charts.PieChart;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
public class CyclingDataFragment extends AbstractChartFragment{
private PieChart currentSpeedChart;
private LineChart speedHistoryChart;
@Override
public String getTitle() {
return "Cycling data";
}
@Override
protected ChartsData refreshInBackground(ChartsHost chartsHost, DBHandler db, GBDevice device) {
List<? extends ActivitySample> samples = getSamples(db, device);
return null;
}
@Override
protected void renderCharts() {
}
@Override
protected List<? extends ActivitySample> getSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
return null;
}
@Override
protected void setupLegend(Chart chart) {
}
@Override
protected void updateChartsnUIThread(ChartsData chartsData) {
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_cycling, container, false);
currentSpeedChart = rootView.findViewById(R.id.chart_cycling_speed);
speedHistoryChart = rootView.findViewById(R.id.chart_cycling_speed_history);
currentSpeedChart.setNoDataText("");
currentSpeedChart.getLegend().setEnabled(false);
currentSpeedChart.setDrawHoleEnabled(true);
currentSpeedChart.setHoleColor(Color.WHITE);
currentSpeedChart.getDescription().setText("");
// currentSpeedChart.setTransparentCircleColor(Color.WHITE);
// currentSpeedChart.setTransparentCircleAlpha(110);
currentSpeedChart.setHoleRadius(70f);
currentSpeedChart.setTransparentCircleRadius(75f);
currentSpeedChart.setDrawCenterText(true);
currentSpeedChart.setRotationEnabled(true);
currentSpeedChart.setHighlightPerTapEnabled(true);
currentSpeedChart.setCenterTextOffset(0, 0);
currentSpeedChart.
return rootView;
}
}

View File

@ -290,6 +290,11 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
return supportsHeartRateMeasurement(device); return supportsHeartRateMeasurement(device);
} }
@Override
public boolean supportsCyclingData() {
return false;
}
@Override @Override
public boolean supportsRemSleep() { public boolean supportsRemSleep() {
return false; return false;

View File

@ -191,6 +191,15 @@ public interface DeviceCoordinator {
*/ */
boolean supportsActivityTracking(); boolean supportsActivityTracking();
/**
* Returns true if cycling data is supported by the device
* (with this coordinator).
* This enables the ChartsActivity.
*
* @return
*/
boolean supportsCyclingData();
/** /**
* Indicates whether the device supports recording dedicated activity tracks, like * Indicates whether the device supports recording dedicated activity tracks, like
* walking, hiking, running, swimming, etc. and retrieving the recorded * walking, hiking, running, swimming, etc. and retrieving the recorded

View File

@ -7,21 +7,19 @@ import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLEDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.bicycle_sensor.db.BicycleSensorActivitySampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.bicycle_sensor.db.CyclingSensorActivitySampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.bicycle_sensor.support.BicycleSensorSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.bicycle_sensor.support.CyclingSensorSupport;
public class BicycleSensorCoordinator extends AbstractBLEDeviceCoordinator { public class BicycleSensorCoordinator extends AbstractBLEDeviceCoordinator {
@Override @Override
@ -32,7 +30,7 @@ public class BicycleSensorCoordinator extends AbstractBLEDeviceCoordinator {
@NonNull @NonNull
@Override @Override
public DeviceType getSupportedType(GBDeviceCandidate candidate) { public DeviceType getSupportedType(GBDeviceCandidate candidate) {
if(candidate.supportsService(BicycleSensorSupport.UUID_BICYCLE_SENSOR_SERVICE)){ if(candidate.supportsService(CyclingSensorSupport.UUID_BICYCLE_SENSOR_SERVICE)){
return getDeviceType(); return getDeviceType();
} }
return DeviceType.UNKNOWN; return DeviceType.UNKNOWN;
@ -54,6 +52,11 @@ public class BicycleSensorCoordinator extends AbstractBLEDeviceCoordinator {
return false; return false;
} }
@Override
public boolean supportsCyclingData() {
return true;
}
@Override @Override
public boolean supportsActivityTracking() { public boolean supportsActivityTracking() {
return true; return true;
@ -61,7 +64,7 @@ public class BicycleSensorCoordinator extends AbstractBLEDeviceCoordinator {
@Override @Override
public SampleProvider<? extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) { public SampleProvider<? extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return new BicycleSensorActivitySampleProvider(device, session); return new CyclingSensorActivitySampleProvider(device, session);
} }
@Override @Override

View File

@ -11,8 +11,8 @@ import nodomain.freeyourgadget.gadgetbridge.entities.BicycleSensorActivitySample
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class BicycleSensorActivitySampleProvider extends AbstractSampleProvider<BicycleSensorActivitySample> { public class CyclingSensorActivitySampleProvider extends AbstractSampleProvider<BicycleSensorActivitySample> {
public BicycleSensorActivitySampleProvider(GBDevice device, DaoSession session) { public CyclingSensorActivitySampleProvider(GBDevice device, DaoSession session) {
super(device, session); super(device, session);
} }

View File

@ -27,14 +27,13 @@ import android.content.Context;
import android.widget.Toast; import android.widget.Toast;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.EnumSet;
import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.asteroidos.AsteroidOSDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.asteroidos.AsteroidOSDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.bicycle_sensor.support.BicycleSensorSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.bicycle_sensor.support.CyclingSensorSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.binary_sensor.BinarySensorSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.binary_sensor.BinarySensorSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.fitpro.FitProDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.fitpro.FitProDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.banglejs.BangleJSDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.banglejs.BangleJSDeviceSupport;
@ -44,7 +43,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.domyos.DomyosT540Sup
import nodomain.freeyourgadget.gadgetbridge.service.devices.flipper.zero.support.FlipperZeroSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.flipper.zero.support.FlipperZeroSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.galaxy_buds.GalaxyBudsDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.galaxy_buds.GalaxyBudsDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.hplus.HPlusSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitband5.AmazfitBand5Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitband5.AmazfitBand5Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitband7.AmazfitBand7Support; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitband7.AmazfitBand7Support;
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipLiteSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipLiteSupport;
@ -372,7 +370,7 @@ public class DeviceSupportFactory {
case SOFLOW_SO6: case SOFLOW_SO6:
return new ServiceDeviceSupport(new SoFlowSupport()); return new ServiceDeviceSupport(new SoFlowSupport());
case BICYCLE_SENSOR: case BICYCLE_SENSOR:
return new ServiceDeviceSupport(new BicycleSensorSupport()); return new ServiceDeviceSupport(new CyclingSensorSupport());
} }
return null; return null;
} }

View File

@ -6,8 +6,8 @@ import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.binary_sensor.BinarySensorSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.binary_sensor.BinarySensorSupport;
public class BicycleSensorBaseSupport extends AbstractBTLEDeviceSupport { public class CyclingSensorBaseSupport extends AbstractBTLEDeviceSupport {
public BicycleSensorBaseSupport(Logger logger) { public CyclingSensorBaseSupport(Logger logger) {
super(logger); super(logger);
} }

View File

@ -13,7 +13,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.UUID; import java.util.UUID;
@ -23,23 +22,20 @@ import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSett
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.bicycle_sensor.db.BicycleSensorActivitySampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.bicycle_sensor.db.CyclingSensorActivitySampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.BicycleSensorActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.BicycleSensorActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.Measurement;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.NotifyAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.NotifyAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.ReadAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.ReadAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfoProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.battery.BatteryInfoProfile;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class BicycleSensorSupport extends BicycleSensorBaseSupport{ public class CyclingSensorSupport extends CyclingSensorBaseSupport {
static class CyclingSpeedCadenceMeasurement { static class CyclingSpeedCadenceMeasurement {
@ -96,7 +92,7 @@ public class BicycleSensorSupport extends BicycleSensorBaseSupport{
public final static UUID UUID_BICYCLE_SENSOR_CSC_MEASUREMENT = public final static UUID UUID_BICYCLE_SENSOR_CSC_MEASUREMENT =
UUID.fromString("00002a5b-0000-1000-8000-00805f9b34fb"); UUID.fromString("00002a5b-0000-1000-8000-00805f9b34fb");
private static final Logger logger = LoggerFactory.getLogger(BicycleSensorSupport.class); private static final Logger logger = LoggerFactory.getLogger(CyclingSensorSupport.class);
private long persistenceInterval; private long persistenceInterval;
private long nextPersistenceTimestamp = 0; private long nextPersistenceTimestamp = 0;
@ -108,7 +104,7 @@ public class BicycleSensorSupport extends BicycleSensorBaseSupport{
private BluetoothGattCharacteristic batteryCharacteristic = null; private BluetoothGattCharacteristic batteryCharacteristic = null;
public BicycleSensorSupport() { public CyclingSensorSupport() {
super(logger); super(logger);
addSupportedService(UUID_BICYCLE_SENSOR_SERVICE); addSupportedService(UUID_BICYCLE_SENSOR_SERVICE);
@ -182,8 +178,8 @@ public class BicycleSensorSupport extends BicycleSensorBaseSupport{
DaoSession session = handler.getDaoSession(); DaoSession session = handler.getDaoSession();
BicycleSensorActivitySample sample = new BicycleSensorActivitySample(); BicycleSensorActivitySample sample = new BicycleSensorActivitySample();
BicycleSensorActivitySampleProvider sampleProvider = CyclingSensorActivitySampleProvider sampleProvider =
new BicycleSensorActivitySampleProvider(getDevice(), session); new CyclingSensorActivitySampleProvider(getDevice(), session);
boolean persistSample = currentMeasurement.revolutionDataPresent || currentMeasurement.cadenceDataPresent; boolean persistSample = currentMeasurement.revolutionDataPresent || currentMeasurement.cadenceDataPresent;

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.gridlayout.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
grid:columnCount="2">
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/chart_cycling_speed"
grid:layout_columnWeight="1"
grid:layout_rowWeight="1">
</com.github.mikephil.charting.charts.PieChart>
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart_cycling_speed_history"
grid:layout_columnSpan="2"
grid:layout_columnWeight="1"
grid:layout_rowWeight="1">
</com.github.mikephil.charting.charts.LineChart>
</androidx.gridlayout.widget.GridLayout>

View File

@ -2474,6 +2474,7 @@
</string-array> </string-array>
<string-array name="pref_charts_tabs_items_default"> <string-array name="pref_charts_tabs_items_default">
<item>@string/p_cycling</item>
<item>@string/p_activity</item> <item>@string/p_activity</item>
<item>@string/p_activity_list</item> <item>@string/p_activity_list</item>
<item>@string/p_sleep</item> <item>@string/p_sleep</item>

View File

@ -96,6 +96,7 @@
<item name="p_call_privacy_mode_number" type="string">number</item> <item name="p_call_privacy_mode_number" type="string">number</item>
<item name="p_call_privacy_mode_complete" type="string">complete</item> <item name="p_call_privacy_mode_complete" type="string">complete</item>
<item name="p_cycling" type="string">cycling</item>
<item name="p_activity" type="string">activity</item> <item name="p_activity" type="string">activity</item>
<item name="p_activity_list" type="string">activitylist</item> <item name="p_activity_list" type="string">activitylist</item>
<item name="p_sleep" type="string">sleep</item> <item name="p_sleep" type="string">sleep</item>