From 8eac10108290c2affe76534713e7c0e01e3f6214 Mon Sep 17 00:00:00 2001 From: Sandor Dornbush Date: Tue, 3 May 2011 21:27:45 -0700 Subject: [PATCH] Fix-up Zephyr - Add cadence - Add power - Check crc --- .../services/sensors/SensorUtils.java | 52 +++++++++++++++++++ .../services/sensors/ZephyrMessageParser.java | 32 +++++++----- 2 files changed, 71 insertions(+), 13 deletions(-) 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..45c2364a9 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 { @@ -32,6 +33,7 @@ public class SensorUtils { /** * Extract one unsigned short from a big 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 @@ -42,6 +44,56 @@ public class SensorUtils { 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++) { + crc = crc8PushByte(crc, buffer[i]); + } + return crc; + } + + /** + * Updates a CRC8 value by using the next byte passed to this method + * + * @param crc int of crc value + * @param add the next byte to add to the CRC8 calculation + */ + private static int crc8PushByte(int crc, byte add) { + int addInt = (add & 0x000000FF); + crc = crc ^ addInt; + for (int i = 0; i < 8; i++) { + if ((crc & 0x00000001) != 0x00000000) { + crc = (crc >> 1) ^ 0x0000008C; + } else { + crc = (crc >> 1); + } + } + return crc; + } + 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..0808c73ca 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 @@ -21,7 +21,7 @@ import com.google.android.apps.mytracks.Constants; import com.google.android.apps.mytracks.content.Sensor; /** - * An implementation of a SensorData parser for Zephyr HRM. + * An implementation of a Sensor MessageParser for Zephyr. * * @author Sandor Dornbush */ @@ -34,20 +34,24 @@ public class ZephyrMessageParser implements MessageParser { sb.append(String.format("%02X", buffer[i])); } 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); - // Cadence - //.setCadence(cadence / 16) - //.build(); + 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); + Sensor.SensorDataSet sds = Sensor.SensorDataSet.newBuilder() .setCreationTime(System.currentTimeMillis()) - .setHeartRate(b) + .setPower(power) + .setHeartRate(heartrate) + .setCadence(cadence) .build(); return sds; @@ -55,8 +59,10 @@ public class ZephyrMessageParser implements MessageParser { @Override public boolean isValid(byte[] buffer) { - // TODO crc etc. - return buffer[0] == 0x02 && buffer[59] == 0x03; + // Check STX, ETX and CRC Checksum + return buffer[0] == 0x02 + && buffer[59] == 0x03 + && SensorUtils.getCrc8(buffer, 3, 57) == (int) (buffer[58] & 0xFF); } @Override