diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorUtils.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorUtils.java index 28f2f4fb8..96704196d 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorUtils.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorUtils.java @@ -24,6 +24,7 @@ import com.google.android.maps.mytracks.R; * A collection of methods for message parsers. * * @author Sandor Dornbush + * @author Nico Laum */ public class SensorUtils { @@ -41,7 +42,52 @@ public class SensorUtils { r |= buffer[index + 1] & 0xFF; return r; } - + + /** + * Extract one unsigned short from a little endian byte array. + * @param buffer the buffer to extract the short from + * @param index the first byte to be interpreted as part of the short + * @return The unsigned short at the given index in the buffer + */ + public static int unsignedShortToIntLittleEndian(byte[] buffer, int index) { + int r = buffer[index] & 0xFF; + r |= (buffer[index + 1] & 0xFF) << 8; + return r; + } + + /** + * Returns CRC8 (polynomial 0x8C) from byte array buffer[start] until (including) buffer[end] + * @param buffer the byte array of data (payload) + * @param start the position in the byte array where the payload begins + * @param end the position in the byte array where the payload ends + * @return CRC8 value + */ + public static int getCrc8(byte[] buffer, int start, int end) { + int[] crc = { 0x0 }; + + for (int i = start; i < (end+1); i++) { + crc8PushByte(crc, buffer[i]); + } + return crc[0]; + } + + /** + * Updates a CRC8 value by using the next byte passed to this method + * @param crc int of crc value (as an array to pass it as reference) + * @param add the next byte to add to the CRC8 calculation + */ + private static void crc8PushByte(int[] crc, byte add) { + int addInt = (add & 0x000000FF); + crc[0] = crc[0] ^ addInt; + for (int i = 0; i < 8; i++) { + if ((crc[0] & 0x00000001) != 0x00000000) { + crc[0] = (crc[0] >> 1) ^ 0x0000008C; + } else { + crc[0] = (crc[0] >> 1); + } + } + } + public static String getStateAsString(Sensor.SensorState state, Context c) { switch (state) { case NONE: diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java index da7a3672e..861d047ef 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ZephyrMessageParser.java @@ -27,7 +27,6 @@ import com.google.android.apps.mytracks.content.Sensor; */ public class ZephyrMessageParser implements MessageParser { - @Override public Sensor.SensorDataSet parseBuffer(byte[] buffer) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < buffer.length; i++) { @@ -35,36 +34,42 @@ public class ZephyrMessageParser implements MessageParser { } Log.w(Constants.TAG, "Got zephyr data: " + sb); // The provided units are 1/16 strides per minute. - // TODO: Fix the cadence calculation. - // int cadence = SensorUtils.unsignedShortToInt(buffer, 56); // Heart Rate - Sensor.SensorData.Builder b = Sensor.SensorData.newBuilder() - .setValue(buffer[12] & 0xFF) - .setState(Sensor.SensorState.SENDING); + Sensor.SensorData.Builder heartrate = Sensor.SensorData.newBuilder() + .setValue(buffer[12] & 0xFF) + .setState(Sensor.SensorState.SENDING); + // Changes Nico Laum (Power and Cadence) + Sensor.SensorData.Builder power = Sensor.SensorData.newBuilder() + .setValue(buffer[11] & 0xFF) + .setState(Sensor.SensorState.SENDING); + Sensor.SensorData.Builder cadence = Sensor.SensorData.newBuilder() + .setValue(SensorUtils.unsignedShortToIntLittleEndian(buffer, 56)/16) + .setState(Sensor.SensorState.SENDING); + // Cadence //.setCadence(cadence / 16) //.build(); Sensor.SensorDataSet sds = Sensor.SensorDataSet.newBuilder() .setCreationTime(System.currentTimeMillis()) - .setHeartRate(b) + .setPower(power) + .setHeartRate(heartrate) + .setCadence(cadence) .build(); return sds; } - @Override public boolean isValid(byte[] buffer) { - // TODO crc etc. - return buffer[0] == 0x02 && buffer[59] == 0x03; + // Changes Nico Laum + // Check STX, ETX and CRC Checksum + return (buffer[0] == 0x02 && buffer[59] == 0x03 && (SensorUtils.getCrc8(buffer, 3, 57) == (int) (buffer[58] & 0xFF))); } - @Override public int getFrameSize() { return 60; } - @Override public int findNextAlignment(byte[] buffer) { // TODO test or understand this code. for (int i = 0; i < buffer.length - 1; i++) {