Initial commit of contrib Ride Logger for Android

Logs rides to json files in Documents/Rides
Supports Ant and most internal sensors on Android:
Power, Heart Rate, GPS, Pressure, Temp, Acceleration...
This commit is contained in:
Chet Henry
2014-11-17 16:05:29 -07:00
parent d802cccd3c
commit 3fad5f296a
23 changed files with 1177 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

12
contrib/RideLogger/.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
# Ignores for Eclipse
/.settings/
# Ignores for Android Projects
/bin/
/gen/
/publish/
/local.properties
/secure.properties
# Ignores for Mac machines
.DS_Store

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE AndroidXML>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ridelogger"
android:versionCode="030100"
android:versionName="3.1.0" >
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="20" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<service
android:name="com.ridelogger.RideService"
android:icon="@drawable/ic_launcher"
android:label="@string/service_name" >
</service>
<activity
android:name="com.ridelogger.StartActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

View File

@@ -0,0 +1,15 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
android.library.reference.1=../AntPluginLib

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE AndroidXML>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView android:layout_height="0dp"
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_weight="1.0"/>
</LinearLayout>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE AndroidXML>
<resources>
<string name="app_name">Ride Logger</string>
<string name="service_name">Logging Ride</string>
</resources>

View File

@@ -0,0 +1,366 @@
package com.ridelogger;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceType;
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import com.ridelogger.R;
import com.ridelogger.listners.Gps;
import com.ridelogger.listners.HeartRate;
import com.ridelogger.listners.Power;
import com.ridelogger.listners.Sensors;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Environment;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
public class RideService extends Service
{
public static BufferedWriter buf;
public static long start_time;
public static Map<String, String> current_values;
public boolean rideStarted = false;
public static HeartRate hr;
public static Power w;
public static Gps gps;
public static Sensors sensors;
MultiDeviceSearch mSearch;
MultiDeviceSearch.SearchCallbacks mCallback;
MultiDeviceSearch.RssiCallback mRssiCallback;
public int notifyID = 1;
NotificationManager mNotificationManager;
public String file_name = "";
SharedPreferences settings;
/**
*
* @return BufferedWriter
*/
public static BufferedWriter getBuf() {
return buf;
}
/**
*
* @return start_time
*/
public static long getStartTime() {
return start_time;
}
/**
*
* @return start_time
*/
public static Map<String, String> getCurrentValues() {
return current_values;
}
/**
*
* @return w
*/
public static Power getPower() {
return w;
}
/**
*
* @return w
*/
public static void setPower(Power pw) {
w = pw;
if(w == null) {
w = pw;
}
}
/**
*
* @return hr
*/
public static HeartRate getHeartRate() {
return hr;
}
public static void setHeartRate(HeartRate phr) {
if(hr == null) {
hr = phr;
}
}
public static void setGps(Gps pgps) {
if(gps == null) {
gps = pgps;
}
}
public static Gps getGps() {
return gps;
}
public static void setSensors(Sensors psens) {
if(sensors == null) {
sensors = psens;
}
}
public static Sensors getSensors() {
return sensors;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startRide();
return Service.START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
public boolean onUnbind (Intent intent) {
return true;
}
@Override
public void onDestroy() {
stopRide();
super.onDestroy();
}
protected void startRide() {
if(rideStarted) return;
start_time = System.currentTimeMillis();
file_name = "ride-" + start_time + ".json";
current_values = new HashMap<String, String>();
SimpleDateFormat f = new SimpleDateFormat("yyyy/MMM/dd HH:mm:ss");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
String utc = f.format(new Date(start_time));
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(start_time);
String month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US);
String week_day = cal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US);
String year = Integer.toString(cal.get(Calendar.YEAR));
settings = getSharedPreferences(StartActivity.PREFS_NAME, 0);
String rider_name = settings.getString(StartActivity.RIDER_NAME, "");
final Set<String> pairedAnts = settings.getStringSet(StartActivity.PAIRED_ANTS, null);
current_values.put("SECS", "0.0");
String rideHeadder = "{" +
"\"RIDE\":{" +
"\"STARTTIME\":\"" + utc + " UTC\"," +
"\"RECINTSECS\":1," +
"\"DEVICETYPE\":\"Android\"," +
"\"IDENTIFIER\":\"\"," +
"\"TAGS\":{" +
"\"Athlete\":\"" + rider_name + "\"," +
"\"Calendar Text\":\"Auto Recored Android Ride\"," +
"\"Change History\":\"\"," +
"\"Data\":\"\"," +
"\"Device\":\"\"," +
"\"Device Info\":\"\"," +
"\"File Format\":\"\"," +
"\"Filename\":\"\"," +
"\"Month\":\"" + month +"\"," +
"\"Notes\":\"\"," +
"\"Objective\":\"\"," +
"\"Sport\":\"Bike\"," +
"\"Weekday\":\"" + week_day + "\"," +
"\"Workout Code\":\"\"," +
"\"Year\":\"" + year + "\"" +
"}," +
"\"SAMPLES\":[{\"SECS\":0}";
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File dir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS
),
"Rides"
);
File file = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS
) + "/Rides",
"ride-" + start_time + ".json"
);
try {
dir.mkdirs();
file.createNewFile();
buf = new BufferedWriter(new FileWriter(file, true));
buf.write(rideHeadder);
if(gps == null) {
gps = new Gps(this);
}
if(sensors == null) {
sensors = new Sensors(this);
}
mCallback = new MultiDeviceSearch.SearchCallbacks(){
public void onDeviceFound(final MultiDeviceSearchResult deviceFound)
{
if (!deviceFound.isAlreadyConnected() && (pairedAnts == null || pairedAnts.contains(Integer.toString(deviceFound.getAntDeviceNumber())))) {
launchConnection(deviceFound);
}
}
@Override
public void onSearchStopped(RequestAccessResult arg0) {}
};
mRssiCallback = new MultiDeviceSearch.RssiCallback() {
@Override
public void onRssiUpdate(final int resultId, final int rssi){}
};
// start the multi-device search
mSearch = new MultiDeviceSearch(this, EnumSet.allOf(DeviceType.class), mCallback, mRssiCallback);
} catch (IOException e) {}
}
rideStarted = true;
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Ride On")
.setContentText("Building ride: " + file_name + " Click to stop ride.");
mBuilder.setProgress(0, 0, true);
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, StartActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(StartActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
if(mNotificationManager == null) {
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
startForeground(notifyID, mBuilder.build());
}
protected void stopRide() {
if(!rideStarted) return;
if(w != null) {
w.onDestroy();
}
if(hr != null) {
hr.onDestroy();
}
if(gps != null) {
gps.onDestroy();
}
if(sensors != null) {
sensors.onDestroy();
}
mSearch.close();
try {
buf.write("]}}");
buf.close();
} catch (IOException e) {}
rideStarted = false;
mNotificationManager.cancel(notifyID);
}
public void launchConnection(MultiDeviceSearchResult result)
{
switch (result.getAntDeviceType())
{
case BIKE_CADENCE:
break;
case BIKE_POWER:
if(w == null) {
w = new Power(result, this);
}
break;
case BIKE_SPD:
break;
case BIKE_SPDCAD:
break;
case BLOOD_PRESSURE:
break;
case ENVIRONMENT:
break;
case WEIGHT_SCALE:
break;
case HEARTRATE:
if(hr == null) {
hr = new HeartRate(result, this);
}
break;
case STRIDE_SDM:
break;
case FITNESS_EQUIPMENT:
break;
case GEOCACHE:
case CONTROLLABLE_DEVICE:
break;
case UNKNOWN:
break;
default:
break;
}
}
}

