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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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;
            }
        }