added more comments + minor refactoring

This commit is contained in:
ml1050
2012-01-21 21:35:58 +01:00
parent bee9f46eaf
commit b0afea35ee
8 changed files with 138 additions and 76 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ limitations under the License.
<string name="allow_access_key">allowAccess</string>
<string name="announcement_frequency_key">announcementFrequency</string>
<string name="ant_cadence_sensor_id_key">antCadenceSensorId</string>
<string name="ant_cadence_speed_sensor_id_key">antCadSpdSensorId</string>
<string name="ant_cadence_speed_sensor_id_key">antCadenceSpeedSensorId</string>
<string name="ant_heart_rate_sensor_id_key">antHeartRateSensorId</string>
<string name="ant_srm_bridge_sensor_id_key">antSRMBridgeSensorId</string>
<string name="auto_resume_track_timeout_key">autoResumeTrackTimeout</string>
@@ -200,13 +200,13 @@ public class AntDirectSensorManager extends AntSensorManager
Log.i(TAG, "setup channel=" + channel + " deviceType=" + sensor.getDeviceType());
return setupAntSensorChannel(sensor.getNetworkNumber(),
channel,
sensor.getDeviceNumber(),
sensor.getDeviceType(),
(byte) 0x01,
sensor.getChannelPeriod(),
sensor.getFrequency(),
(byte) 0);
channel,
sensor.getDeviceNumber(),
sensor.getDeviceType(),
(byte) 0x01,
sensor.getChannelPeriod(),
sensor.getFrequency(),
(byte) 0);
}
private void sendSensorData(byte index, int value) {
@@ -242,11 +242,11 @@ public class AntDirectSensorManager extends AntSensorManager
sensorData = b.setCreationTime(now).build();
}
public void sendCadence(int value) {
public void setCadence(int value) {
sendSensorData(CADENCE_DATA_INDEX, value);
}
public void sendHeartRate(int value) {
public void setHeartRate(int value) {
sendSensorData(HEART_RATE_DATA_INDEX, value);
}
}
@@ -32,9 +32,9 @@ public abstract class AntSensorBase {
public static final byte NETWORK_NUMBER = 1;
public static final byte RF_FREQUENCY = 57;
protected short deviceNumber;
private byte deviceType;
private short channelPeriod;
private short deviceNumber;
private final byte deviceType;
private final short channelPeriod;
AntSensorBase(short deviceNumber, byte deviceType,
String deviceTypeString, short channelPeriod) {
@@ -17,14 +17,19 @@
package com.google.android.apps.mytracks.services.sensors.ant;
/**
* Interface for collecting data from the sensor classes
*
* Interface for collecting data from the sensors.
* @author Laszlo Molnar
*/
public interface AntSensorDataCollector {
public void sendCadence(int value);
/**
* Sets the current cadence to the value specified.
*/
void setCadence(int value);
public void sendHeartRate(int value);
/**
* Sets the current heart rate to the value specified.
*/
void setHeartRate(int value);
}
@@ -17,7 +17,7 @@ package com.google.android.apps.mytracks.services.sensors.ant;
/**
* Cadence sensor.
* Ant+ cadence sensor.
*
* @author Laszlo Molnar
*/
@@ -29,20 +29,20 @@ public class CadenceSensor extends AntSensorBase {
public static final byte CADENCE_DEVICE_TYPE = 122;
public static final short CADENCE_CHANNEL_PERIOD = 8102;
SensorDataProcessor cadence = new SensorDataProcessor();
SensorDataProcessor dataProcessor = new SensorDataProcessor();
CadenceSensor(short devNum) {
super(devNum, CADENCE_DEVICE_TYPE,
"cadence sensor", CADENCE_CHANNEL_PERIOD);
super(devNum, CADENCE_DEVICE_TYPE, "cadence sensor", CADENCE_CHANNEL_PERIOD);
}
/**
* Decode an ANT+ cadence sensor message.
* @param antMessage The byte array received from the cadence sensor.
*/
@Override
public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) {
int sensorTime = ((int) antMessage[5] & 0xFF) + ((int) antMessage[6] & 0xFF) * 256;
int crankRevs = ((int) antMessage[7] & 0xFF) + ((int) antMessage[8] & 0xFF) * 256;
c.sendCadence(cadence.getValue(crankRevs, sensorTime));
c.setCadence(dataProcessor.getValue(crankRevs, sensorTime));
}
};
@@ -17,7 +17,7 @@ package com.google.android.apps.mytracks.services.sensors.ant;
/**
* Combined cadence and speed sensor.
* Ant+ combined cadence and speed sensor.
*
* @author Laszlo Molnar
*/
@@ -29,20 +29,20 @@ public class CadenceSpeedSensor extends AntSensorBase {
public static final byte CADENCE_SPEED_DEVICE_TYPE = 121;
public static final short CADENCE_SPEED_CHANNEL_PERIOD = 8086;
SensorDataProcessor cadence = new SensorDataProcessor();
SensorDataProcessor dataProcessor = new SensorDataProcessor();
CadenceSpeedSensor(short devNum) {
super(devNum, CADENCE_SPEED_DEVICE_TYPE,
"speed&cadence sensor", CADENCE_SPEED_CHANNEL_PERIOD);
super(devNum, CADENCE_SPEED_DEVICE_TYPE, "speed&cadence sensor", CADENCE_SPEED_CHANNEL_PERIOD);
}
/**
* Decode an ANT+ cadence&speed sensor message.
* @param antMessage The byte array received from the sensor.
*/
@Override
public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) {
int sensorTime = ((int) antMessage[1] & 0xFF) + ((int) antMessage[2] & 0xFF) * 256;
int crankRevs = ((int) antMessage[3] & 0xFF) + ((int) antMessage[4] & 0xFF) * 256;
c.sendCadence(cadence.getValue(crankRevs, sensorTime));
c.setCadence(dataProcessor.getValue(crankRevs, sensorTime));
}
};
@@ -20,7 +20,7 @@ import static com.google.android.apps.mytracks.Constants.TAG;
import android.util.Log;
/**
* Heart reate monitor sensor.
* Ant+ heart reate monitor sensor.
*
* @author Laszlo Molnar
*/
@@ -33,17 +33,17 @@ public class HeartRateSensor extends AntSensorBase {
public static final short HEART_RATE_CHANNEL_PERIOD = 8070;
HeartRateSensor(short devNum) {
super(devNum, HEART_RATE_DEVICE_TYPE,
"heart rate monitor", HEART_RATE_CHANNEL_PERIOD);
super(devNum, HEART_RATE_DEVICE_TYPE, "heart rate monitor", HEART_RATE_CHANNEL_PERIOD);
}
/**
* Decode an ANT+ heart rate monitor message.
* @param antMessage The byte array received from the heart rate monitor.
*/
@Override
public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) {
int bpm = (int) antMessage[8] & 0xFF;
Log.d(TAG, "now:" + System.currentTimeMillis() + " heart rate=" + bpm);
c.sendHeartRate(bpm);
c.setHeartRate(bpm);
}
};
@@ -20,7 +20,7 @@ import android.util.Log;
import java.util.LinkedList;
/**
* Processes an ANT sensor data (counter) + timestamp pair,
* Processes an ANT+ sensor data (counter) + timestamp pair,
* and returns the instantaneous value of the sensor
*
* @author Laszlo Molnar
@@ -28,84 +28,141 @@ import java.util.LinkedList;
public class SensorDataProcessor {
/**
* History is used for looking back at the old data
* when no new data is present, but an instantaneous value is needed
* HistoryElement stores a time stamped sensor counter
*/
private class HistoryElement {
public long sysTime;
public int data;
public int sensorTime;
private static class HistoryElement {
final long systemTime;
final int data;
final int sensorTime;
HistoryElement(long sys, int d, int sens) {
sysTime = sys;
data = d;
sensorTime = sens;
HistoryElement(long systemTime, int data, int sensorTime) {
this.systemTime = systemTime;
this.data = data;
this.sensorTime = sensorTime;
}
};
}
// Removes old data from the history.
// Returns true if the remaining history is not empty.
/**
* Removes old data from the history.
*
* @param now the current system time
* @return true if the remaining history is not empty
*/
protected boolean removeOldHistory(long now) {
HistoryElement h;
while ((h = history.peek()) != null) {
if (now - h.sysTime <= historyLengthMillis) {
// if the first element of the list is in our desired time range then return
if (now - h.systemTime <= HISTORY_LENGTH_MILLIS) {
return true;
}
// otherwise remove the too old element, and look at the next (newer) one
history.removeFirst();
}
return false;
}
private int counter = -1; // the latest counter value reported by the sensor
private int actValue = 0;
public static final int historyLengthMillis = 5000; // 5 sec
/**
* The latest counter value reported by the sensor
*/
private int counter = -1;
/**
* The calculated instantaneous sensor value to be displayed
*/
private int displayedValue = 0;
private static final int ONE_SECOND_MILLIS = 1000;
private static final int HISTORY_LENGTH_MILLIS = ONE_SECOND_MILLIS * 5;
private static final int ONE_MINUTE_MILLIS = ONE_SECOND_MILLIS * 60;
private static final int SENSOR_TIME_RESOLUTION = 1024; // in a second
private static final int SENSOR_TIME_ONE_MINUTE = SENSOR_TIME_RESOLUTION * 60;
/**
* History of previous sensor data - oldest first
* only the latest HISTORY_LENGTH_MILLIS milliseconds of data is stored
*/
private LinkedList<HistoryElement> history = new LinkedList<HistoryElement>();
/**
* Calculates the instantaneous sensor value to be displayed
* using the history when the sensor only resends the old data
*/
private int getValueFromHistory(int data, long now) {
if (!removeOldHistory(now)) {
// there is nothing in the history, return 0
return displayedValue = 0;
}
HistoryElement f = history.getFirst();
HistoryElement l = history.getLast();
int sensorTimeChange = (l.sensorTime - f.sensorTime) & 0xFFFF;
int counterChange = (data - f.data) & 0xFFFF;
// difference between now and systemTime of the oldest history entry
// for better precision sensor timestamps are considered between
// the first and the last history entry (could be overkill)
int systemTimeChange = (int) (now - l.systemTime
+ (sensorTimeChange * ONE_SECOND_MILLIS) / SENSOR_TIME_RESOLUTION);
// displayedValue is not overwritten by this calculated value
// because it is still needed when a new sensor event arrives
int v = (counterChange * ONE_MINUTE_MILLIS) / systemTimeChange;
Log.d(TAG, "getValue returns (2):" + v);
// do not return larger number than displayedValue
return v < displayedValue ? v : displayedValue;
}
/**
* Calculates the instantaneous sensor value to be displayed
*
* @param data sensor reported counter value
* @param sensorTime sensor reported timestamp
* @return the calculated value
*/
public int getValue(int data, int sensorTime) {
long now = System.currentTimeMillis();
int dDelta = (data - counter) & 0xFFFF;
int counterChange = (data - counter) & 0xFFFF;
Log.d(TAG, "now=" + now + " data=" + data + " sensortime=" + sensorTime);
if (counter < 0) {
// store the actual counter value from the sensor
// store the initial counter value reported by the sensor
// the timestamp is probably out of date, so the history is not updated
counter = data;
return actValue = 0;
return displayedValue = 0;
}
counter = data;
if (dDelta != 0) {
if (counterChange != 0) {
// if new data is arrived from the sensor ...
if (removeOldHistory(now)) {
// ... and the history is not empty, then use the latest entry
HistoryElement h = history.getLast();
actValue = ((int) ((data - h.data) & 0xFFFF)) * 1024 * 60
/ (int) ((sensorTime - h.sensorTime) & 0xFFFF);
int sensorTimeChange = (sensorTime - h.sensorTime) & 0xFFFF;
counterChange = (data - h.data) & 0xFFFF;
displayedValue = counterChange * SENSOR_TIME_ONE_MINUTE / sensorTimeChange;
}
history.addLast(new HistoryElement(now, data, sensorTime));
} else if (!history.isEmpty()) {
HistoryElement h = history.getLast();
if (60000 < (now - h.sysTime) * actValue) {
if (!removeOldHistory(now)) {
actValue = 0;
} else {
HistoryElement f = history.getFirst();
HistoryElement l = history.getLast();
int sDelta = (l.sensorTime - f.sensorTime) & 0xFFFF;
int cDelta = (data - f.data) & 0xFFFF;
// the sensor has resent an old (counter,timestamp) pair,
// but the history is not empty
// the saved actValue is not overwritten by this
// the returned value is computed from the history
int v = (int) (cDelta * 60 * 1000 / (now - l.sysTime + (sDelta / 1024) * 1000));
Log.d(TAG, "getValue returns (2):" + v);
return v < actValue ? v : actValue;
}
} else {
// the current actValue is still valid, nothing to do here
}
HistoryElement h = history.getLast();
if (ONE_MINUTE_MILLIS < (now - h.systemTime) * displayedValue) {
// Too much time has passed since the last counter change.
// This means that a smaller value than displayedValue must be
// returned. So the history is looked up, and a calculated
// average number is returned.
// Note, that displayedValue is NOT updated unless the history
// is empty or contains outdated entries. In that case it is zeroed.
return getValueFromHistory(data, now);
} // else the current displayedValue is still valid, nothing to do here
} else {
actValue = 0;
// no new data from the sensor & the history is empty -> return 0
displayedValue = 0;
}
Log.d(TAG, "getValue returns:" + actValue);
return actValue;
Log.d(TAG, "getValue returns:" + displayedValue);
return displayedValue;
}
}