View File

@@ -0,0 +1,196 @@
package com.ridelogger;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashSet;
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceType;
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.text.InputType;
import android.widget.EditText;
import android.widget.Toast;
public class StartActivity extends FragmentActivity
{
Intent rsi;
public static final String PREFS_NAME = "RideLogger";
public static final String RIDER_NAME = "RiderName";
public static final String PAIRED_ANTS = "PairedAnts";
SharedPreferences settings;
AlertDialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
rsi = new Intent(this, RideService.class);
settings = getSharedPreferences(PREFS_NAME, 0);
String rider_name = settings.getString(RIDER_NAME, "");
if(rider_name == "") {
// 1. Instantiate an AlertDialog.Builder with its constructor
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// 2. Chain together various setter methods to set the dialog characteristics
builder.setMessage("What is your Golder Cheata Rider Name")
.setTitle("Chose Rider Name");
// Set up the input
final EditText input = new EditText(this);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
builder.setPositiveButton("Set", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String name = input.getText().toString();
if(name != "" && name != null) {
SharedPreferences.Editor editor = settings.edit();
editor.putString(RIDER_NAME, name);
editor.commit();
setupAnt();
}
}
});
// 3. Get the AlertDialog from create()
dialog = builder.create();
dialog.show();
} else {
toggleRide();
finish();
}
}
protected void setupAnt() {
MultiDeviceSearch mSearch;
MultiDeviceSearch.SearchCallbacks mCallback;
MultiDeviceSearch.RssiCallback mRssiCallback;
final ArrayList<MultiDeviceSearchResult> foundDevices = new ArrayList<MultiDeviceSearchResult>();
mCallback = new MultiDeviceSearch.SearchCallbacks(){
public void onDeviceFound(final MultiDeviceSearchResult deviceFound)
{
if(!foundDevices.contains(deviceFound)) {
foundDevices.add(deviceFound);
selectDevicesDialog(foundDevices);
}
}
@Override
public void onSearchStopped(RequestAccessResult arg0) {}
};
mRssiCallback = new MultiDeviceSearch.RssiCallback() {
@Override
public void onRssiUpdate(final int resultId, final int rssi){}
};
// start the multi-device search
mSearch = new MultiDeviceSearch(this, EnumSet.allOf(DeviceType.class), mCallback, mRssiCallback);
}
protected void selectDevicesDialog(final ArrayList<MultiDeviceSearchResult> foundDevices) {
final ArrayList<Integer> mSelectedItems = new ArrayList<Integer>(); // Where we track the selected items
final ArrayList<CharSequence> foundDevicesString = new ArrayList<CharSequence>();
for(MultiDeviceSearchResult device : foundDevices) {
foundDevicesString.add(device.getAntDeviceType() + " - " + device.getDeviceDisplayName());
}
CharSequence[] foundDevicesCharSeq = foundDevicesString.toArray(new CharSequence[foundDevicesString.size()]);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// Set the dialog title
builder.setTitle("Select Paired Ant Devices")
// Specify the list array, the items to be selected by default (null for none),
// and the listener through which to receive callbacks when items are selected
.setMultiChoiceItems(foundDevicesCharSeq, null, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
// If the user checked the item, add it to the selected items
mSelectedItems.add(which);
} else if (mSelectedItems.contains(which)) {
// Else, if the item is already in the array, remove it
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// Set the action buttons
.setPositiveButton("Pair", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
ArrayList<String> ids = new ArrayList<String>();
for(Integer index : mSelectedItems) {
ids.add(Integer.toString(foundDevices.get(index).getAntDeviceNumber()));
}
SharedPreferences.Editor editor = settings.edit();
editor.putStringSet(PAIRED_ANTS, new HashSet<String>(ids));
editor.commit();
toggleRide();
finish();
}
});
dialog = builder.create();
dialog.show();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
private void stopRide() {
Toast toast = Toast.makeText(getApplicationContext(), "Stoping Ride!", Toast.LENGTH_LONG);
toast.show();
this.stopService(rsi);
}
protected void toggleRide() {
if(!isServiceRunning(RideService.class)) {
startRide();
} else {
stopRide();
}
}
private void startRide() {
if(!isServiceRunning(RideService.class)) {
this.startService(rsi);
}
Toast toast = Toast.makeText(getApplicationContext(), "Starting Ride!", Toast.LENGTH_LONG);
toast.show();
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,114 @@
package com.ridelogger.listners;
import android.content.Context;
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState;
import com.dsi.ant.plugins.antplus.pccbase.PccReleaseHandle;
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IDeviceStateChangeReceiver;
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IPluginAccessResultReceiver;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import com.ridelogger.RideService;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Map;
/**
* Base class to connects to Heart Rate Plugin and display all the event data.
*/
public class Base
{
public static BufferedWriter buf;
public static long start_time;
public static Map<String, String> current_values;
public PccReleaseHandle<?> releaseHandle;
public Context context;
public Base(MultiDeviceSearchResult result, Context mContext) {
init(mContext);
}
public Base(Context mContext) {
init(mContext);
}
public void init(Context mContext) {
buf = RideService.getBuf();
start_time = RideService.getStartTime();
current_values = RideService.getCurrentValues();
context = mContext;
}
IDeviceStateChangeReceiver mDeviceStateChangeReceiver = new IDeviceStateChangeReceiver() {
@Override
public void onDeviceStateChange(final DeviceState newDeviceState){}
};
public IPluginAccessResultReceiver<?> mResultReceiver;
public void writeData(String key, String value)
{
if(!current_values.containsKey(key) || current_values.get(key) != value) {
String ts = String.valueOf((double) (System.currentTimeMillis() - start_time) / 1000.0);
current_values.put("SECS", ts);
current_values.put(key, value);
try {
buf.write(",{");
buf.write("\"");
buf.write("SECS");
buf.write("\":");
buf.write(ts);
buf.write(",\"");
buf.write(key);
buf.write("\":");
buf.write(value);
buf.write("}");
} catch (IOException e) {}
}
}
public void writeData(Map<String, String> map)
{
String ts = String.valueOf((double) (System.currentTimeMillis() - start_time) / 1000.0);
current_values.put("SECS", ts);
try {
buf.write(",{");
buf.write("\"");
buf.write("SECS");
buf.write("\":");
buf.write(ts);
for (Map.Entry<String, String> entry : map.entrySet())
{
String key = entry.getKey();
String value = entry.getValue();
buf.write(",\"");
buf.write(key);
buf.write("\":");
buf.write(value);
current_values.put(key, value);
}
buf.write("}");
} catch (IOException e) {}
}
public void onDestroy()
{
if(releaseHandle != null) {
releaseHandle.close();
}
}
}

View File

@@ -0,0 +1,45 @@
package com.ridelogger.listners;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
public class Gps extends Base
{
public Gps(Context mContext)
{
super(mContext);
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
Map<String, String> map = new HashMap<String, String>();
map.put("ALTITUDE", Double.toString(location.getAltitude()) );
map.put("KPH", Float.toString( location.getSpeed()) );
map.put("bearing", Float.toString( location.getBearing()) );
map.put("gpsa", Float.toString( location.getAccuracy()) );
map.put("LAT", Double.toString(location.getLatitude()) );
map.put("LON", Double.toString(location.getLongitude()));
writeData(map);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}

View File

@@ -0,0 +1,44 @@
package com.ridelogger.listners;
import android.content.Context;
import com.dsi.ant.plugins.antplus.pcc.AntPlusHeartRatePcc;
import com.dsi.ant.plugins.antplus.pcc.AntPlusHeartRatePcc.DataState;
import com.dsi.ant.plugins.antplus.pcc.AntPlusHeartRatePcc.IHeartRateDataReceiver;
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState;
import com.dsi.ant.plugins.antplus.pcc.defines.EventFlag;
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IPluginAccessResultReceiver;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import java.math.BigDecimal;
import java.util.EnumSet;
/**
* Base class to connects to Heart Rate Plugin and display all the event data.
*/
public class HeartRate extends Base
{
public HeartRate(MultiDeviceSearchResult result, Context mContext) {
super(result, mContext);
releaseHandle = AntPlusHeartRatePcc.requestAccess(context, result.getAntDeviceNumber(), 0, mResultReceiver, mDeviceStateChangeReceiver);
}
public IPluginAccessResultReceiver<AntPlusHeartRatePcc> mResultReceiver = new IPluginAccessResultReceiver<AntPlusHeartRatePcc>() {
//Handle the result, connecting to events on success or reporting failure to user.
@Override
public void onResultReceived(AntPlusHeartRatePcc result, RequestAccessResult resultCode, DeviceState initialDeviceState)
{
if(resultCode == com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult.SUCCESS) {
result.subscribeHeartRateDataEvent(
new IHeartRateDataReceiver() {
@Override
public void onNewHeartRateData(final long estTimestamp, EnumSet<EventFlag> eventFlags, final int computedHeartRate, final long heartBeatCount, final BigDecimal heartBeatEventTime, final DataState dataState) {
writeData("HR", String.valueOf(computedHeartRate));
}
}
);
}
}
};
}

View File

@@ -0,0 +1,183 @@
package com.ridelogger.listners;
import android.content.Context;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.CalculatedWheelDistanceReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.CalculatedWheelSpeedReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.DataSource;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.ICalculatedCrankCadenceReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.ICalculatedPowerReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.ICalculatedTorqueReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IInstantaneousCadenceReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IPedalPowerBalanceReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IPedalSmoothnessReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IRawCrankTorqueDataReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IRawPowerOnlyDataReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.IRawWheelTorqueDataReceiver;
import com.dsi.ant.plugins.antplus.pcc.AntPlusBikePowerPcc.ITorqueEffectivenessReceiver;
import com.dsi.ant.plugins.antplus.pcc.defines.DeviceState;
import com.dsi.ant.plugins.antplus.pcc.defines.EventFlag;
import com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult;
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IDeviceStateChangeReceiver;
import com.dsi.ant.plugins.antplus.pccbase.AntPluginPcc.IPluginAccessResultReceiver;
import com.dsi.ant.plugins.antplus.pccbase.MultiDeviceSearch.MultiDeviceSearchResult;
import java.math.BigDecimal;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/**
* Base class to connects to Heart Rate Plugin and display all the event data.
*/
public class Power extends Base
{
public Power(MultiDeviceSearchResult result, Context mContext) {
super(result, mContext);
releaseHandle = AntPlusBikePowerPcc.requestAccess(context, result.getAntDeviceNumber(), 0, mResultReceiver, mDeviceStateChangeReceiver);
}
BigDecimal wheelCircumferenceInMeters = new BigDecimal("2.07");
IDeviceStateChangeReceiver mDeviceStateChangeReceiver = new IDeviceStateChangeReceiver()
{
@Override
public void onDeviceStateChange(final DeviceState newDeviceState){}
};
protected IPluginAccessResultReceiver<AntPlusBikePowerPcc> mResultReceiver = new IPluginAccessResultReceiver<AntPlusBikePowerPcc>() {
//Handle the result, connecting to events on success or reporting failure to user.
@Override
public void onResultReceived(AntPlusBikePowerPcc result, RequestAccessResult resultCode, DeviceState initialDeviceState)
{
if(resultCode == com.dsi.ant.plugins.antplus.pcc.defines.RequestAccessResult.SUCCESS) {
result.subscribeCalculatedPowerEvent(new ICalculatedPowerReceiver() {
@Override
public void onNewCalculatedPower(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedPower) {
writeData("WATTS", String.format("%.1f", calculatedPower));
}
}
);
result.subscribeCalculatedTorqueEvent(
new ICalculatedTorqueReceiver() {
@Override
public void onNewCalculatedTorque(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedTorque) {
writeData("NM", String.format("%.1f", calculatedTorque));
}
}
);
result.subscribeCalculatedCrankCadenceEvent(
new ICalculatedCrankCadenceReceiver() {
@Override
public void onNewCalculatedCrankCadence(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedCrankCadence) {
writeData("RPM", String.format("%.1f", calculatedCrankCadence));
}
}
);
result.subscribeCalculatedWheelSpeedEvent(
new CalculatedWheelSpeedReceiver(wheelCircumferenceInMeters) {
@Override
public void onNewCalculatedWheelSpeed(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedWheelSpeed)
{
writeData("KMH", String.format("%.1f", calculatedWheelSpeed));
}
}
);
result.subscribeCalculatedWheelDistanceEvent(
new CalculatedWheelDistanceReceiver(wheelCircumferenceInMeters) {
@Override
public void onNewCalculatedWheelDistance(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final BigDecimal calculatedWheelDistance)
{
writeData("KM", String.format("%.1f", calculatedWheelDistance));
}
}
);
result.subscribeInstantaneousCadenceEvent(
new IInstantaneousCadenceReceiver() {
@Override
public void onNewInstantaneousCadence(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final DataSource dataSource, final int instantaneousCadence)
{
writeData("RPM", String.format("%d", instantaneousCadence));
}
}
);
result.subscribeRawPowerOnlyDataEvent(
new IRawPowerOnlyDataReceiver() {
@Override
public void onNewRawPowerOnlyData(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long powerOnlyUpdateEventCount, final int instantaneousPower, final long accumulatedPower)
{
writeData("WATTS", String.format("%d", instantaneousPower));
}
}
);
result.subscribePedalPowerBalanceEvent(
new IPedalPowerBalanceReceiver() {
@Override
public void onNewPedalPowerBalance(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final boolean rightPedalIndicator, final int pedalPowerPercentage)
{
writeData("LTE", String.format("%d", pedalPowerPercentage));
}
}
);
result.subscribeRawWheelTorqueDataEvent(
new IRawWheelTorqueDataReceiver() {
@Override
public void onNewRawWheelTorqueData(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long wheelTorqueUpdateEventCount, final long accumulatedWheelTicks, final BigDecimal accumulatedWheelPeriod, final BigDecimal accumulatedWheelTorque)
{
writeData("NM", String.format("%.1f", accumulatedWheelTorque));
}
}
);
result.subscribeRawCrankTorqueDataEvent(
new IRawCrankTorqueDataReceiver() {
@Override
public void onNewRawCrankTorqueData(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long crankTorqueUpdateEventCount, final long accumulatedCrankTicks, final BigDecimal accumulatedCrankPeriod, final BigDecimal accumulatedCrankTorque)
{
writeData("NM", String.format("%.1f", accumulatedCrankTorque));
}
}
);
result.subscribeTorqueEffectivenessEvent(
new ITorqueEffectivenessReceiver() {
@Override
public void onNewTorqueEffectiveness(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long powerOnlyUpdateEventCount, final BigDecimal leftTorqueEffectiveness, final BigDecimal rightTorqueEffectiveness)
{
Map<String, String> map = new HashMap<String, String>();
map.put("LTE", String.format("%.1f", leftTorqueEffectiveness));
map.put("RTE", String.format("%.1f", rightTorqueEffectiveness));
writeData(map);
}
}
);
result.subscribePedalSmoothnessEvent(new IPedalSmoothnessReceiver() {
@Override
public void onNewPedalSmoothness(final long estTimestamp, final EnumSet<EventFlag> eventFlags, final long powerOnlyUpdateEventCount, final boolean separatePedalSmoothnessSupport, final BigDecimal leftOrCombinedPedalSmoothness, final BigDecimal rightPedalSmoothness)
{
Map<String, String> map = new HashMap<String, String>();
map.put("SNPLC", String.format("%.1f", leftOrCombinedPedalSmoothness));
map.put("SNPR", String.format("%.1f", rightPedalSmoothness));
writeData(map);
}
}
);
}
}
};
}

View File

@@ -0,0 +1,141 @@
package com.ridelogger.listners;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
public class Sensors extends Base
{
private SensorManager mSensorManager;
private Sensor mLight;
private Sensor mAccel;
private Sensor mPress;
private Sensor mTemp;
private Sensor mField;
private SensorEventListener luxListner;
private SensorEventListener accelListner;
private SensorEventListener pressListner;
private SensorEventListener tempListner;
private SensorEventListener fieldListner;
public Sensors(Context mContext)
{
super(mContext);
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
mAccel = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
mPress = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
mTemp = mSensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
mField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
if(mLight != null) {
luxListner = new SensorEventListener() {
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public final void onSensorChanged(SensorEvent event) {
// The light sensor returns a single value.
// Many sensors return 3 values, one for each axis.
writeData("lux", Float.toString(event.values[0]));
}
};
mSensorManager.registerListener(luxListner, mLight, 3000000);
}
if(mAccel != null) {
accelListner = new SensorEventListener() {
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public final void onSensorChanged(SensorEvent event) {
Map<String, String> map = new HashMap<String, String>();
map.put("ms2x", Float.toString(event.values[0]));
map.put("ms2y", Float.toString(event.values[1]));
map.put("ms2z", Float.toString(event.values[2]));
writeData(map);
}
};
mSensorManager.registerListener(accelListner, mAccel, SensorManager.SENSOR_DELAY_NORMAL);
}
if(mPress != null) {
pressListner = new SensorEventListener() {
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public final void onSensorChanged(SensorEvent event) {
// The light sensor returns a single value.
// Many sensors return 3 values, one for each axis.
writeData("press", Float.toString(event.values[0]));
}
};
mSensorManager.registerListener(pressListner, mPress, 3000000);
}
if(mTemp != null) {
tempListner = new SensorEventListener() {
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public final void onSensorChanged(SensorEvent event) {
// The light sensor returns a single value.
// Many sensors return 3 values, one for each axis.
writeData("temp", Float.toString(event.values[0]));
}
};
mSensorManager.registerListener(tempListner, mTemp, 3000000);
}
if(mField != null) {
fieldListner = new SensorEventListener() {
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {}
@Override
public final void onSensorChanged(SensorEvent event) {
Map<String, String> map = new HashMap<String, String>();
map.put("uTx", Float.toString(event.values[0]));
map.put("uTy", Float.toString(event.values[1]));
map.put("uTz", Float.toString(event.values[2]));
writeData(map);
}
};
mSensorManager.registerListener(fieldListner, mField, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
public void onDestroy()
{
if(luxListner != null) {
mSensorManager.unregisterListener(luxListner);
}
if(accelListner != null) {
mSensorManager.unregisterListener(accelListner);
}
if(pressListner != null) {
mSensorManager.unregisterListener(pressListner);
}
if(tempListner != null) {
mSensorManager.unregisterListener(tempListner);
}
if(fieldListner != null) {
mSensorManager.unregisterListener(fieldListner);
}
}
}