public static void MergeHeartRates(FitMessages messages) { float? hr_anchor_event_timestamp = 0.0f; DateTime hr_anchor_timestamp = new DateTime(0); bool hr_anchor_set = false; byte? last_valid_hr = 0; DateTime last_valid_hr_time = new DateTime(0); DateTime record_range_start_time = new DateTime(messages.Records[0].GetTimestamp()); int hr_start_index = 0; int hr_start_sub_index = 0; // // Update this foreach() to loop through just the Record messages // foreach (RecordMesg recordMesg in messages.Records) { long hrSum = 0; long hrSumCount = 0; // Obtain the time for which the record message is valid DateTime record_range_end_time = new DateTime(recordMesg.GetTimestamp()); // Need to determine timestamp range which applies to this record bool findingInRangeHrMesgs = true; // Start searching HR mesgs where we left off int hr_mesg_counter = hr_start_index; int hr_sub_mesg_counter = hr_start_sub_index; // // Update this while() to loop through just the HR messages // while (findingInRangeHrMesgs && (hr_mesg_counter < messages.HeartRates.Count)) { HrMesg hrMesg = new HrMesg(messages.HeartRates[hr_mesg_counter]); // Update HR timestamp anchor, if present if (hrMesg.GetTimestamp() != null && hrMesg.GetTimestamp().GetTimeStamp() != 0) { hr_anchor_timestamp = new DateTime(hrMesg.GetTimestamp()); hr_anchor_set = true; if (hrMesg.GetFractionalTimestamp() != null) { hr_anchor_timestamp.Add((double)hrMesg.GetFractionalTimestamp()); } if (hrMesg.GetNumEventTimestamp() == 1) { hr_anchor_event_timestamp = hrMesg.GetEventTimestamp(0); } else { throw new FitException("FIT HrToRecordMesgBroadcastPlugin Error: Anchor HR mesg must have 1 event_timestamp"); } } if (hr_anchor_set == false) { // We cannot process any HR messages if we have not received a timestamp anchor throw new FitException("FIT HrToRecordMesgBroadcastPlugin Error: No anchor timestamp received in a HR mesg before diff HR mesgs"); } else if (hrMesg.GetNumEventTimestamp() != hrMesg.GetNumFilteredBpm()) { throw new FitException("FIT HrToRecordMesgBroadcastPlugin Error: HR mesg with mismatching event timestamp and filtered bpm"); } for (int j = hr_sub_mesg_counter; j < hrMesg.GetNumEventTimestamp(); j++) { // Build up timestamp for each message using the anchor and event_timestamp DateTime hrMesgTime = new DateTime(hr_anchor_timestamp); float? event_timestamp = hrMesg.GetEventTimestamp(j); // Deal with roll over case if (event_timestamp < hr_anchor_event_timestamp) { if ((hr_anchor_event_timestamp - event_timestamp) > (1 << 21)) { event_timestamp += (1 << 22); } else { throw new FitException("FIT HrToRecordMesgBroadcastPlugin Error: Anchor event_timestamp is greater than subsequent event_timestamp. This does not allow for correct delta calculation."); } } hrMesgTime.Add((double)(event_timestamp - hr_anchor_event_timestamp)); // Check if hrMesgTime is gt record start time // and if hrMesgTime is lte to record end time if ((hrMesgTime.CompareTo(record_range_start_time) > 0) && (hrMesgTime.CompareTo(record_range_end_time) <= 0)) { hrSum += (long)hrMesg.GetFilteredBpm(j); hrSumCount++; last_valid_hr_time = new DateTime(hrMesgTime); } // check if hrMesgTime exceeds the record time else if (hrMesgTime.CompareTo(record_range_end_time) > 0) { // Remember where we left off hr_start_index = hr_mesg_counter; hr_start_sub_index = j; findingInRangeHrMesgs = false; if (hrSumCount > 0) { // Update record heart rate last_valid_hr = (byte?)System.Math.Round((((float)hrSum) / hrSumCount), System.MidpointRounding.AwayFromZero); recordMesg.SetHeartRate(last_valid_hr); messages.RecordFieldNames.Add("HeartRate"); } // If no stored HR is available, fill in record messages with the // last valid filtered hr for a maximum of 5 seconds else if ((record_range_start_time.CompareTo(last_valid_hr_time) > 0) && ((record_range_start_time.GetTimeStamp() - last_valid_hr_time.GetTimeStamp()) < 5)) { recordMesg.SetHeartRate(last_valid_hr); messages.RecordFieldNames.Add("HeartRate"); } // Reset HR average hrSum = 0; hrSumCount = 0; record_range_start_time = new DateTime(record_range_end_time); // Breaks out of looping within the event_timestamp array break; } } hr_mesg_counter++; hr_sub_mesg_counter = 0; } } }
static void OnMesg(object sender, MesgEventArgs e) { Mesg msg = e.mesg; if (msg.Num == MesgNum.Record) { RecordMesg recordMesg = new RecordMesg(msg); Console.Write("Data,{0},record,", msg.LocalNum); if (recordMesg.GetTimestamp() != null) { Console.Write("timestamp,{0},s,", recordMesg.GetTimestamp().GetTimeStamp()); } if ((recordMesg.GetDistance() != null) && (recordMesg.GetDistance() != (uint)Fit.BaseType[Fit.UInt32].invalidValue)) { Console.Write("distance, {0:0.0}, m,", recordMesg.GetDistance()); } if ((recordMesg.GetSpeed() != null) && (recordMesg.GetSpeed() != (ushort)Fit.BaseType[Fit.UInt16].invalidValue)) { Console.Write("speed,{0:0.000},m/s,", recordMesg.GetSpeed()); } if ((recordMesg.GetCadence() != null) && (recordMesg.GetCadence() != (byte)Fit.BaseType[Fit.UInt8].invalidValue)) { Console.Write("cadence,{0},rpm,", recordMesg.GetCadence()); } if ((recordMesg.GetEnhancedSpeed() != null) && (recordMesg.GetEnhancedSpeed() != (uint)Fit.BaseType[Fit.UInt32].invalidValue)) { Console.Write("enhanced_speed,{0:0.000},m/s,", recordMesg.GetEnhancedSpeed()); } if ((recordMesg.GetHeartRate() != null) && (recordMesg.GetHeartRate() != (byte)Fit.BaseType[Fit.UInt8].invalidValue)) { Console.Write("heart_rate,{0},bpm,", recordMesg.GetHeartRate()); } Console.Write("\n"); } else if (msg.Num == MesgNum.Hr) { HrMesg hrMesg = new HrMesg(msg); Console.Write("Data,{0},hr,", msg.LocalNum); int count; if ((hrMesg.GetTimestamp() != null) && (hrMesg.GetTimestamp().GetTimeStamp() != (uint)Fit.BaseType[Fit.UInt32].invalidValue)) { Console.Write("timestamp,{0},,", hrMesg.GetTimestamp().GetTimeStamp()); } if (hrMesg.GetNumFilteredBpm() > 0) { Console.Write("filtered_bpm,"); count = hrMesg.GetNumFilteredBpm(); for (int i = 0; i < count; i++) { Console.Write("{0}", hrMesg.GetFilteredBpm(i)); if (i < count - 1) { Console.Write("|"); } } Console.Write(",bpm,"); } if (hrMesg.GetNumEventTimestamp12() > 0) { Console.Write("event_timestamp_12,"); count = hrMesg.GetNumEventTimestamp12(); for (int i = 0; i < count; i++) { Console.Write("{0}", hrMesg.GetEventTimestamp12(i)); if (i < count - 1) { Console.Write("|"); } } Console.Write(",,"); } if (hrMesg.GetNumEventTimestamp() > 0) { Console.Write("event_timestamp,"); count = hrMesg.GetNumEventTimestamp(); for (int i = 0; i < count; i++) { Console.Write("{0:G}", hrMesg.GetEventTimestamp(i)); if (i < count - 1) { Console.Write("|"); } } Console.Write(",s,"); } if (hrMesg.GetFractionalTimestamp() != null) { Console.Write("fractional_timestamp,{0:0.######},s,", hrMesg.GetFractionalTimestamp()); } Console.Write("\n"); } }