public static void ExportSchedulesFITFile(Stream exportStream, MemoryStream dataStream) { MemoryStream tempDataStream = new MemoryStream(); // Reserve size for header tempDataStream.Write(new Byte[12], 0, 12); // File id message FITMessage fileIdMessage = new FITMessage(FITGlobalMessageIds.FileId); FITMessageField fileType = new FITMessageField((Byte)FITFileIdFieldsIds.FileType); FITMessageField manufacturerId = new FITMessageField((Byte)FITFileIdFieldsIds.ManufacturerId); FITMessageField productId = new FITMessageField((Byte)FITFileIdFieldsIds.ProductId); FITMessageField serialNumber = new FITMessageField((Byte)FITFileIdFieldsIds.SerialNumber); FITMessageField exportDate = new FITMessageField((Byte)FITFileIdFieldsIds.ExportDate); FITMessageField number = new FITMessageField((Byte)FITFileIdFieldsIds.Number); manufacturerId.SetUInt16(1); fileType.SetEnum((Byte)FITFileTypes.Schedules); // Invalid fields productId.SetUInt16(0xFFFF); serialNumber.SetUInt32z(0); exportDate.SetUInt32(0xFFFFFFFF); number.SetUInt16(0xFFFF); fileIdMessage.AddField(serialNumber); fileIdMessage.AddField(exportDate); fileIdMessage.AddField(manufacturerId); fileIdMessage.AddField(productId); fileIdMessage.AddField(number); fileIdMessage.AddField(fileType); fileIdMessage.Serialize(tempDataStream); // Write all passed in data to output stream tempDataStream.Write(dataStream.GetBuffer(), 0, (int)dataStream.Length); // Write FIT header at the start of the stream GarminFitnessByteRange headerSize = new GarminFitnessByteRange(12); GarminFitnessByteRange protocolVersion = new GarminFitnessByteRange((Byte)((FITConstants.FITProtocolMajorVersion << 4) | FITConstants.FITProtocolMinorVersion)); GarminFitnessUInt16Range profileVersion = new GarminFitnessUInt16Range((UInt16)((FITConstants.FITProfileMajorVersion * FITConstants.FITProfileMajorVersionMultiplier) + FITConstants.FITProfileMinorVersion)); GarminFitnessInt32Range dataSize = new GarminFitnessInt32Range(0); tempDataStream.Seek(0, SeekOrigin.Begin); dataSize.Value = (int)tempDataStream.Length - 12; headerSize.Serialize(tempDataStream); protocolVersion.Serialize(tempDataStream); profileVersion.Serialize(tempDataStream); dataSize.Serialize(tempDataStream); tempDataStream.Write(Encoding.UTF8.GetBytes(FITConstants.FITFileDescriptor), 0, 4); // Write CRC GarminFitnessUInt16Range crc = new GarminFitnessUInt16Range(FITUtils.ComputeStreamCRC(tempDataStream)); tempDataStream.Seek(0, SeekOrigin.End); crc.Serialize(tempDataStream); // Write all data to output stream exportStream.Write(tempDataStream.GetBuffer(), 0, (int)tempDataStream.Length); }
public virtual void FillFITMessageForScheduledDate(FITMessage scheduleMessage, DateTime scheduledDate) { FITMessageField workoutManufacturer = new FITMessageField((Byte)FITScheduleFieldIds.WorkoutManufacturer); FITMessageField workoutProduct = new FITMessageField((Byte)FITScheduleFieldIds.WorkoutProduct); FITMessageField workoutSN = new FITMessageField((Byte)FITScheduleFieldIds.WorkoutSN); FITMessageField scheduleType = new FITMessageField((Byte)FITScheduleFieldIds.ScheduleType); FITMessageField workoutCompleted = new FITMessageField((Byte)FITScheduleFieldIds.WorkoutCompleted); FITMessageField workoutId = new FITMessageField((Byte)FITScheduleFieldIds.WorkoutId); FITMessageField scheduledField = new FITMessageField((Byte)FITScheduleFieldIds.ScheduledDate); DateTime midDaySchedule = new DateTime(scheduledDate.Date.Year, scheduledDate.Date.Month, scheduledDate.Day, 12, 0, 0); TimeSpan timeSinceReference = midDaySchedule - new DateTime(1989, 12, 31); // Hardcoded fields from the schedule file workoutManufacturer.SetUInt16(1); // Always 1 workoutProduct.SetUInt16(20119); // Always 20119 workoutSN.SetUInt32z(0); // Invalid workoutCompleted.SetEnum((Byte)0xFF); // Invalid/Not completed // Real data scheduleType.SetEnum((Byte)FITScheduleType.Workout); workoutId.SetUInt32(CreationTimestamp); scheduleMessage.AddField(workoutSN); scheduleMessage.AddField(workoutId); scheduleMessage.AddField(scheduledField); scheduleMessage.AddField(workoutManufacturer); scheduleMessage.AddField(workoutProduct); scheduleMessage.AddField(workoutCompleted); scheduleMessage.AddField(scheduleType); scheduledField.SetUInt32((UInt32)timeSinceReference.TotalSeconds); }
public void FillFITMessage(FITMessage workoutMessage) { FITMessageField capabilities = new FITMessageField((Byte)FITWorkoutFieldIds.Capabilities); FITMessageField sportType = new FITMessageField((Byte)FITWorkoutFieldIds.SportType); FITMessageField numValidSteps = new FITMessageField((Byte)FITWorkoutFieldIds.NumSteps); FITMessageField unknown = new FITMessageField((Byte)FITWorkoutFieldIds.Unknown); FITMessageField workoutName = new FITMessageField((Byte)FITWorkoutFieldIds.WorkoutName); sportType.SetEnum((Byte)Options.Instance.GetFITSport(Category)); capabilities.SetUInt32z(32); numValidSteps.SetUInt16(StepCount); unknown.SetUInt16(0xFFFF); workoutMessage.AddField(capabilities); if (!String.IsNullOrEmpty(Name)) { workoutName.SetString(Name, (Byte)(Constants.MaxNameLength + 1)); workoutMessage.AddField(workoutName); } workoutMessage.AddField(numValidSteps); workoutMessage.AddField(unknown); workoutMessage.AddField(sportType); }
public void TestFITDeserialization() { ILogbook logbook = PluginMain.GetApplication().Logbook; Workout placeholderWorkout = null; FITMessage serializedMessage = new FITMessage(FITGlobalMessageIds.Workout); FITMessageField nameField = new FITMessageField((Byte)FITWorkoutFieldIds.WorkoutName); FITMessageField numStepsField = new FITMessageField((Byte)FITWorkoutFieldIds.NumSteps); FITMessageField categoryField = new FITMessageField((Byte)FITWorkoutFieldIds.SportType); try { placeholderWorkout = WorkoutImporter.ImportWorkoutFromMessage(serializedMessage, logbook.ActivityCategories[0]); Assert.Fail("Workout without name was FIT deserialized"); } catch (FITParserException) { } nameField.SetString(String.Empty); serializedMessage.AddField(nameField); try { placeholderWorkout = WorkoutImporter.ImportWorkoutFromMessage(serializedMessage, logbook.ActivityCategories[0]); Assert.Fail("Workout without step count was FIT deserialized"); } catch (FITParserException) { } numStepsField.SetUInt16(0); serializedMessage.AddField(numStepsField); // Name nameField.SetString("TestName"); placeholderWorkout = WorkoutImporter.ImportWorkoutFromMessage(serializedMessage, logbook.ActivityCategories[0]); Assert.AreEqual("TestName", placeholderWorkout.Name, "Workout name not properly FIT deserialized"); GarminWorkoutManager.Instance.RemoveWorkout(placeholderWorkout); nameField.SetString("Workout2"); placeholderWorkout = WorkoutImporter.ImportWorkoutFromMessage(serializedMessage, logbook.ActivityCategories[0]); Assert.AreEqual("Workout2", placeholderWorkout.Name, "Workout name not properly FIT deserialized"); GarminWorkoutManager.Instance.RemoveWorkout(placeholderWorkout); // No need to test category, we ignore them in the application at this time (TODO) // Number of steps is tested in the steps list test since it requires multiple messages // Do not test steps deserialization here, it has it's own test }
public static void ExportWorkoutToFIT(IWorkout workout, Stream exportStream, bool updateExportDate) { MemoryStream dataStream = new MemoryStream(); // Reserve size for header dataStream.Write(new Byte[12], 0, 12); // File id message FITMessage fileIdMessage = new FITMessage(FITGlobalMessageIds.FileId); FITMessageField fileType = new FITMessageField((Byte)FITFileIdFieldsIds.FileType); FITMessageField manufacturerId = new FITMessageField((Byte)FITFileIdFieldsIds.ManufacturerId); FITMessageField productId = new FITMessageField((Byte)FITFileIdFieldsIds.ProductId); FITMessageField serialNumber = new FITMessageField((Byte)FITFileIdFieldsIds.SerialNumber); FITMessageField exportDate = new FITMessageField((Byte)FITFileIdFieldsIds.ExportDate); FITMessageField number = new FITMessageField((Byte)FITFileIdFieldsIds.Number); fileType.SetEnum((Byte)FITFileTypes.Workout); manufacturerId.SetUInt16(1); productId.SetUInt16(20119); serialNumber.SetUInt32z(0); exportDate.SetUInt32(workout.CreationTimestamp); number.SetUInt16(0xFFFF); fileIdMessage.AddField(serialNumber); fileIdMessage.AddField(exportDate); fileIdMessage.AddField(manufacturerId); fileIdMessage.AddField(productId); fileIdMessage.AddField(number); fileIdMessage.AddField(fileType); fileIdMessage.Serialize(dataStream); // File creator message FITMessage fileCreatorMessage = new FITMessage(FITGlobalMessageIds.FileCreator); FITMessageField software = new FITMessageField((Byte)FITFileCreatorFieldsIds.SoftwareVersion); FITMessageField hardware = new FITMessageField((Byte)FITFileCreatorFieldsIds.HardwareVersion); software.SetUInt16(3605); hardware.SetUInt8(0); fileCreatorMessage.AddField(software); fileCreatorMessage.AddField(hardware); fileCreatorMessage.Serialize(dataStream); // Write workout workout.SerializeToFIT(dataStream); // Write FIT header at the start of the stream GarminFitnessByteRange headerSize = new GarminFitnessByteRange(12); GarminFitnessByteRange protocolVersion = new GarminFitnessByteRange((Byte)((FITConstants.FITProtocolMajorVersion << 4) | FITConstants.FITProtocolMinorVersion)); GarminFitnessUInt16Range profileVersion = new GarminFitnessUInt16Range((UInt16)((FITConstants.FITProfileMajorVersion * FITConstants.FITProfileMajorVersionMultiplier) + FITConstants.FITProfileMinorVersion)); GarminFitnessInt32Range dataSize = new GarminFitnessInt32Range(0); dataStream.Seek(0, SeekOrigin.Begin); dataSize.Value = (int)dataStream.Length - 12; headerSize.Serialize(dataStream); protocolVersion.Serialize(dataStream); profileVersion.Serialize(dataStream); dataSize.Serialize(dataStream); dataStream.Write(Encoding.UTF8.GetBytes(FITConstants.FITFileDescriptor), 0, 4); // Write CRC GarminFitnessUInt16Range crc = new GarminFitnessUInt16Range(FITUtils.ComputeStreamCRC(dataStream)); dataStream.Seek(0, SeekOrigin.End); crc.Serialize(dataStream); // Write all data to output stream exportStream.Write(dataStream.GetBuffer(), 0, (int)dataStream.Length); if (updateExportDate) { workout.LastExportDate = DateTime.Now; } }
public void SerializeToFITSettings(Stream outputStream) { FITMessage userProfileMessage = new FITMessage(FITGlobalMessageIds.UserProfile); FITMessageField profileName = new FITMessageField((Byte)FITUserProfileFieldIds.FriendlyName); FITMessageField gender = new FITMessageField((Byte)FITUserProfileFieldIds.Gender); FITMessageField weight = new FITMessageField((Byte)FITUserProfileFieldIds.Weight); FITMessageField restingHR = new FITMessageField((Byte)FITUserProfileFieldIds.RestingHR); profileName.SetString(ProfileName, (Byte)(Constants.MaxNameLength + 1)); userProfileMessage.AddField(profileName); gender.SetEnum(IsMale ? (Byte)FITGenders.Male : (Byte)FITGenders.Female); userProfileMessage.AddField(gender); weight.SetUInt16((UInt16)(WeightInKilos * 10)); userProfileMessage.AddField(weight); restingHR.SetUInt8(RestingHeartRate); userProfileMessage.AddField(restingHR); userProfileMessage.Serialize(outputStream); (m_ActivityProfiles[(int)GarminCategories.Biking] as GarminBikingActivityProfile).SerializeBikeProfiles(outputStream); }
public virtual void SerializeFITZonesTarget(Stream outputStream) { FITMessage zonesTargetMessage = new FITMessage(FITGlobalMessageIds.ZonesTarget); FITMessageField maxHR = new FITMessageField((Byte)FITZonesTargetFieldIds.MaxHR); FITMessageField FTP = new FITMessageField((Byte)FITZonesTargetFieldIds.FTP); FITMessageField HRCalcType = new FITMessageField((Byte)FITZonesTargetFieldIds.HRCalcType); FITMessageField powerCalcType = new FITMessageField((Byte)FITZonesTargetFieldIds.PowerCalcType); maxHR.SetUInt8(MaximumHeartRate); FTP.SetUInt16(0); HRCalcType.SetEnum((Byte)FITHRCalcTypes.Custom); powerCalcType.SetEnum((Byte)FITPowerCalcTypes.Custom); zonesTargetMessage.AddField(maxHR); zonesTargetMessage.AddField(FTP); zonesTargetMessage.AddField(HRCalcType); zonesTargetMessage.AddField(powerCalcType); zonesTargetMessage.Serialize(outputStream); }
public virtual void SerializeFITSpeedZones(Stream outputStream) { UInt16 i = 0; foreach (GarminFitnessNamedSpeedZone zone in m_SpeedZones) { FITMessage zonesTargetMessage = new FITMessage(FITGlobalMessageIds.SpeedZones); FITMessageField index = new FITMessageField((Byte)FITSpeedZonesFieldIds.MessageIndex); FITMessageField zoneName = new FITMessageField((Byte)FITSpeedZonesFieldIds.Name); FITMessageField highSpeed = new FITMessageField((Byte)FITSpeedZonesFieldIds.HighSpeed); if (i == 0) { index.SetUInt16(i); zoneName.SetString(zone.Name, (Byte)(Constants.MaxNameLength + 1)); highSpeed.SetUInt16((UInt16)(zone.Low * 1000)); zonesTargetMessage.AddField(index); zonesTargetMessage.AddField(zoneName); zonesTargetMessage.AddField(highSpeed); zonesTargetMessage.Serialize(outputStream); zonesTargetMessage.Clear(); } index.SetUInt16((UInt16)(i + 1)); zoneName.SetString(zone.Name, (Byte)(Constants.MaxNameLength + 1)); highSpeed.SetUInt16((UInt16)(zone.High * 1000)); zonesTargetMessage.AddField(index); zonesTargetMessage.AddField(zoneName); zonesTargetMessage.AddField(highSpeed); zonesTargetMessage.Serialize(outputStream, false); ++i; } }
public virtual void SerializeFITHRZones(Stream outputStream) { UInt16 i = 0; foreach (GarminFitnessValueRange<GarminFitnessDoubleRange> zone in m_HeartRateZones) { FITMessage zonesTargetMessage = new FITMessage(FITGlobalMessageIds.HRZones); FITMessageField index = new FITMessageField((Byte)FITHRZonesFieldIds.MessageIndex); FITMessageField zoneName = new FITMessageField((Byte)FITHRZonesFieldIds.Name); FITMessageField highBPM = new FITMessageField((Byte)FITHRZonesFieldIds.HighBPM); if (i == 0) { index.SetUInt16(i); zoneName.SetString(String.Format("HR Zone {0}", i), (Byte)(Constants.MaxNameLength + 1)); highBPM.SetUInt8((Byte)(zone.Lower * MaximumHeartRate)); zonesTargetMessage.AddField(index); zonesTargetMessage.AddField(zoneName); zonesTargetMessage.AddField(highBPM); zonesTargetMessage.Serialize(outputStream); zonesTargetMessage.Clear(); } index.SetUInt16((UInt16)(i + 1)); zoneName.SetString(String.Format("HR Zone {0}", i + 1), (Byte)(Constants.MaxNameLength + 1)); highBPM.SetUInt8((Byte)(zone.Upper * MaximumHeartRate)); zonesTargetMessage.AddField(index); zonesTargetMessage.AddField(zoneName); zonesTargetMessage.AddField(highBPM); zonesTargetMessage.Serialize(outputStream, false); ++i; } }
public void SerializeBikeProfiles(Stream outputStream) { UInt16 i = 0; foreach (GarminBikeProfile bike in m_Bikes) { FITMessage bikeProfileMessage = new FITMessage(FITGlobalMessageIds.BikeProfile); FITMessageField index = new FITMessageField((Byte)FITBikeProfileFieldIds.MessageIndex); FITMessageField name = new FITMessageField((Byte)FITBikeProfileFieldIds.Name); FITMessageField odometer = new FITMessageField((Byte)FITBikeProfileFieldIds.Odometer); FITMessageField customWheelSize = new FITMessageField((Byte)FITBikeProfileFieldIds.CustomWheelSize); FITMessageField autoWheelSize = new FITMessageField((Byte)FITBikeProfileFieldIds.AutoWheelSize); FITMessageField weight = new FITMessageField((Byte)FITBikeProfileFieldIds.Weight); FITMessageField useAutoWheelSize = new FITMessageField((Byte)FITBikeProfileFieldIds.AutoWheelSetting); FITMessageField cadenceSensor = new FITMessageField((Byte)FITBikeProfileFieldIds.SpeedCadenceSensorEnabled); FITMessageField powerSensor = new FITMessageField((Byte)FITBikeProfileFieldIds.PowerSensorEnabled); index.SetUInt16(i); name.SetString(bike.Name, (Byte)(Constants.MaxNameLength + 1)); odometer.SetUInt32((UInt32)(bike.OdometerInMeters * 100)); customWheelSize.SetUInt16(bike.WheelSize); autoWheelSize.SetUInt16(bike.WheelSize); weight.SetUInt16((UInt16)Math.Round(Weight.Convert(bike.WeightInPounds, Weight.Units.Pound, Weight.Units.Kilogram) * 10, 0)); useAutoWheelSize.SetEnum(bike.AutoWheelSize ? (Byte)FITBoolean.True : (Byte)FITBoolean.False); cadenceSensor.SetEnum(bike.HasCadenceSensor ? (Byte)FITBoolean.True : (Byte)FITBoolean.False); powerSensor.SetEnum(bike.HasPowerSensor ? (Byte)FITBoolean.True : (Byte)FITBoolean.False); bikeProfileMessage.AddField(index); bikeProfileMessage.AddField(name); bikeProfileMessage.AddField(odometer); bikeProfileMessage.AddField(customWheelSize); bikeProfileMessage.AddField(autoWheelSize); bikeProfileMessage.AddField(weight); bikeProfileMessage.AddField(useAutoWheelSize); bikeProfileMessage.AddField(cadenceSensor); bikeProfileMessage.AddField(powerSensor); bikeProfileMessage.Serialize(outputStream, i == 0); ++i; } }